/*
 * The shared stylesheet: design tokens, the page container, and the
 * components every page draws from.
 *
 * Colours are tokens, never raw hex in a rule.  Each token is defined once for
 * light, then redefined for dark twice: under prefers-color-scheme (for
 * visitors who never chose) and under body[data-theme="dark"] (for those who
 * did).  A raw hex in a new rule is almost always a bug in one of the themes.
 *
 * Per-element values (a chart's colour, a progress percentage) come from the
 * template as custom properties, style="--chart-color: ...", not as a
 * generated class per value.
 *
 * A page's own stylesheet is linked from {% block page_css %} and states only
 * where it disagrees with this file.
 */

* { box-sizing: border-box; margin: 0; padding: 0; }

html { scrollbar-gutter: stable; }

/* ── Fonts ──
   Self-hosted rather than linked from a font CDN: no third-party host in the
   CSP, no request leaving for another site, and the files are cached under
   the same content hash as everything else.  Latin subsets of the variable
   fonts, OFL licensed (static/fonts/OFL.txt).  Fredoka is the rounded display
   face for headings, buttons and the name; Nunito, also rounded, is the
   reading face. */
@font-face {
    font-family: "Fredoka";
    src: url("../fonts/fredoka-latin.9591efe1be62.woff2") format("woff2");
    font-weight: 300 700;
    font-display: swap;
}
@font-face {
    font-family: "Nunito";
    src: url("../fonts/nunito-latin.166202cc391c.woff2") format("woff2");
    font-weight: 200 1000;
    font-display: swap;
}

/* ── Theme tokens ── */
:root {
    color-scheme: light dark;

    --font-display: "Fredoka", ui-rounded, "Trebuchet MS", sans-serif;
    --font-body: "Nunito", ui-rounded, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

    /* Brand: verdant green, with a sunny yellow used sparingly */
    --brand:      #1e7a46;
    --brand-d:    #155f36;
    --brand-deep: #0f4a29;
    --brand-tint: #e3f2e7;
    --accent:     #f5b83d;
    --accent-tint: #fdf1d6;

    /* Surfaces */
    --bg:        #f7f9f2;
    --surface:   #ffffff;
    --surface-2: #eef4ea;

    /* Text */
    --text:       #1f2a22;
    --text-head:  #143020;
    --text-soft:  #48574c;
    --text-muted: #667368;
    --on-brand:   #ffffff;

    /* Borders and shadows */
    --border:      #dbe5d6;
    --shadow-card: 0 1px 2px rgba(20, 48, 32, 0.06), 0 10px 24px rgba(20, 48, 32, 0.07);

    /* Inputs */
    --input-bg: #ffffff;

    /* Flash messages */
    --flash-ok-bg:    #e3f2e7;
    --flash-ok-text:  #17613a;
    --flash-err-bg:   #fdecea;
    --flash-err-text: #b71c1c;
}

@media (prefers-color-scheme: dark) {
    body:not([data-theme="light"]) {
        color-scheme: dark;
        --brand:      #6fd396;
        --brand-d:    #8ee0ac;
        --brand-deep: #3f9a64;
        --brand-tint: #17301f;
        --accent:     #f5c25a;
        --accent-tint: #33290f;
        --bg:        #0f1611;
        --surface:   #172019;
        --surface-2: #1d2920;
        --text:       #e4ebe5;
        --text-head:  #f1f6ef;
        --text-soft:  #b0bdb2;
        --text-muted: #8c998e;
        --on-brand:   #0f1611;
        --border:      #2a382d;
        --shadow-card: 0 0 0 1px rgba(255, 255, 255, 0.05);
        --input-bg: #1d2920;
        --flash-ok-bg:    #12301d;
        --flash-ok-text:  #8ee0ac;
        --flash-err-bg:   #2d0808;
        --flash-err-text: #ef9a9a;
    }
}

body[data-theme="dark"] {
    color-scheme: dark;
    --brand:      #6fd396;
    --brand-d:    #8ee0ac;
    --brand-deep: #3f9a64;
    --brand-tint: #17301f;
    --accent:     #f5c25a;
    --accent-tint: #33290f;
    --bg:        #0f1611;
    --surface:   #172019;
    --surface-2: #1d2920;
    --text:       #e4ebe5;
    --text-head:  #f1f6ef;
    --text-soft:  #b0bdb2;
    --text-muted: #8c998e;
    --on-brand:   #0f1611;
    --border:      #2a382d;
    --shadow-card: 0 0 0 1px rgba(255, 255, 255, 0.05);
    --input-bg: #1d2920;
    --flash-ok-bg:    #12301d;
    --flash-ok-text:  #8ee0ac;
    --flash-err-bg:   #2d0808;
    --flash-err-text: #ef9a9a;
}

/* ── Page ── */
body {
    background: var(--bg);
    color: var(--text);
    font-family: var(--font-body);
    font-size: 1.0625rem;
    line-height: 1.6;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

a { color: var(--brand); text-underline-offset: 0.18em; }
a:hover { color: var(--brand-d); }

.site-header, .site-footer {
    padding: 0.9rem 1.5rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
}
.site-header { border-bottom: 1px solid var(--border); background: var(--surface); }
.site-name {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    white-space: nowrap;
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 1.35rem;
    letter-spacing: -0.01em;
    color: var(--text-head);
    text-decoration: none;
}
.site-name:hover { color: var(--text-head); }
/* The sprout mark: two leaves in the brand greens and a stem, drawn inline
   so it follows the theme. */
.site-mark { width: 1.9rem; height: 1.9rem; flex-shrink: 0; }
.site-mark .leaf-a { fill: var(--brand); }
.site-mark .leaf-b { fill: var(--brand-deep); }
.site-mark .stem { stroke: var(--brand-deep); }
.site-nav { display: flex; align-items: center; gap: 1rem; font-weight: 700; }
.site-nav a { text-decoration: none; white-space: nowrap; }

.site-footer {
    margin-top: auto;
    color: var(--text-muted);
    font-size: 0.9rem;
    border-top: 1px solid var(--border);
    flex-wrap: wrap;
}
.site-footer nav { display: flex; flex-wrap: wrap; gap: 0.4rem 1.1rem; }
.site-footer a { color: var(--text-soft); }

/* The page container: one definition.  A page states only its disagreement,
   at the top of its own stylesheet. */
.content {
    width: 100%;
    max-width: 900px;
    margin: 0 auto;
    padding: 2.5rem 1.5rem;
}
@media (max-width: 600px) {
    .content { padding: 1.5rem 1rem; }
    .site-header, .site-footer { padding: 0.8rem 1rem; }
    .site-nav { gap: 0.75rem; font-size: 0.95rem; }
    .site-name { font-size: 1.2rem; gap: 0.35rem; }
    .site-mark { width: 1.6rem; height: 1.6rem; }
}

h1, h2, h3 {
    font-family: var(--font-display);
    font-weight: 600;
    color: var(--text-head);
    line-height: 1.2;
    letter-spacing: -0.01em;
}
h1 { font-size: clamp(1.9rem, 4.5vw, 2.6rem); margin-bottom: 0.75rem; }
h2 { font-size: 1.45rem; margin: 2.25rem 0 0.5rem; }
p + p { margin-top: 0.75rem; }

.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 20px;
    box-shadow: var(--shadow-card);
    padding: 1.5rem;
}

/* Buttons sit on a darker edge and press down into it: a little physical,
   like a sticker or a toy button, without leaving the brand colours. */
.button {
    display: inline-block;
    background: var(--brand);
    color: var(--on-brand);
    font-family: var(--font-display);
    font-size: 1.05rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    padding: 0.7rem 1.5rem;
    border: 0;
    border-radius: 999px;
    box-shadow: 0 4px 0 var(--brand-deep);
    text-decoration: none;
    cursor: pointer;
    transition: transform 0.08s ease, box-shadow 0.08s ease, background 0.15s ease;
}
.button:hover, .button:focus-visible { background: var(--brand-d); color: var(--on-brand); }
.button:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--brand-deep); }
.button:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }

.button[hidden] { display: none; }

/* The second choice beside a .button: the same shape, on the page colour. */
.button--quiet {
    background: var(--surface);
    color: var(--brand);
    border: 1px solid var(--border);
    box-shadow: 0 3px 0 var(--border);
    padding: 0.55rem 1.1rem;
}
.button--quiet:hover, .button--quiet:focus-visible { background: var(--surface-2); color: var(--brand); }
.button--quiet:active { box-shadow: 0 0 0 var(--border); }

/* A form button that reads as a link, for a small action like signing out
   that still has to POST. */
.link-button {
    background: none;
    border: 0;
    padding: 0;
    font: inherit;
    color: var(--brand);
    text-decoration: underline;
    cursor: pointer;
}

@media (prefers-reduced-motion: reduce) {
    .button { transition: none; }
}

/* ── Toasts (partials/_toasts.html, static/js/toasts.js) ── */
.toast-stack {
    position: fixed;
    top: calc(env(safe-area-inset-top, 0px) + 0.75rem);
    left: 50%;
    transform: translateX(-50%);
    width: min(92vw, 28rem);
    z-index: 400;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    pointer-events: none;
}
.toast {
    pointer-events: auto;
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 0.8rem 0.9rem 0.8rem 1.1rem;
    border-radius: 12px;
    font-size: 0.9rem;
    font-weight: 600;
    box-shadow: var(--shadow-card), 0 6px 20px rgba(0, 0, 0, 0.18);
    border: 1px solid color-mix(in srgb, currentColor 25%, transparent);
    /* Held back a moment and slow to settle: arriving with the page, a
       faster toast is gone from the eye before it has been read as one. */
    animation: toast-in 0.65s cubic-bezier(0.2, 0.8, 0.25, 1) 0.25s backwards;
    transition: opacity 0.25s ease, transform 0.25s ease;
}
.toast--success { background: var(--flash-ok-bg);  color: var(--flash-ok-text); }
.toast--error   { background: var(--flash-err-bg); color: var(--flash-err-text); }
.toast-text { flex: 1; min-width: 0; }
.toast-close {
    flex-shrink: 0;
    background: none;
    border: 0;
    color: inherit;
    font-size: 1.3rem;
    line-height: 1;
    padding: 0 0.2rem;
    cursor: pointer;
    opacity: 0.7;
}
.toast-close:hover, .toast-close:focus-visible { opacity: 1; }
.toast.is-leaving { opacity: 0; transform: translateY(-0.5rem); }
@keyframes toast-in {
    from { opacity: 0; transform: translateY(-1.5rem) scale(0.96); }
}
@media (prefers-reduced-motion: reduce) {
    .toast { animation: none; transition: none; }
}

/* ── Print ──
   Charts are pages with a print stylesheet, not PDFs.  The site's chrome
   never prints; anything else on a chart page that shouldn't goes in
   .no-print.  A chart page adds its own @page size. */
@media print {
    body { background: #fff; color: #000; }
    .site-header, .site-footer, .toast-stack, .no-print { display: none !important; }
}
