﻿/* ==========================================================================
   WoodlandNotes — "a naturalist's field notebook in the woods".
   Warm pressed-paper, dappled canopy light, hand-formed edges, ink field-sketch
   botanicals, handwritten marginalia. Tactile + unhurried, never a SaaS template.
   Brand anchored on Nature of Learning. Shared by the Blazor Server web app and
   the MAUI Blazor Hybrid field app — all texture is inline SVG so it works offline.
   ========================================================================== */

:root {
    /* Forest canopy (NoL-aligned, layered for depth) */
    --fn-forest-950: #14201a;
    --fn-forest-900: #1b291f;
    --fn-forest-800: #26352a;
    --fn-forest-700: #3d4e3b;   /* PRIMARY BRAND GREEN (NoL exact) */
    --fn-forest-600: #4a6147;   /* field-primary fill (AA w/ white) */
    --fn-forest-500: #5e7a59;
    --fn-moss: #6f8a5e;

    /* Leaf + sun (dappled light) */
    --fn-leaf-400: #7bc28a;
    --fn-leaf-200: #d7e8cf;
    --fn-leaf-cta: #46b93d;     /* bright delight accent — brand/CTA glyph only */
    --fn-leaf-cta-ink: #13320f;
    --fn-sun: #e8b84b;          /* warm dappled sunlight */
    --fn-sun-soft: #f3dca0;

    /* Pressed paper (kraft / field notebook) */
    --fn-paper: #f7f1e4;
    --fn-paper-2: #efe6d3;
    --fn-paper-3: #e6d8bf;
    --fn-card: #fdfaf2;
    --fn-card-edge: #efe4cd;

    /* Bark + earth */
    --fn-bark-700: #4a3727;
    --fn-bark-500: #806249;
    --fn-bark-300: #c2ab8c;

    /* Sky / stream */
    --fn-sky-600: #5a86a0;
    --fn-sky-200: #cfe0e8;

    /* Ink (warm near-black, hand-written) */
    --fn-ink-900: #211c14;
    --fn-ink-700: #322a1e;
    --fn-ink-500: #6b5d49;
    /* Secondary/muted text. Darkened to meet WCAG AA (~4.6:1) on the cream paper — the old #9a8a70 was ~2.7:1
       and failed for small text. Still visibly lighter than --fn-ink-500 for hierarchy. */
    --fn-ink-300: #756449;

    /* Safety — meaning only (golden amber). Kept for warnings/caution so those stay unambiguous. */
    --fn-amber-600: #b5760a;
    --fn-amber-200: #f6e3bd;
    --fn-red-600: #a83217;
    --fn-red-200: #f1d3cb;

    /* Ember — the ONE warm accent: firelight / autumn ochre. A DELIBERATELY redder, burnt tone so it never
       reads as the golden safety-amber above (warnings stay unmistakable). Used with discipline — primary CTAs,
       the current/active focal state, focus rings, and the single key number — never as decoration.
       AA-checked: white text on --fn-ember = 5.0:1; --fn-ember-strong as text on cream = 5.5:1. */
    --fn-ember: #b0551a;         /* accent FILL — carries cream/white text (primary buttons, active fills)   */
    --fn-ember-strong: #9a4a12;  /* pressed/hover-deep, and the accent AS TEXT on cream                       */
    --fn-ember-ink: #8f430f;     /* the one key number / accent text where maximum legibility matters         */
    --fn-ember-soft: #f4ddc1;    /* faint firelight tint — selected grounds, ring cushion                     */
    --fn-ember-glow: rgba(176,85,26,.38);  /* focus-ring halo                                                 */

    /* Hand-drawn lines on paper */
    --fn-line: #e3d6bb;
    --fn-line-strong: #d2c1a0;
    --fn-ink-line: #cdb99a;
    --fn-sketch: #7c6a4a;        /* sepia "pen" used for hand-drawn frames (with #fn-sketch filter) */
    --fn-sketch-soft: #a3906c;

    /* Type */
    --fn-font-display: "Fraunces", "Merriweather", Georgia, serif;
    --fn-font: "Inter", "Open Sans", "Segoe UI", system-ui, sans-serif;
    --fn-font-hand: "Caveat", "Bradley Hand", "Segoe Print", cursive;
    --fn-text-xs: 0.78rem;
    --fn-text-sm: 0.875rem;
    --fn-text-base: 1rem;
    --fn-text-lg: 1.15rem;
    --fn-text-xl: 1.45rem;
    --fn-text-2xl: 1.95rem;
    --fn-text-3xl: 2.7rem;

    --fn-sp-1: 0.25rem; --fn-sp-2: 0.5rem; --fn-sp-3: 0.75rem;
    --fn-sp-4: 1rem; --fn-sp-5: 1.5rem; --fn-sp-6: 2rem; --fn-sp-7: 3rem; --fn-sp-8: 4rem;

    /* Radii — clean and gentle */
    --fn-radius-sm: 9px;
    --fn-radius: 13px;
    --fn-radius-lg: 18px;
    --fn-radius-pill: 999px;

    /* Soft, warm, layered shadow (no harsh material) */
    --fn-shadow-sm: 0 1px 2px rgba(40,52,42,.05), 0 2px 6px rgba(74,55,39,.05);
    --fn-shadow: 0 2px 6px rgba(40,52,42,.06), 0 10px 26px rgba(74,55,39,.10);
    --fn-shadow-lg: 0 6px 16px rgba(20,32,26,.10), 0 24px 60px rgba(20,32,26,.18);

    --fn-tap: 56px;
    --fn-tap-xl: 72px;

    --setting-accent: var(--fn-leaf-cta);

    /* Paper grain (subtle fractal noise) */
    --fn-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
    /* Brush-stroke underline (leaf-green, for secondary buttons + text marks) */
    --fn-underline: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='14' viewBox='0 0 220 14'%3E%3Cpath d='M3 8 C40 3 70 11 110 7 C150 3 185 10 217 5' fill='none' stroke='%2346b93d' stroke-width='4' stroke-linecap='round'/%3E%3C/svg%3E");
    /* The same brush in soft firelight — swept under the ember PRIMARY button on hover (the green one clashes on ember) */
    --fn-underline-ember: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='14' viewBox='0 0 220 14'%3E%3Cpath d='M3 8 C40 3 70 11 110 7 C150 3 185 10 217 5' fill='none' stroke='%23f2c079' stroke-width='4' stroke-linecap='round'/%3E%3C/svg%3E");
    /* Faint fern motif for foliage panels */
    --fn-fern: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cg fill='none' stroke='%23ffffff' stroke-width='1.3' stroke-linecap='round' opacity='0.10'%3E%3Cpath d='M30 110 C30 70 30 40 48 22'/%3E%3Cpath d='M33 92 C20 88 13 80 12 70'/%3E%3Cpath d='M33 92 C46 86 52 78 53 68'/%3E%3Cpath d='M35 74 C23 70 17 63 16 54'/%3E%3Cpath d='M35 74 C47 69 52 62 53 53'/%3E%3Cpath d='M40 56 C30 53 25 47 24 39'/%3E%3Cpath d='M40 56 C50 52 54 46 55 38'/%3E%3C/g%3E%3C/svg%3E");
    /* Hills + trees horizon — a mask shape (fill alpha only; colour comes from the element's background) */
    --fn-hills: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='108' height='62' viewBox='0 0 108 62'%3E%3Cpath d='M0 62 C18 47 36 53 54 46 C72 39 90 48 108 42 V62Z' fill='%23000' opacity='0.5'/%3E%3Cpath d='M0 62 C22 56 42 60 62 54 C80 49 96 56 108 52 V62Z' fill='%23000'/%3E%3Cg fill='%23000'%3E%3Cpath d='M26 62 l9-23 9 23z'/%3E%3Crect x='34' y='52' width='2' height='10'/%3E%3Cpath d='M78 62 l7-18 7 18z'/%3E%3Crect x='84' y='54' width='2' height='8'/%3E%3C/g%3E%3C/svg%3E");

    /* Hand-drawn frame as a TRUE VECTOR (wavy rounded-rect path). Scales to any box via preserveAspectRatio=none;
       non-scaling-stroke keeps the line a uniform crisp weight. No raster displacement → smooth at any zoom. */
    --fn-frame: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 400' preserveAspectRatio='none'%3E%3Cpath d='M40 3 C58 1 78 5 96 3 C120 5 140 1 162 3 C184 1 200 5 218 3 C242 5 266 1 290 3 C314 5 334 1 360 3 C378 3 397 22 397 40 C399 64 395 86 397 112 C395 136 399 158 397 182 C399 206 395 228 397 252 C395 276 399 298 397 322 C397 342 396 352 397 360 C397 378 378 397 360 397 C334 399 312 395 290 397 C266 395 244 399 220 397 C198 399 174 395 150 397 C128 395 110 399 88 397 C68 395 56 399 40 397 C22 397 3 378 3 360 C1 334 5 312 3 290 C5 266 1 244 3 220 C1 198 5 174 3 150 C5 128 1 110 3 88 C3 68 4 56 3 40 C3 22 22 3 40 3 Z' fill='none' stroke='%237c6a4a' stroke-width='2.5' vector-effect='non-scaling-stroke' stroke-linejoin='round' stroke-linecap='round'/%3E%3C/svg%3E");
    --fn-frame-dashed: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 400' preserveAspectRatio='none'%3E%3Cpath d='M40 3 C58 1 78 5 96 3 C120 5 140 1 162 3 C184 1 200 5 218 3 C242 5 266 1 290 3 C314 5 334 1 360 3 C378 3 397 22 397 40 C399 64 395 86 397 112 C395 136 399 158 397 182 C399 206 395 228 397 252 C395 276 399 298 397 322 C397 342 396 352 397 360 C397 378 378 397 360 397 C334 399 312 395 290 397 C266 395 244 399 220 397 C198 399 174 395 150 397 C128 395 110 399 88 397 C68 395 56 399 40 397 C22 397 3 378 3 360 C1 334 5 312 3 290 C5 266 1 244 3 220 C1 198 5 174 3 150 C5 128 1 110 3 88 C3 68 4 56 3 40 C3 22 22 3 40 3 Z' fill='none' stroke='%237c6a4a' stroke-width='2.5' stroke-dasharray='9 7' vector-effect='non-scaling-stroke' stroke-linejoin='round' stroke-linecap='round'/%3E%3C/svg%3E");
    --fn-frame-fill: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 400' preserveAspectRatio='none'%3E%3Cpath d='M40 3 C58 1 78 5 96 3 C120 5 140 1 162 3 C184 1 200 5 218 3 C242 5 266 1 290 3 C314 5 334 1 360 3 C378 3 397 22 397 40 C399 64 395 86 397 112 C395 136 399 158 397 182 C399 206 395 228 397 252 C395 276 399 298 397 322 C397 342 396 352 397 360 C397 378 378 397 360 397 C334 399 312 395 290 397 C266 395 244 399 220 397 C198 399 174 395 150 397 C128 395 110 399 88 397 C68 395 56 399 40 397 C22 397 3 378 3 360 C1 334 5 312 3 290 C5 266 1 244 3 220 C1 198 5 174 3 150 C5 128 1 110 3 88 C3 68 4 56 3 40 C3 22 22 3 40 3 Z' fill='%23000'/%3E%3C/svg%3E");

    /* Border-image frame for CARDS — wavy rounded-rect with cream fill + sepia stroke. Used via border-image
       so the line stays a FIXED thickness with FIXED-size corners on any card width (no large-card distortion). */
    --fn-card-bi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 120 120'%3E%3Cpath d='M30 9 C48 6 66 12 90 9 C100 9 111 20 111 30 C114 48 108 66 111 90 C111 100 100 111 90 111 C66 114 48 108 30 111 C20 111 9 100 9 90 C6 66 12 48 9 30 C9 20 20 9 30 9 Z' fill='%23fdfaf2' stroke='%237c6a4a' stroke-width='4' stroke-linejoin='round' stroke-linecap='round'/%3E%3C/svg%3E");
}

/* Button "pressed-paper" fills — the SAME wavy rounded-rect as cards, baked per variant and applied via
   border-image so the corners stay a fixed crisp size at ANY width. (A scaled mask — the old approach —
   smears the wave when a button is stretched full-width; this never does.) */
:root {
    --fn-btn-bi-paper:  url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 120 120'%3E%3Cpath d='M30 9 C48 6 66 12 90 9 C100 9 111 20 111 30 C114 48 108 66 111 90 C111 100 100 111 90 111 C66 114 48 108 30 111 C20 111 9 100 9 90 C6 66 12 48 9 30 C9 20 20 9 30 9 Z' fill='%23fdfaf2' stroke='%237c6a4a' stroke-width='3.5' stroke-linejoin='round' stroke-linecap='round'/%3E%3C/svg%3E");
    --fn-btn-bi-forest: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 120 120'%3E%3Cpath d='M30 9 C48 6 66 12 90 9 C100 9 111 20 111 30 C114 48 108 66 111 90 C111 100 100 111 90 111 C66 114 48 108 30 111 C20 111 9 100 9 90 C6 66 12 48 9 30 C9 20 20 9 30 9 Z' fill='%234a6147' stroke='%232b3a28' stroke-width='3' stroke-linejoin='round' stroke-linecap='round'/%3E%3C/svg%3E");
    --fn-btn-bi-ember:  url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 120 120'%3E%3Cpath d='M30 9 C48 6 66 12 90 9 C100 9 111 20 111 30 C114 48 108 66 111 90 C111 100 100 111 90 111 C66 114 48 108 30 111 C20 111 9 100 9 90 C6 66 12 48 9 30 C9 20 20 9 30 9 Z' fill='%23b0551a' stroke='%23833c0d' stroke-width='3' stroke-linejoin='round' stroke-linecap='round'/%3E%3C/svg%3E");
    --fn-btn-bi-red:    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 120 120'%3E%3Cpath d='M30 9 C48 6 66 12 90 9 C100 9 111 20 111 30 C114 48 108 66 111 90 C111 100 100 111 90 111 C66 114 48 108 30 111 C20 111 9 100 9 90 C6 66 12 48 9 30 C9 20 20 9 30 9 Z' fill='%23a83217' stroke='%237e2410' stroke-width='3' stroke-linejoin='round' stroke-linecap='round'/%3E%3C/svg%3E");
    --fn-btn-bi-muted:  url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 120 120'%3E%3Cpath d='M30 9 C48 6 66 12 90 9 C100 9 111 20 111 30 C114 48 108 66 111 90 C111 100 100 111 90 111 C66 114 48 108 30 111 C20 111 9 100 9 90 C6 66 12 48 9 30 C9 20 20 9 30 9 Z' fill='%23efe6d3' stroke='%23cdb99a' stroke-width='3' stroke-linejoin='round' stroke-linecap='round'/%3E%3C/svg%3E");
}

/* High-contrast accessibility mode. Previously this barely moved — a near-invisible delta. It's now a
   The palette runs deep BY DEFAULT: greens and inks toward pine/near-black, the ember dark enough to clear AA+
   on cream, and firm hand-drawn hairlines so card/table/input edges read cleanly. (This was a toggled
   high-contrast mode; adopted as the standard look — the difference didn't warrant a separate control. A later
   :root block deliberately overrides the base tokens above.) */
:root {
    --fn-forest-950: #0b130e; --fn-forest-900: #111b14; --fn-forest-800: #16231a;
    --fn-forest-700: #24371f; --fn-forest-600: #1f3d22; --fn-forest-500: #2e492a;
    --fn-ink-900: #16120b; --fn-ink-700: #241d12; --fn-ink-500: #322c20; --fn-ink-300: #463a26;
    --fn-red-600: #871403; --fn-amber-600: #8a4a00;
    /* deepen the accent too, so ember text/fills stay AA+ in this mode */
    --fn-ember: #8f3d0c; --fn-ember-strong: #7c340a; --fn-ember-ink: #7c340a;
    --fn-ember-glow: rgba(124,52,10,.5);
    /* firm hairlines — the biggest single readability win for cards, tables and inputs */
    --fn-line: #c9b391; --fn-line-strong: #a08a63; --fn-ink-line: #a08a63; --fn-card-edge: #d6c4a0;
}
/* Re-bake the ember button fill to match the deepened palette (border-image URLs can't read a var). */
:root {
    --fn-btn-bi-ember: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 120 120'%3E%3Cpath d='M30 9 C48 6 66 12 90 9 C100 9 111 20 111 30 C114 48 108 66 111 90 C111 100 100 111 90 111 C66 114 48 108 30 111 C20 111 9 100 9 90 C6 66 12 48 9 30 C9 20 20 9 30 9 Z' fill='%238f3d0c' stroke='%23632a07' stroke-width='3.2' stroke-linejoin='round' stroke-linecap='round'/%3E%3C/svg%3E");
}

* { box-sizing: border-box; }

html, body {
    margin: 0; padding: 0;
    font-family: var(--fn-font);
    font-size: var(--fn-text-base); line-height: 1.55;
    color: var(--fn-ink-700);
    background-color: var(--fn-paper);
    /* dappled canopy light — layered soft radials over warm paper */
    background-image:
        radial-gradient(120% 85% at 88% -8%, rgba(232,184,75,.16), transparent 55%),
        radial-gradient(90% 70% at -10% 8%, rgba(94,122,89,.14), transparent 55%),
        radial-gradient(70% 60% at 50% 120%, rgba(61,78,59,.10), transparent 60%);
    background-attachment: fixed;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}
/* paper grain overlay */
body::before {
    content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 9999;
    background-image: var(--fn-grain); background-size: 200px 200px;
    opacity: .07; mix-blend-mode: multiply;
}

h1, h2, h3, h4 {
    font-family: var(--fn-font-display);
    color: var(--fn-forest-900); line-height: 1.1; font-weight: 600;
    margin: 0 0 var(--fn-sp-3); letter-spacing: -0.015em;
    font-optical-sizing: auto;
}
/* h1 anchors on the deepest pine (not the mid-900) so the page has a genuine dark top-note against the cream —
   part of widening the tonal range so the palette reads with depth rather than one flat mid-green. */
h1 { font-size: var(--fn-text-3xl); font-weight: 600; line-height: 1.16; padding-top: 0.04em; color: var(--fn-forest-950); }
h2 { font-size: var(--fn-text-2xl); }
h3 { font-size: var(--fn-text-xl); }

/* hand-drawn brush underline accent */
.underline-leaf { position: relative; display: inline-block; }
.underline-leaf::after {
    content: ""; position: absolute; left: 0; right: -6px; bottom: -10px; height: 12px;
    background: var(--fn-underline) no-repeat; background-size: 100% 100%;
}

/* the same hand-drawn brush, sized to highlight a word/phrase inline in body copy */
.mark-leaf { position: relative; display: inline-block; font-weight: 600; color: inherit; }
.mark-leaf::after {
    content: ""; position: absolute; left: -2px; right: -4px; bottom: -3px; height: 7px;
    background: var(--fn-underline) no-repeat; background-size: 100% 100%;
}

a { color: var(--fn-forest-700); text-decoration: none; }
a:hover { color: var(--fn-forest-500); text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 3px; }

p { margin: 0 0 var(--fn-sp-4); }
.muted { color: var(--fn-ink-500); }
.small { font-size: var(--fn-text-sm); }
.lede { font-size: var(--fn-text-lg); color: var(--fn-ink-700); }
.hand { font-family: var(--fn-font-hand); font-size: 1.35em; line-height: 1; color: var(--fn-forest-600); }

/* ---------- Buttons — "pressed paper" --------------------------------------------------------------
   The hand-drawn wavy edge (same shape as cards) via border-image: corners stay crisp at ANY width, so a
   full-width CTA no longer smears. Tactile physics: the button sits RAISED off the paper and SINKS when
   pressed; a bright leaf brush-underline sweeps in on hover; disabled is clearly inert (flat + muted), not
   just faded. The fill is a per-variant CSS var (--fn-btn-bi) so variants only swap one token. ------------- */
.btn {
    position: relative; isolation: isolate;
    display: inline-flex; align-items: center; justify-content: center; gap: var(--fn-sp-2);
    min-height: 50px; padding: 10px var(--fn-sp-5); line-height: 1.2;
    font: inherit; font-weight: 600;
    background: transparent; border: none; color: var(--fn-forest-800); cursor: pointer;
    --fn-btn-bi: var(--fn-btn-bi-paper);   /* default = secondary (cream fill, sepia hand-drawn edge) */
    /* raised off the paper — drop-shadow follows the wavy alpha edge (box-shadow would be a rectangle) */
    filter: drop-shadow(0 2px 2px rgba(40,52,42,.10)) drop-shadow(0 5px 11px rgba(74,55,39,.11));
    transition: transform .12s cubic-bezier(.2,.8,.3,1), filter .15s ease, color .15s ease;
}
/* the wavy fill+edge — border-image keeps fixed corners (no scale-smear) */
.btn::before {
    content: ""; position: absolute; inset: 0; z-index: -2; pointer-events: none;
    border: 14px solid transparent;
    border-image: var(--fn-btn-bi) 30 fill / 14px / 0 stretch;
    transition: filter .15s ease;
}
/* the leaf brush-underline, swept in on hover */
.btn::after {
    content: ""; position: absolute; left: 16%; right: 16%; bottom: 8px; height: 6px; z-index: -1;
    background: var(--fn-underline) no-repeat; background-size: 100% 100%;
    transform: scaleX(0); transform-origin: center; opacity: 0;
    transition: transform .22s cubic-bezier(.2,.8,.3,1), opacity .16s ease;
    pointer-events: none;
}
.btn:hover { transform: translateY(-1.5px); filter: drop-shadow(0 3px 4px rgba(40,52,42,.12)) drop-shadow(0 10px 20px rgba(74,55,39,.15)); }
.btn:hover::before { filter: brightness(1.04); }
.btn:hover::after { transform: scaleX(1); opacity: .95; }
.btn:active { transform: translateY(1px); filter: drop-shadow(0 1px 1px rgba(40,52,42,.10)); }   /* sinks in */
.btn:active::before { filter: brightness(.95); }
.btn:active::after { opacity: 0; }
/* The accent focus ring — a crisp ember outline with a soft firelight cushion. One consistent, high-visibility
   focus treatment shared by every interactive control (see the :focus-visible rules further down that reuse it). */
.btn:focus-visible { outline: 3px solid var(--fn-ember); outline-offset: 3px; box-shadow: 0 0 0 6px var(--fn-ember-glow); }
.btn:disabled, .btn[disabled] {
    cursor: not-allowed; color: var(--fn-ink-300);
    --fn-btn-bi: var(--fn-btn-bi-muted);
    filter: none; transform: none;   /* clearly inert: flat on the paper, muted ink */
}
.btn:disabled::after, .btn[disabled]::after { display: none; }

/* ---- The three action tiers ------------------------------------------------------------------------
   TIER 1  .btn-primary — the ONE main action per view. Ember (firelight) fill so the primary reads as the
           warm focal point against the green-and-cream world. Rare by design; that's what keeps it a signal.
   TIER 2  .btn (default) — pressed-paper cream fill, sepia hand-drawn edge, forest-ink label. Supporting
           actions; there can be several.
   TIER 3  .btn-ghost / .link-btn — no fill, forest text, quiet hover wash. Low-emphasis / inline.
   .btn-danger sits OUTSIDE the tiers: red = destructive/incident meaning, never "primary".
   All four share the identical hover-rise / press-sink / disabled-inert physics and the ember focus ring. */
.btn-primary { color: #fff6ec; --fn-btn-bi: var(--fn-btn-bi-ember); }
.btn-primary::after { background-image: var(--fn-underline-ember); }   /* firelight sweep, not the green leaf */
.btn-danger  { color: #fff;    --fn-btn-bi: var(--fn-btn-bi-red); }
.btn-danger::after { display: none; }   /* the green leaf clashes on red */

.btn-ghost { color: var(--fn-forest-700); filter: none; }
.btn-ghost::before, .btn-ghost::after { display: none; }
.btn-ghost:hover { background: rgba(74,97,71,.09); border-radius: var(--fn-radius); transform: none; filter: none; }

/* An <a class="btn"> is a BUTTON, not a link — but `a:hover` above (green + underline) carries an element +
   pseudo-class, so it OUT-SPECIFIES the tier colours here and repaints the label mid-hover: a white-on-ember
   primary turned green-on-ember with a line through it. Restate each tier for anchors so a link-styled button
   hovers like a button. */
a.btn:hover, a.btn:focus { text-decoration: none; }
a.btn, a.btn:hover { color: var(--fn-forest-800); }
a.btn-primary, a.btn-primary:hover { color: #fff6ec; }
a.btn-danger, a.btn-danger:hover { color: #fff; }
a.btn-ghost, a.btn-ghost:hover { color: var(--fn-forest-700); }

.btn--xl { min-height: 56px; width: 100%; font-size: var(--fn-text-lg); }
.link-btn { background: none; border: none; padding: 0; cursor: pointer; color: var(--fn-forest-700); font: inherit; text-decoration: underline; text-underline-offset: 3px; }

/* ---------- Cards (pressed paper, hand-drawn ink frame) ---------- */
.card {
    position: relative; isolation: isolate; background: transparent; padding: var(--fn-sp-5);
}
/* the wavy frame + cream fill come from a border-image on a pseudo: FIXED line thickness & corner size at
   any card width (large cards no longer over-wave or flatten). drop-shadow follows the wavy shape. */
.card::before {
    content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
    border: 15px solid transparent;
    border-image: var(--fn-card-bi) 30 fill / 15px / 0 stretch;
    filter: drop-shadow(0 3px 7px rgba(40,52,42,.10));
}
.card--hero::before { filter: drop-shadow(0 5px 12px rgba(40,52,42,.13)); }
/* same wavy border-image frame on the other big boxed surfaces (login card, dashboard setup card) */
.auth-card, .setup-card { background: transparent !important; border: none !important; box-shadow: none !important; position: relative; isolation: isolate; }
.auth-card::before, .setup-card::before {
    content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
    border: 15px solid transparent; border-image: var(--fn-card-bi) 30 fill / 15px / 0 stretch;
    filter: drop-shadow(0 4px 9px rgba(40,52,42,.11));
}
.card-title { font-family: var(--fn-font-display); color: var(--fn-forest-900); font-size: var(--fn-text-lg); margin: 0 0 var(--fn-sp-2); }

/* ---------- Chips ----------
   Small status/label TAGS by default (a 40px pill reads as a button and bloats table rows). Interactive
   chips — <button class="chip"> and selectable .chip-grid items — opt back into a tappable target below. */
.chip {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 3px 10px; border-radius: var(--fn-radius-pill);
    background: var(--fn-paper-2); border: 1px solid var(--fn-line-strong);
    color: var(--fn-forest-800); font-size: var(--fn-text-xs); font-weight: 600; line-height: 1.35; white-space: nowrap;
}
.chip--ok { background: var(--fn-leaf-200); border-color: var(--fn-leaf-400); color: #2f5a2c; }
.chip--warn { background: var(--fn-amber-200); border-color: var(--fn-amber-600); color: #6a4604; }
.chip--danger { background: var(--fn-red-200); border-color: var(--fn-red-600); color: var(--fn-red-600); }
button.chip, .chip-grid .chip { min-height: 40px; padding: 0 14px; font-size: var(--fn-text-sm); cursor: pointer; }

/* ---------- Consent badge ---------- */
.consent-badge { display: inline-flex; align-items: center; gap: 6px; padding: 3px 11px; border-radius: var(--fn-radius-pill); font-size: var(--fn-text-xs); font-weight: 700; }
.consent-badge::before { content: ""; width: 8px; height: 8px; border-radius: 50%; }
.consent-badge--ok { background: var(--fn-leaf-200); color: var(--fn-forest-800); }
.consent-badge--ok::before { background: var(--fn-leaf-cta); }
.consent-badge--no { background: var(--fn-red-200); color: var(--fn-red-600); }
.consent-badge--no::before { background: var(--fn-red-600); }

/* ---------- Stats (hand-circled numbers) ---------- */
.stat-row { display: flex; flex-wrap: wrap; gap: var(--fn-sp-4); margin: var(--fn-sp-5) 0; }
.stat {
    position: relative; display: block; background: var(--fn-card);
    border: 1.5px solid var(--fn-card-edge); border-radius: var(--fn-radius);
    padding: var(--fn-sp-4) var(--fn-sp-5); min-width: 132px; box-shadow: var(--fn-shadow-sm);
    transition: transform .14s ease, box-shadow .2s ease; text-decoration: none;
}
.stat:hover { transform: translateY(-2px) rotate(-.4deg); box-shadow: var(--fn-shadow); text-decoration: none; }
.stat-num { display: block; font-family: var(--fn-font-display); font-size: var(--fn-text-3xl); color: var(--fn-forest-700); line-height: 1; }
/* Shared with the register ratio readout (a full sentence) — keep it clean readable sans, not uppercase. */
.stat-label { display: block; font-family: var(--fn-font); font-size: var(--fn-text-sm); color: var(--fn-ink-500); margin-top: 4px; }

/* ---- Home dashboard stat cards: icon badge + number + label, of a piece with the session screen's cards. ---- */
.hstat-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: .7rem; margin: var(--fn-sp-5) 0; }
.hstat { position: relative; overflow: hidden; display: flex; flex-direction: column; align-items: flex-start; gap: .1rem;
    background: var(--fn-card); border: 1.5px solid var(--fn-card-edge); border-radius: var(--fn-radius);
    padding: .9rem .95rem; box-shadow: var(--fn-shadow-sm); text-decoration: none;
    transition: transform .14s ease, box-shadow .2s ease, border-color .14s ease; }
.hstat:hover { transform: translateY(-2px); box-shadow: var(--fn-shadow); border-color: var(--fn-leaf-400); text-decoration: none; }
/* The icon sits large and faint in the card's right edge (a background motif), so the colour is a calm pop
   rather than a loud wash — three counts that read as a quiet, cohesive glance, not a rainbow. */
.hstat-ic { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); z-index: 0; opacity: .12; pointer-events: none; }
.hstat-num { position: relative; z-index: 1; font-family: var(--fn-font-display); font-size: var(--fn-text-3xl); line-height: 1; color: var(--fn-forest-800); }
.hstat--children .hstat-ic { color: var(--fn-forest-600); }
.hstat--sessions .hstat-ic { color: var(--fn-sky-600); }
.hstat--ras .hstat-ic { color: var(--fn-amber-600); }
.hstat-label { position: relative; z-index: 1; font-family: var(--fn-font); font-size: var(--fn-text-xs); font-weight: 700; text-transform: uppercase;
    letter-spacing: .05em; color: var(--fn-ink-500); margin-top: 3px; line-height: 1.15; }
/* On phone widths the 3 cards are narrow — shrink the label so the long "Risk assessments" wraps to two
   clean lines instead of clipping. (Desktop keeps the full size: the cards are roomy there.) */
@media (max-width: 560px) { .hstat-label { font-size: 10.5px; letter-spacing: .02em; } }
@media (max-width: 360px) { .hstat-label { font-size: 10px; } .hstat { padding: .8rem .7rem; } }

/* ---------- Banners ---------- */
.banner { padding: var(--fn-sp-3) var(--fn-sp-4); border-radius: var(--fn-radius); font-weight: 600; }
.banner--offline { background: var(--fn-bark-500); color: #fff; }
.banner--warn { background: var(--fn-amber-200); color: #6a4604; }
.banner--danger { background: var(--fn-red-600); color: #fff; }
.banner--ok { background: var(--fn-leaf-200); color: var(--fn-forest-900); }
.banner--info { background: var(--fn-paper-2); color: var(--fn-ink-700); font-weight: 500; }

/* ---------- Sync pill ---------- */
.sync-pill { display: inline-flex; align-items: center; gap: 8px; padding: 6px 14px; border-radius: var(--fn-radius-pill); background: var(--fn-paper-2); border: 1.5px solid var(--fn-line-strong); font-size: var(--fn-text-sm); font-weight: 600; }
.sync-pill::before { content: ""; width: 9px; height: 9px; border-radius: 50%; background: var(--fn-ink-300); }
.sync-pill--synced::before { background: var(--fn-leaf-cta); box-shadow: 0 0 0 3px var(--fn-leaf-200); }
.sync-pill--offline::before { background: var(--fn-bark-500); }
.sync-pill--pending::before { background: var(--fn-amber-600); }

/* ---------- Forms ---------- */
label { display: block; font-weight: 600; color: var(--fn-forest-800); margin-bottom: var(--fn-sp-4); }
/* Paired fields sit side-by-side with breathing room and wrap cleanly on a phone (no butting). */
.field-row { display: flex; gap: var(--fn-sp-3); flex-wrap: wrap; }
.field-row > label { flex: 1 1 12rem; }
input:not([type]), input[type=text], input[type=email], input[type=password], input[type=search],
input[type=number], input[type=date], input[type=time], input[type=tel], select, textarea {
    display: block; width: 100%; margin-top: 6px; min-height: 46px; padding: 10px 14px;
    font: inherit; line-height: 1.4; color: var(--fn-ink-900); background: var(--fn-paper);
    border: 1.5px solid var(--fn-line-strong); border-radius: var(--fn-radius-sm);
    transition: border-color .15s ease, box-shadow .15s ease, background .15s ease;
}
textarea { padding: 11px 14px; min-height: 5rem; line-height: 1.5; resize: vertical; }
/* Selects read as soft pills with a hand-drawn chevron — friendlier than the OS dropdown. */
select {
    appearance: none; -webkit-appearance: none; -moz-appearance: none;
    border-radius: var(--fn-radius-pill); padding-left: 18px; padding-right: 42px; cursor: pointer;
    background-color: var(--fn-paper);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%233d4e3b' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right 16px center; background-size: 14px;
}
select::-ms-expand { display: none; }
::placeholder { color: var(--fn-ink-300); opacity: 1; }
input:focus, select:focus, textarea:focus { outline: none; background-color: var(--fn-card); border-color: var(--fn-forest-500); box-shadow: 0 0 0 4px var(--fn-leaf-200); }
.validation-message, .field-validation-error { color: var(--fn-red-600); font-size: var(--fn-text-sm); }

/* ---- Signature capture (SignaturePad) — drawn / uploaded / confirm ---- */
.sigpad { display: flex; flex-direction: column; gap: .55rem; }
.sigpad-statement { font-weight: 600; color: var(--fn-forest-800); margin: 0; }
/* Name + the how-you-sign switch on one row (the switch to the right), wrapping to two when narrow. */
.sigpad-top { display: flex; align-items: flex-end; gap: .75rem; flex-wrap: wrap; }
.sigpad-name { margin: 0; flex: 1 1 220px; min-width: 0; }
.sigpad-tabs { display: inline-flex; gap: 4px; background: var(--fn-leaf-200); border-radius: var(--fn-radius-pill); padding: 3px; align-self: flex-start; flex: 0 0 auto; }
/* In the row, the switch sits on the input's baseline, not floated to the top of it. */
.sigpad-top .sigpad-tabs { align-self: auto; }
.sigpad-tab { border: none; background: transparent; font: inherit; font-weight: 600; color: var(--fn-forest-800);
    padding: .35rem .9rem; border-radius: var(--fn-radius-pill); cursor: pointer; }
.sigpad-tab.is-active { background: var(--fn-card); box-shadow: var(--fn-shadow-sm); }
.sigpad-canvas-wrap { position: relative; }
.sigpad-canvas { width: 100%; height: 170px; background: #fff; border: 1.5px dashed var(--fn-line-strong);
    border-radius: var(--fn-radius-sm); touch-action: none; display: block; }
.sigpad-clear { position: absolute; top: 8px; right: 8px; border: 1px solid var(--fn-line-strong);
    background: rgba(255,255,255,.85); border-radius: var(--fn-radius-sm); font: inherit; font-size: .82rem;
    padding: .2rem .6rem; cursor: pointer; color: var(--fn-ink-500); }
.sigpad-hint { color: var(--fn-ink-300); font-size: var(--fn-text-sm, .85rem); margin: 0; }
.sigpad-upload { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }
.sigpad-upload-prev { max-width: 220px; max-height: 110px; background: #fff; border: 1px solid var(--fn-line);
    border-radius: var(--fn-radius-sm); padding: 4px; }
.sigpad-error { color: var(--fn-red-600); font-size: var(--fn-text-sm, .85rem); margin: 0; }
.sigpad .btn-primary { align-self: flex-start; }

/* A captured signature shown back (read view): the image with who/when underneath. */
.sig-shown { display: inline-flex; flex-direction: column; gap: 2px; }
.sig-shown img { max-width: 240px; max-height: 110px; background: #fff; border: 1px solid var(--fn-line);
    border-radius: var(--fn-radius-sm); padding: 4px; }
.sig-shown .sig-meta { color: var(--fn-ink-500); font-size: var(--fn-text-sm, .85rem); }

/* ---------- App shell ---------- */
/* The nav belongs to the content, not to the window: cap the shell and centre the pair, so on a wide monitor
   the nav stays shoulder-to-shoulder with the column instead of being stranded at the far edge. Below 1570px
   this is inert — the shell is simply full width, exactly as it was.
   The shell paper and the body paper are the SAME colour, so without an edge the app just dissolves into the
   background on the right and hard-stops on the left. The hairline + lift make it read as a page laid ON the
   woodland, which is why it needs no colour change (the sidebar's torn teeth dissolve into that same paper). */
.fn-shell { display: flex; min-height: 100vh; max-width: 1570px; margin-inline: auto; }
@media (min-width: 1571px) {
    .fn-shell { box-shadow: 0 0 0 1px var(--fn-line), var(--fn-shadow-lg); }
    /* Light falls through the canopy onto the middle of the page: the edges of the window sit in shade, so the
       centred shell reads as lit rather than as a rectangle that merely stopped. */
    body::after {
        content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
        background: radial-gradient(115% 85% at 50% 40%, transparent 52%, rgba(38,52,36,.13) 100%);
    }
}
/* STICKY, with its own scroll. It used to be an ordinary tall column in the flex row, so scrolling a long page
   scrolled the navigation off the top with it — you'd reach the foot of a session and have no way out of it.
   `align-self: flex-start` is the bit that matters: without it the flex row stretches the sidebar to the full
   page height and sticky has nothing left to do.
   The scroll lives on the INNER box, not here. The fern and the torn edge are the sidebar's skin, painted as
   its pseudo-elements — and an absolutely-positioned pseudo-element inside a scroll container is part of the
   scrolled content: it spans only the client box, slides up with the nav, and the scrollbar gutter shoves it
   in from the right edge. That's the wobbly edge coming adrift: teeth floating inside the nav with a strip of
   green beyond them. Give the scroll to a child and the skin stays pinned to the sidebar. */
.fn-sidebar {
    position: sticky; top: 0; align-self: flex-start;
    height: 100vh; height: 100dvh;
    width: 250px; flex: 0 0 250px;
    background:
        radial-gradient(120% 50% at 50% -10%, rgba(232,184,75,.18), transparent 55%),
        linear-gradient(185deg, var(--fn-forest-800) 0%, var(--fn-forest-900) 55%, var(--fn-forest-950) 100%);
    color: #eef3ea;
    display: flex; flex-direction: column;
}
/* `min-height: 0` is what lets this shrink inside the flex column and actually scroll instead of pushing the
   sidebar taller. No visible scrollbar: its gutter would cut straight through the torn teeth, and it would
   narrow the nav by the gutter width the moment the window got short — .fn-sidebar-more is the affordance
   instead. */
.fn-sidebar-scroll {
    position: relative; z-index: 1;
    flex: 1 1 auto; min-height: 0;
    padding: var(--fn-sp-5) var(--fn-sp-3) var(--fn-sp-6);
    display: flex; flex-direction: column; gap: 2px;
    overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain;
    scrollbar-width: none;
}
.fn-sidebar-scroll::-webkit-scrollbar { width: 0; height: 0; }
/* faint fern foliage + torn organic right edge */
.fn-sidebar::before { content: ""; position: absolute; inset: 0; background-image: var(--fn-fern); background-size: 120px 120px; opacity: .5; pointer-events: none; }
.fn-sidebar::after {
    content: ""; position: absolute; top: 0; bottom: 0; right: -1px; width: 14px;
    /* Paint the torn teeth with the SAME viewport-fixed canopy-light gradient as <body>,
       so they dissolve seamlessly into the page. A flat --fn-paper fill here left a faint
       vertical seam where it met the body's greenish top-left radial (at -10% 8%). */
    background-color: var(--fn-paper);
    background-image:
        radial-gradient(120% 85% at 88% -8%, rgba(232,184,75,.16), transparent 55%),
        radial-gradient(90% 70% at -10% 8%, rgba(94,122,89,.14), transparent 55%),
        radial-gradient(70% 60% at 50% 120%, rgba(61,78,59,.10), transparent 60%);
    background-attachment: fixed;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='80' preserveAspectRatio='none' viewBox='0 0 14 80'%3E%3Cpath d='M14 0 H6 C10 12 2 16 6 28 C9 38 1 42 5 54 C8 64 2 70 7 80 H14 Z' fill='black'/%3E%3C/svg%3E") repeat-y left/14px 80px;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='80' preserveAspectRatio='none' viewBox='0 0 14 80'%3E%3Cpath d='M14 0 H6 C10 12 2 16 6 28 C9 38 1 42 5 54 C8 64 2 70 7 80 H14 Z' fill='black'/%3E%3C/svg%3E") repeat-y left/14px 80px;
}
.fn-brand { position: relative; z-index: 1; display: flex; align-items: center; gap: 11px; font-family: var(--fn-font-display); font-weight: 600; font-size: var(--fn-text-xl); color: #fff; padding: 0 var(--fn-sp-2) var(--fn-sp-5); }
.fn-brand svg { width: 40px; height: 40px; flex: none; }
.fn-nav { position: relative; z-index: 1; display: flex; flex-direction: column; gap: 2px; }
.fn-nav a { display: flex; align-items: center; gap: 12px; padding: 13px 14px; border-radius: var(--fn-radius-pill); color: #d4dfce; font-weight: 600; text-decoration: none; transition: background .15s ease, color .15s ease; }
.fn-nav a svg { width: 20px; height: 20px; flex: none; opacity: .85; }
.fn-nav a:hover { background: rgba(255,255,255,.06); color: #fff; text-decoration: none; }
/* Selected = a clean even pill + a brightened icon. No left bar — it doubled up with the pill and read clumsily. */
.fn-nav a.active { background: rgba(70,185,61,.16); color: #fff; }
.fn-nav a.active svg { opacity: 1; color: var(--fn-leaf-cta); }
.fn-nav a { position: relative; }
.fn-nav-section { position: relative; z-index: 1; font-family: var(--fn-font-hand); font-size: 1.05rem; letter-spacing: .02em; color: #a9bba0; margin: var(--fn-sp-4) var(--fn-sp-3) 2px; }

/* A short window CONDENSES the nav rather than scrolling it. A nav you have to scroll to discover Reports in is
   a nav hiding half of itself, and on a 768px-tall laptop we were overflowing by only a row or two — so the rows
   give up air, and no item goes away. Keyed on height alone: this is about how tall the window is, nothing else. */
@media (max-height: 900px) {
    .fn-sidebar-scroll { padding-top: var(--fn-sp-4); padding-bottom: var(--fn-sp-4); }
    .fn-brand { padding-bottom: var(--fn-sp-3); }
    .fn-nav a { padding: 10px 14px; }
    .fn-nav-section { margin-top: var(--fn-sp-3); }
}
@media (max-height: 780px) {
    .fn-brand { font-size: var(--fn-text-lg); padding-bottom: var(--fn-sp-2); }
    .fn-brand svg { width: 34px; height: 34px; }
    .fn-nav a { padding: 8px 14px; }
    .fn-nav a svg { width: 19px; height: 19px; }
    .fn-nav-section { margin-top: var(--fn-sp-2); font-size: 1rem; }
}

/* "More below" — a fade and a chevron over the foot of the nav. Invisible by default and revealed by `is-shown`,
   which nav-more.js sets only while something is genuinely below the fold, so a browser that never runs the
   script shows no hint at all rather than a hint pointing at nothing. It stops short of the torn edge (right:
   13px) — the teeth are the sidebar's edge and nothing paints over them. */
.fn-sidebar-more {
    position: absolute; left: 0; right: 13px; bottom: 0; height: 76px; z-index: 2;
    display: flex; align-items: flex-end; justify-content: center; padding-bottom: 7px;
    pointer-events: none; color: #cddcc4;
    background: linear-gradient(to top,
        var(--fn-forest-950) 20%,
        color-mix(in srgb, var(--fn-forest-950) 72%, transparent) 55%,
        transparent);
    opacity: 0; transition: opacity .2s ease;
}
.fn-sidebar-more.is-shown { opacity: 1; }
.fn-sidebar-more svg { width: 18px; height: 18px; animation: fn-nav-bob 1.9s ease-in-out infinite; }
@keyframes fn-nav-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(3px); } }
@media (prefers-reduced-motion: reduce) { .fn-sidebar-more svg { animation: none; } }

.fn-main { flex: 1 1 auto; display: flex; flex-direction: column; min-width: 0; }
.fn-topbar { display: flex; align-items: center; justify-content: flex-end; gap: var(--fn-sp-4); height: 62px; padding: 0 var(--fn-sp-6); background: rgba(253,250,242,.7); backdrop-filter: blur(6px); border-bottom: 1.5px solid var(--fn-line); }
.fn-topbar .me { color: var(--fn-ink-500); font-size: var(--fn-text-sm); }
/* fill-mode `backwards` (not `both`): the rise-in entrance plays, but afterwards .fn-content reverts to NO
   transform. With `both` it permanently held the end transform, becoming a containing block that trapped the
   fixed-position session sheet/scrim (sheet fell off-screen, scrim covered only part). */
/* The content column is centred in the space beside the nav — the same gravity the session hub uses, so home
   and session read as one app. Left-alignment only earns its keep when something occupies the space on the
   right; a page that has such a thing opts into .fn-content--rail (content + aside) instead. */
.fn-content { padding: var(--fn-sp-6) var(--fn-sp-7); max-width: 1320px; width: 100%; margin-inline: auto; animation: rise-in .5s cubic-bezier(.2,.8,.3,1) backwards; }
.fn-content--rail { display: grid; gap: var(--fn-sp-6); align-items: start; }
@media (min-width: 1180px) { .fn-content--rail { grid-template-columns: minmax(0, 1fr) 320px; } }
.logout-form { display: inline; }

/* ---------- Auth / woodland scene ---------- */
.auth-scene { position: relative; min-height: 100vh; display: grid; place-items: center; padding: var(--fn-sp-5); overflow: hidden; }
.auth-scene .scene { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0; }
.auth-card {
    position: relative; z-index: 2; width: 100%; max-width: 430px;
    background: var(--fn-card); border: 1.5px solid var(--fn-card-edge); border-radius: var(--fn-radius-lg);
    box-shadow: var(--fn-shadow-lg); padding: var(--fn-sp-6) var(--fn-sp-6) var(--fn-sp-5);
    animation: rise-in .6s cubic-bezier(.2,.8,.3,1) both;
}
.auth-card h1 { font-size: var(--fn-text-2xl); margin-bottom: var(--fn-sp-1); }
.auth-card .brand-line { display: flex; align-items: center; gap: 9px; color: var(--fn-forest-700); font-family: var(--fn-font-display); font-weight: 600; font-size: var(--fn-text-lg); margin-bottom: var(--fn-sp-4); }
.auth-card .brand-line > svg { width: 26px; height: 26px; }
.auth-submit { width: 100%; margin-top: var(--fn-sp-2); }
.auth-error { background: var(--fn-red-200); color: var(--fn-red-600); padding: var(--fn-sp-3); border-radius: var(--fn-radius-sm); margin-bottom: var(--fn-sp-4); font-weight: 600; }

/* A "read this before you go on" note on an auth page — softer than an error; it isn't a failure. */
.auth-note { background: var(--fn-card); border: 1px solid var(--fn-card-edge); border-left: 3px solid var(--fn-forest-700); padding: var(--fn-sp-3); border-radius: var(--fn-radius-sm); margin-bottom: var(--fn-sp-4); }
.auth-note p { margin: .4rem 0 0; }

/* Switching between the forest schools you work with. A wider card than the other auth pages: these rows
   carry a name, a role and a button, and at 430px the button wraps onto two lines. */
.auth-card--wide { max-width: 560px; }
.org-switch-list { list-style: none; margin: var(--fn-sp-3) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--fn-sp-2); }
.org-switch-item { display: flex; align-items: center; justify-content: space-between; gap: var(--fn-sp-3); padding: var(--fn-sp-3); border: 1px solid var(--fn-card-edge); border-radius: var(--fn-radius-sm); background: var(--fn-card); }
.org-switch-item.is-current { border-color: var(--fn-forest-700); }
.org-switch-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.org-switch-name { font-weight: 600; }
.org-switch-item form { margin: 0; }
.org-switch-item .btn { white-space: nowrap; }
.auth-card .field-row { display: flex; gap: var(--fn-sp-3); }
.auth-card .field-row label { flex: 1; min-width: 0; }
/* inline "Forgot password?" sitting on the password label's baseline */
.auth-label-row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--fn-sp-3); }
.auth-label-row a { font-size: var(--fn-text-sm); font-weight: 600; }
/* clearly separated sign-up prompt — a hairline keeps it off the Sign in button */
.auth-alt { margin-top: var(--fn-sp-5); padding-top: var(--fn-sp-4); border-top: 1px solid var(--fn-line); text-align: center; color: var(--fn-ink-500); font-size: var(--fn-text-sm); }
.field-hint { display: block; color: var(--fn-ink-500); font-size: var(--fn-text-sm); margin-top: 4px; }
/* drifting leaves — the OUTER span falls straight down at a steady pace (never pauses); the INNER span
   flutters side-to-side and rocks on its own rhythm. Splitting descent from sway means the fall never
   stalls, and giving each leaf its own descent + flutter timing keeps them spread out instead of clumping. */
.leaf-drift { position: absolute; top: 0; z-index: 1; color: var(--fn-leaf-400); animation: leaf-descend linear infinite; will-change: transform; }
.leaf-flutter { display: inline-block; animation: leaf-flutter ease-in-out infinite alternate; will-change: transform; }

/* ---------- Forest School · The App — logo lockup (sprig + stacked wordmark) ---------- */
.fs-logo { display: inline-flex; align-items: center; gap: .5em; text-decoration: none; line-height: 1; }
.fs-logo__mark { width: 2.25em; height: 2.25em; flex: none; }
/* app-icon squircle: same mark on paper and on dark — one consistent brand chip */
.fs-logo__mark .fs-box   { fill: var(--fn-forest-700); }
.fs-logo__mark .fs-leaf  { fill: #5fd24f; }
.fs-logo__mark .fs-leaf2 { fill: #5fd24f; opacity: .82; }
.fs-logo__mark .fs-stem  { stroke: #cfe0c7; }
/* only the sprig sways (pivoting at the stem base); the box stays put */
.fs-logo__mark .fs-sprig { transform-box: fill-box; transform-origin: 50% 100%; animation: leaf-sway 6s ease-in-out infinite; }
.fs-logo__text { display: inline-grid; gap: .22em; }
.fs-logo__name { font-family: var(--fn-font-display); font-weight: 600; font-size: 1em; letter-spacing: -.01em; color: var(--fn-forest-900); }
.fs-logo__kicker { font-family: var(--fn-font); font-weight: 700; font-size: .42em; letter-spacing: .34em; text-transform: uppercase; color: var(--fn-forest-500); }
/* hero size on the login splash */
.fs-logo.fs-hero { font-size: var(--fn-text-2xl); }
/* on dark surfaces (sidebar / mobile top bar): only the wordmark changes — the squircle mark is identical everywhere */
.fs-logo.fs-on-dark .fs-logo__name { color: #fff; }
.fs-logo.fs-on-dark .fs-logo__kicker { color: #9fb497; }

/* ---------- Page header ---------- */
.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--fn-sp-4); margin-bottom: var(--fn-sp-6); flex-wrap: wrap; }
.page-head h1 { margin: 0; }
.page-head .sub { font-family: var(--fn-font-hand); font-size: 1.4rem; color: var(--fn-ink-500); margin: 6px 0 0; }

/* ---------- Tables ---------- */
/* No overflow:hidden — it would kill the sticky header; corners are rounded per-cell instead. */
.fn-table { width: 100%; border-collapse: separate; border-spacing: 0; background: var(--fn-card); border: 1.5px solid var(--fn-card-edge); border-radius: var(--fn-radius-lg); box-shadow: var(--fn-shadow-sm); }
.fn-table th { text-align: left; font-family: var(--fn-font-hand); font-size: 1.1rem; color: var(--fn-ink-500); font-weight: 700; padding: 10px var(--fn-sp-4); background: var(--fn-paper-2); border-bottom: 1.5px solid var(--fn-line); position: sticky; top: 0; z-index: 2; }
.fn-table thead th:first-child { border-top-left-radius: var(--fn-radius-lg); }
.fn-table thead th:last-child { border-top-right-radius: var(--fn-radius-lg); }
.fn-table tbody tr:last-child td:first-child { border-bottom-left-radius: var(--fn-radius-lg); }
.fn-table tbody tr:last-child td:last-child { border-bottom-right-radius: var(--fn-radius-lg); }
.fn-table td { padding: var(--fn-sp-3) var(--fn-sp-4); border-bottom: 1px solid var(--fn-line); transition: background .12s ease; }
/* Anchor each row on its primary (first) column, but keep nested secondary text light. */
.fn-table td:first-child { font-weight: 600; }
.fn-table td:first-child .muted, .fn-table td:first-child .small { font-weight: 400; }
.fn-table tr:last-child td { border-bottom: none; }
.fn-table tbody tr:hover td { background: var(--fn-paper-2); }
/* Keyboard focus for clickable rows (role=button, made operable by the global Enter/Space handler). */
.fn-table tbody tr[role="button"] { outline: none; }
.fn-table tbody tr[role="button"]:focus-visible td { background: var(--fn-leaf-200); box-shadow: inset 0 -2px 0 var(--fn-forest-500), inset 0 2px 0 var(--fn-forest-500); }
[role="button"][tabindex]:not(tr):focus-visible { outline: 3px solid var(--fn-ember); outline-offset: 2px; }

/* Visually-hidden, still read by screen readers. */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* Skeleton loader — shimmer placeholder shaped like a table while a list loads. */
.skeleton-card { background: var(--fn-card); border: 1.5px solid var(--fn-card-edge); border-radius: var(--fn-radius-lg); box-shadow: var(--fn-shadow-sm); overflow: hidden; }
.skeleton-row { display: flex; align-items: center; gap: 1.5rem; padding: 15px var(--fn-sp-4); border-bottom: 1px solid var(--fn-line); }
.skeleton-row:last-child { border-bottom: none; }
.skeleton-bar { height: 12px; border-radius: 6px;
    background: linear-gradient(90deg, var(--fn-paper-2) 25%, var(--fn-paper-3) 37%, var(--fn-paper-2) 63%);
    background-size: 400% 100%; animation: skeleton-shimmer 1.4s ease infinite; }
@keyframes skeleton-shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }
@media (prefers-reduced-motion: reduce) { .skeleton-bar { animation: none; } }

/* On a phone a 4-column table overflows and clips its right-hand columns. Collapse each row into a
   stacked card: the first cell is the title, the rest become tidy label:value lines (via data-label). */
@media (max-width: 640px) {
    .fn-table { border: none; background: transparent; box-shadow: none; border-radius: 0; overflow: visible; }
    .fn-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
    .fn-table tbody, .fn-table tr, .fn-table td { display: block; width: 100%; }
    .fn-table tr { background: var(--fn-card); border: 1.5px solid var(--fn-card-edge); border-radius: var(--fn-radius-lg); box-shadow: var(--fn-shadow-sm); padding: 12px 14px; margin-bottom: 10px; }
    .fn-table tbody tr:hover td { background: transparent; }
    .fn-table td { border-bottom: none; padding: 4px 0; }
    .fn-table td:first-child { font-size: 1.05rem; font-weight: 600; margin-bottom: 2px; padding-bottom: 8px; border-bottom: 1px solid var(--fn-line); }
    .fn-table td[data-label] { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 4px 12px; min-width: 0; }
    .fn-table td[data-label]::before { content: attr(data-label); flex: 0 0 auto; color: var(--fn-ink-500); font-size: .8rem; font-weight: 600; }
    /* The value must be able to shrink and wrap so nothing runs off the right edge. */
    .fn-table td[data-label] > * { min-width: 0; max-width: 100%; overflow-wrap: anywhere; }
    /* A wrapping tag-list (e.g. medical flags) stacks UNDER its label and wraps across the full
       card width; its pills wrap their own long free-text rather than clipping. */
    .fn-table td[data-label]:has(.tag-list) { flex-direction: column; align-items: stretch; }
    .fn-table td[data-label] .tag-list { width: 100%; }
    .fn-table td[data-label] .chip { white-space: normal; }
}

/* Compliance-at-a-glance chip row (profile + free-practitioner home) */
.prof-compliance { display: flex; flex-wrap: wrap; gap: .5rem; margin: 0 0 1rem; }

/* Inline document preview (uploaded PDF via iframe/object; Word converted to sanitised HTML) */
.doc-frame { width: 100%; height: 75vh; border: 1.5px solid var(--fn-card-edge); border-radius: var(--fn-radius-sm); background: #fff; }
.doc-html { background: #fff; border: 1.5px solid var(--fn-card-edge); border-radius: var(--fn-radius-sm); padding: 1.25rem 1.5rem; max-height: 75vh; overflow: auto; }
.doc-html :is(h1, h2, h3) { font-family: var(--fn-font-display); color: var(--fn-forest-900); margin: 1rem 0 .4rem; }
.doc-html p { margin: 0 0 .6rem; }
.doc-html table { border-collapse: collapse; width: 100%; margin: .6rem 0; }
.doc-html td, .doc-html th { border: 1px solid var(--fn-line-strong); padding: 6px 9px; text-align: left; vertical-align: top; }
.doc-html img { max-width: 100%; height: auto; }

/* Payment-overdue grace nudge (owner only) */
.grace-banner {
    display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px;
    background: var(--fn-amber-200); color: var(--fn-ink-900);
    border: 1.5px solid var(--fn-amber-600); border-radius: var(--fn-radius-sm);
    padding: 12px 16px; margin: 0 0 1rem; font-weight: 600;
}
.grace-banner .btn { flex: 0 0 auto; }

/* Lapsed-subscription paywall — a calm, legible stop, not an error. Sits over the page content
   (below the top bar) so "browse read-only" and the billing path both stay one tap away. */
.paywall {
    position: fixed; inset: 0; z-index: var(--fn-z-sheet, 60);
    background: rgba(38, 36, 32, .45); backdrop-filter: blur(2px);
    display: flex; align-items: center; justify-content: center; padding: 20px;
}
.paywall-card {
    background: var(--fn-paper, #fbf7ef); border: 1px solid var(--fn-line-strong);
    border-left: 6px solid var(--fn-forest-600);
    border-radius: var(--fn-radius); box-shadow: var(--fn-shadow-lg);
    max-width: 520px; width: 100%; padding: 26px 26px 22px;
}
.paywall-card h2 { margin: 0 0 .5rem; }
.paywall-card p { color: var(--fn-ink-700); }
.paywall-actions { display: flex; flex-direction: column; gap: 10px; margin-top: 1.1rem; }
.paywall-actions .btn { width: 100%; }

/* ---------- Group hub tiles (the session-runner hub pattern, reused for managing a group:
   each tile is the status line AND the way in — nothing hidden below the fold) ---------- */
.ghub-tiles { display: flex; flex-direction: column; gap: 12px; max-width: 720px; }
.ghub-tile {
    display: flex; align-items: center; gap: 14px; width: 100%; text-align: left; cursor: pointer;
    background: var(--fn-card); border: 1.5px solid var(--fn-card-edge); border-radius: var(--fn-radius);
    padding: 16px 18px; box-shadow: var(--fn-shadow-sm);
    transition: transform .14s cubic-bezier(.2,.7,.3,1), box-shadow .2s;
}
.ghub-tile:hover { transform: translateY(-2px); box-shadow: var(--fn-shadow); }
a.ghub-tile { text-decoration: none; color: inherit; }
.ghub-edit-link { display: inline-block; margin-top: .8rem; font-size: .85rem; color: var(--fn-ink-500); text-decoration: underline; }
.ghub-edit-link:hover { color: var(--fn-forest-700); }
.ghub-tile-ic { flex: 0 0 auto; display: grid; place-items: center; width: 44px; height: 44px;
    border-radius: 12px; background: var(--fn-leaf-200); color: var(--fn-forest-700); }
.ghub-tile-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ghub-tile-title { font-family: var(--fn-font-display); font-weight: 700; font-size: 1.15rem; color: var(--fn-forest-900); }
.ghub-tile-sub { font-size: .92rem; color: var(--fn-ink-500); }
.ghub-go { margin-left: auto; font-size: 1.6rem; color: var(--fn-ink-500); line-height: 1; }
.ghub-next {
    display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap;
    background: var(--fn-leaf-200); border: 1.5px solid var(--fn-leaf-400);
    border-radius: var(--fn-radius); padding: 14px 18px; margin: 0 0 1.1rem; max-width: 720px;
}
.ghub-next .btn { flex: 0 0 auto; }
.ghub-past > summary { cursor: pointer; font-weight: 600; color: var(--fn-ink-500); padding: .6rem 0 0; }

/* Responsive hub shell. Phone: one thing at a time — the hub OR a panel, flipped by ?p= so the back
   gesture pops out. Desktop: master-detail — the tiles become a left rail with the open section
   alongside (first section open on landing), so drilling in is never an extra step. */
.ghub-shell.is-hub .ghub-main { display: none; }
.ghub-shell.is-panel .ghub-side { display: none; }
.ghub-panel-head { margin-bottom: 1.1rem; }
.ghub-panel-title { font-size: 1.55rem; margin: 0; }
@media (min-width: 1000px) {
    .ghub-shell { display: grid; grid-template-columns: 300px minmax(0, 1fr); gap: 1.75rem; align-items: start; }
    .ghub-shell.is-hub .ghub-main, .ghub-shell.is-panel .ghub-side { display: block; }
    .ghub-shell .ghub-side { min-width: 0; }
    .ghub-panel-head { display: none; }   /* the active rail tile already names the section, and the rail is the way back */
    .ghub-side .ghub-next { flex-direction: column; align-items: stretch; text-align: left; }
    .ghub-side .ghub-tile { padding: 12px 14px; }
    .ghub-side .ghub-tile-title { font-size: 1.02rem; }
    .ghub-side .ghub-tile:hover { transform: none; }
    .ghub-tile.is-active { border-color: var(--fn-forest-700); background: var(--fn-leaf-200); }
    .ghub-tile.is-active .ghub-go { color: var(--fn-forest-700); }
}

/* Done screen: one column, one gap. Every card is spaced the same way, so nothing butts up against the card
   above it (the counts and the cards used to touch on one side and sit 16px apart on the other). */
.sum-stack { display: flex; flex-direction: column; gap: 1rem; }

/* At-a-glance counts — a row of figures INSIDE the closing card, divided by hairlines. They were four separate
   boxes with a straight 1px border, which fought the hand-drawn frame of every card around them. */
.sum-stats { display: grid; grid-template-columns: repeat(4, 1fr); margin: 1rem -.25rem 0;
    padding-top: .9rem; border-top: 1px solid var(--fn-line); }
.sum-stat { padding: 0 .5rem; text-align: center; border-right: 1px solid var(--fn-line); }
.sum-stat:last-child { border-right: 0; }
.sum-num { display: block; font-family: var(--fn-font-hand); font-size: 1.7rem; font-weight: 700; color: var(--fn-forest-700); line-height: 1; }
.sum-lbl { display: block; font-size: .72rem; color: var(--fn-ink-500); margin-top: 4px; }
@media (max-width: 430px) {
    .sum-stats { grid-template-columns: repeat(2, 1fr); row-gap: .9rem; }
    /* On two columns the divider must fall between the pair, not after every cell. */
    .sum-stat:nth-child(2n) { border-right: 0; }
}

/* ---------- Misc ---------- */
.op-note { background: radial-gradient(120% 140% at 0% 0%, rgba(215,232,207,.7), var(--fn-card)); border: 1.5px solid var(--fn-leaf-400); border-radius: var(--fn-radius); padding: var(--fn-sp-4) var(--fn-sp-5); }
.coming-soon { background: var(--fn-paper-2); border: 2px dashed var(--fn-line-strong); border-radius: var(--fn-radius-lg); padding: var(--fn-sp-7); text-align: center; color: var(--fn-ink-500); }
.coming-soon .hand { display: block; font-size: 2rem; margin-bottom: var(--fn-sp-2); }

/* ---------- Empty states ---------- */
.empty-state {
    text-align: center; padding: var(--fn-sp-8) var(--fn-sp-5); max-width: 460px; margin: var(--fn-sp-4) auto;
    background: var(--fn-paper-2); border: 2px dashed var(--fn-line-strong); border-radius: var(--fn-radius-lg);
}
.empty-state .empty-emoji { font-size: 2.6rem; line-height: 1; margin-bottom: var(--fn-sp-3); }
.empty-state .empty-icon { color: var(--fn-forest-500); line-height: 1; margin-bottom: var(--fn-sp-3); }
.empty-state h2 { font-family: var(--fn-font-display); font-size: 1.5rem; color: var(--fn-forest-900); margin: 0 0 var(--fn-sp-2); }
.empty-state p { color: var(--fn-ink-500); margin: 0 auto var(--fn-sp-5); max-width: 38ch; }
.empty-state .btn { width: auto; }
.row-skip { opacity: .5; }

/* ---------- Mobile top bar + bottom tab nav ---------- */
.fn-topbar-brand { display: none; align-items: center; gap: 8px; font-family: var(--fn-font-display); font-weight: 600; font-size: var(--fn-text-lg); color: var(--fn-forest-900); text-decoration: none; }
.fn-topbar-brand .leaf { color: var(--fn-leaf-cta); }
.fn-topbar-spacer { flex: 1 1 auto; }

/* WHO YOU ARE — at the foot of the nav. On a desktop the top bar carried NOTHING but your email address and a
   Sign out link: 62px of every page, permanently, for two things you look at roughly never — and it scrolled
   away, so it wasn't even reliably there. The sidebar is sticky and always in view; its foot is where an account
   belongs. The top bar still exists on a phone, where it carries the brand and the way into the menu. */
@media (min-width: 761px) {
    .fn-topbar { display: none; }
}
.fn-nav-foot { margin-top: auto; padding-top: var(--fn-sp-4); border-top: 1px solid rgba(255,255,255,.10); }
.fn-nav-me { display: flex; align-items: center; gap: 10px; padding: .5rem .7rem; border-radius: var(--fn-radius-sm);
    text-decoration: none; color: #eef3ea; }
.fn-nav-me:hover { background: rgba(255,255,255,.08); text-decoration: none; }
.fn-nav-me-avatar { flex: 0 0 auto; width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center;
    background: rgba(255,255,255,.14); color: #eef3ea; font-size: .74rem; font-weight: 700; letter-spacing: .02em; }
.fn-nav-me-body { min-width: 0; display: flex; flex-direction: column; }
.fn-nav-me-name { font-size: .78rem; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fn-nav-me-sub { font-size: .7rem; color: rgba(238,243,234,.6); }
.fn-nav-signout { width: 100%; margin-top: 2px; padding: .45rem .7rem; text-align: left; border: 0; background: none;
    cursor: pointer; font: 600 .78rem var(--fn-font); color: rgba(238,243,234,.62); border-radius: var(--fn-radius-sm); }
.fn-nav-signout:hover { background: rgba(255,255,255,.08); color: #eef3ea; }

.bottomnav { display: none; }
.bn-tab {
    flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
    min-height: 60px; padding: 6px 0; color: var(--fn-ink-500); text-decoration: none; font-size: 0.72rem; font-weight: 600;
}
.bn-tab svg { width: 24px; height: 24px; }
.bn-tab.active { color: var(--fn-forest-700); }
.bn-tab.active svg { color: var(--fn-leaf-cta); }
.bn-tab:hover { text-decoration: none; }

/* ---------- More (mobile setup hub) ---------- */
/* The More sheet — the phone's nav. Sections mirror the desktop sidebar's, because it renders the same list. */
.more-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--fn-sp-4); max-width: 560px; margin-bottom: var(--fn-sp-5); }
.more-head h1 { margin: 0; }
.more-head .sub { margin: .3rem 0 0; color: var(--fn-ink-500); }
/* A menu you can't put down isn't a menu. Big enough to hit with a thumb without aiming. */
.more-close { flex: 0 0 auto; display: grid; place-items: center; width: 44px; height: 44px; margin-top: 2px;
    border: 1.5px solid var(--fn-card-edge); border-radius: 50%; background: var(--fn-card);
    color: var(--fn-ink-500); font-size: 1.05rem; line-height: 1; text-decoration: none; box-shadow: var(--fn-shadow-sm); }
.more-close:hover { text-decoration: none; color: var(--fn-forest-900); border-color: var(--fn-line-strong); }
.more-section { max-width: 560px; margin: var(--fn-sp-5) 0 var(--fn-sp-3); font-size: var(--fn-text-xs);
    letter-spacing: .09em; text-transform: uppercase; color: var(--fn-ink-500); font-weight: 600; }
.more-section:first-of-type { margin-top: 0; }
.more-row strong .fn-nav-tag { margin-left: 6px; }
.more-avatar { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%;
    background: var(--fn-forest-800); color: var(--fn-paper); font-size: .8rem; font-weight: 700; letter-spacing: .02em; }
.more-list { display: flex; flex-direction: column; gap: 10px; max-width: 560px; }
.more-row { display: flex; align-items: center; gap: 14px; padding: 16px 18px; background: var(--fn-card); border: 1.5px solid var(--fn-card-edge); border-radius: var(--fn-radius); box-shadow: var(--fn-shadow-sm); text-decoration: none; color: var(--fn-ink-700); transition: transform .12s ease, box-shadow .12s ease; }
.more-row:hover { text-decoration: none; box-shadow: var(--fn-shadow); transform: translateY(-1px); }
.more-row .more-ic { font-size: 1.5rem; line-height: 1; }
.more-row span:nth-child(2) { flex: 1; display: flex; flex-direction: column; }
.more-row strong { color: var(--fn-forest-900); }
.more-row small { color: var(--fn-ink-500); }
.more-row .more-go { font-size: 1.6rem; color: var(--fn-ink-300); }
.more-signout { margin-top: var(--fn-sp-5); }

/* ---------- Today dashboard ---------- */
.today-card {
    display: flex; flex-direction: column; gap: 4px; text-decoration: none;
    background: linear-gradient(135deg, var(--fn-forest-700), var(--fn-forest-900));
    color: #f4efe0; border-radius: var(--fn-radius-lg); padding: var(--fn-sp-5) var(--fn-sp-6);
    box-shadow: var(--fn-shadow); position: relative; overflow: hidden; margin-bottom: var(--fn-sp-4);
}

/* "Needs you" dashboard strip — clay-accented to-do cards, shown only when there's something to act on. */
/* Date/season note on the left, the few "needs you" cards on the right of the same row. */
.wn-top { display: flex; align-items: center; justify-content: space-between; gap: .8rem 1.25rem; flex-wrap: wrap; margin: 0 0 var(--fn-sp-4); }
.wn-top .wn-note { margin: 0; }
.needs-strip { display: flex; flex-wrap: wrap; gap: .6rem; margin: 0; }
.needs-card { display: flex; align-items: center; gap: .6rem; padding: .65rem .95rem; text-decoration: none;
    background: #fbf0e6; border: 1.5px solid #e7c3a6; border-radius: var(--fn-radius); color: var(--fn-ink-700);
    transition: transform .12s ease, box-shadow .12s ease; }
.needs-card:hover { transform: translateY(-1px); box-shadow: var(--fn-shadow-sm); text-decoration: none; }
.needs-card .needs-ic { color: var(--fn-red-600); display: flex; }
.needs-num { font-weight: 700; font-family: var(--fn-font-display); font-size: 1.05rem; }
.needs-label { color: var(--fn-ink-500); }
.needs-go { margin-left: .3rem; color: var(--fn-red-600); font-weight: 700; }

/* Collapsible form section (progressive disclosure) — native <details>, keyboard-accessible, no JS. */
.form-details > summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: .5rem; margin: 0; }
.form-details > summary::-webkit-details-marker { display: none; }
.form-details > summary::after { content: "▸"; margin-left: auto; color: var(--fn-ink-500); transition: transform .15s ease; }
.form-details[open] > summary::after { transform: rotate(90deg); }
.form-details[open] > summary { margin-bottom: var(--fn-sp-3); }
.form-details > summary:focus-visible { outline: 3px solid var(--fn-ember); outline-offset: 3px; border-radius: var(--fn-radius-sm); }
.today-card::after {
    content: ""; position: absolute; right: -20px; bottom: -30px; width: 150px; height: 150px; opacity: .14;
    background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='1.2'><path d='M12 3c1.2 4 5 5 5 9a5 5 0 01-10 0c0-2 1-3.2 2.2-4.2C9.2 9.6 10 11 11 11c1.2-1.8-.4-5 1-8Z'/></svg>") no-repeat center/contain;
}
.today-card:hover { text-decoration: none; transform: translateY(-1px); box-shadow: var(--fn-shadow-lg); }
.today-kicker { font-family: var(--fn-font); font-size: var(--fn-text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .07em; color: #bfe6a8; }
.today-card.is-live .today-kicker { color: #8ff07a; }
.today-title { font-family: var(--fn-font-display); font-size: 1.9rem; font-weight: 600; line-height: 1.1; margin: 2px 0; }
.today-meta { color: #d8cfb8; font-size: var(--fn-text-sm); }
.today-go { margin-top: var(--fn-sp-3); font-weight: 700; color: #fff; }
.today-card--empty { background: linear-gradient(135deg, var(--fn-paper-2), var(--fn-card)); color: var(--fn-ink-700); border: 2px dashed var(--fn-line-strong); box-shadow: var(--fn-shadow-sm); }
.today-card--empty .today-kicker { color: var(--fn-forest-600); }
.today-card--empty .today-title { color: var(--fn-forest-900); }
.today-card--empty .today-meta { color: var(--fn-ink-500); }
.today-card--empty .today-go { color: var(--fn-forest-700); }
.today-card--empty::after { background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%233d4e3b' stroke-width='1.2'><path d='M12 3c1.2 4 5 5 5 9a5 5 0 01-10 0c0-2 1-3.2 2.2-4.2C9.2 9.6 10 11 11 11c1.2-1.8-.4-5 1-8Z'/></svg>"); opacity: .2; }

/* Setup checklist */
.setup-card { background: var(--fn-card); border: 1.5px solid var(--fn-card-edge); border-radius: var(--fn-radius-lg); box-shadow: var(--fn-shadow-sm); padding: var(--fn-sp-5) var(--fn-sp-5) var(--fn-sp-3); margin-bottom: var(--fn-sp-5); }
.setup-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.setup-head h2 { font-family: var(--fn-font-display); font-size: 1.4rem; margin: 0; color: var(--fn-forest-900); }
.setup-count { font-family: var(--fn-font-hand); font-size: 1.15rem; color: var(--fn-forest-600); white-space: nowrap; }
.setup-bar { height: 8px; border-radius: 99px; background: var(--fn-paper-2); margin: 12px 0 4px; overflow: hidden; }
.setup-bar span { display: block; height: 100%; border-radius: 99px; background: linear-gradient(90deg, var(--fn-leaf-400), var(--fn-leaf-cta)); transition: width .4s ease; }
.setup-steps { list-style: none; margin: 8px 0 0; padding: 0; }
.setup-steps li { display: flex; align-items: center; gap: 12px; padding: 14px 0; border-bottom: 1px solid var(--fn-line); }
.setup-steps li:last-child { border-bottom: none; }
.setup-tick { flex: 0 0 26px; width: 26px; height: 26px; border-radius: 50%; border: 2px solid var(--fn-line-strong); display: flex; align-items: center; justify-content: center; font-weight: 800; color: #fff; }
.setup-steps li.is-done .setup-tick { background: var(--fn-leaf-cta); border-color: var(--fn-leaf-cta); }
.setup-body { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.setup-body strong { color: var(--fn-forest-900); }
.setup-steps li.is-done .setup-body strong { color: var(--fn-ink-500); text-decoration: line-through; text-decoration-color: var(--fn-line-strong); }
.setup-body small { color: var(--fn-ink-500); }
.setup-cta { min-height: 42px; padding: 0 18px; white-space: nowrap; }
.setup-done-tag { font-family: var(--fn-font-hand); font-size: 1.1rem; color: var(--fn-forest-600); }

.signed-line { color: var(--fn-ink-500); font-size: var(--fn-text-sm); margin-top: var(--fn-sp-5); }

/* ---------- In-session focus shell ----------
   Running a session is a mode, not a page. On a PHONE it takes the whole screen: no sidebar, no bottom nav, no
   setup chrome — just this session and a clear way out (the strip-out lives in the phone media query below).
   At a DESK the app chrome stays: you're writing the session up, not standing in a wood, and locking you away
   from the children, the risk library and the diary isn't focus — it's a dead end. The header bar below is the
   same in both, so the session always says where and when you are. */
.fn-focus { max-width: 980px; margin: 0 auto; padding: 14px 16px 96px; }
.focus-bar {
    position: sticky; top: 0; z-index: 40;
    display: flex; align-items: center; gap: 10px;
    margin: -14px -16px 16px; padding: 10px 14px;
    /* Near-opaque solid (no backdrop-filter): a blurred sticky bar forces constant GPU compositing,
       which janks on field phones — keep the field app cheap to paint. */
    background: var(--fn-paper);
    border-bottom: 1px solid var(--fn-line);
    box-shadow: 0 1px 0 color-mix(in srgb, var(--fn-paper) 60%, transparent);
}
.focus-title {
    flex: 1 1 auto; min-width: 0; font-weight: 600; color: var(--fn-ink-900);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.focus-title small { display: block; font-weight: 500; color: var(--fn-ink-500); font-size: .82rem; }
.focus-leave, .focus-action {
    flex: 0 0 auto; font-weight: 600; text-decoration: none;
    padding: 9px 12px; border-radius: 12px; min-height: 40px; display: inline-flex; align-items: center;
}
.focus-leave { color: var(--fn-forest-700); }
.focus-leave:hover { background: var(--fn-paper-2); text-decoration: none; }
.focus-action { color: var(--fn-red-600); }
.focus-action:hover { background: var(--fn-red-200); text-decoration: none; }
/* Desktop: the session sits inside the normal content column, so the bar reads as this page's header rather
   than a phone's chrome — it sticks under nothing, and the sidebar is the way around the app. */
@media (min-width: 761px) {
    .fn-focus { padding: 0 0 96px; }
    .focus-bar { margin: 0 0 1.25rem; padding: 0 0 .9rem; background: transparent; box-shadow: none; }
    .focus-title { font-family: var(--fn-font-display); font-size: 1.35rem; }
    .focus-leave { margin-left: -12px; }
}
/* A child's name in the register, when the host can open their record (web only). Underline on hover only —
   the register must stay a scannable list of names, not a page of blue links. */
.reg-name--link { color: var(--fn-forest-900); text-decoration: none; cursor: pointer; }
.reg-name--link:hover { text-decoration: underline; text-underline-offset: 3px; }
/* "Edit →" on the plan, and the empty-plan prompt that replaces it when there's nothing planned yet. */
.dash-plan-edit { margin-left: auto; padding: 2px 8px; border: 0; border-radius: var(--fn-radius-pill);
    background: transparent; font: inherit; font-size: var(--fn-text-xs); font-weight: 700;
    color: var(--fn-forest-700); cursor: pointer; }
.dash-plan-edit:hover { background: var(--fn-paper-2); }
.dash-plan--empty { display: block; width: 100%; text-align: left; border: 1.5px dashed var(--fn-line-strong);
    background: transparent; font: inherit; cursor: pointer; }
.dash-plan--empty:hover { border-color: var(--fn-forest-600); }

/* ---------- Branded loading splash ---------- */
.app-loading {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1rem;
    min-height: 78vh; text-align: center; padding: 2rem 1rem;
}
.app-loading-mark svg {
    width: 88px; height: 88px; display: block; border-radius: 21px;
    filter: drop-shadow(0 7px 16px rgba(40, 52, 42, .18));
    animation: app-breathe 1.9s cubic-bezier(.4, 0, .3, 1) infinite;
}
.app-loading-text {
    margin: 0; font-family: var(--fn-font-hand); font-size: 1.35rem; color: var(--fn-forest-700);
    animation: app-fade 1.9s ease-in-out infinite;
}
@keyframes app-breathe { 0%, 100% { transform: scale(1) translateY(0); } 50% { transform: scale(1.07) translateY(-3px); } }
@keyframes app-fade { 0%, 100% { opacity: .5; } 50% { opacity: 1; } }

/* First-load splash (Blazor Server connect gap) — a full-screen calm cover on the paper ground with the same
   breathing mark as .app-loading, so an interactive page never opens on bare beige. Lives in App.razor's body;
   the boot script fades it (.is-gone) and removes it once the page is up. Web-only (MAUI has its own boot). */
.fn-boot {
    position: fixed; inset: 0; z-index: 10000;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1rem;
    text-align: center; padding: 2rem 1rem;
    background-color: var(--fn-paper);
    background-image:
        radial-gradient(120% 85% at 88% -8%, rgba(232,184,75,.16), transparent 55%),
        radial-gradient(90% 70% at -10% 8%, rgba(94,122,89,.14), transparent 55%),
        radial-gradient(70% 60% at 50% 120%, rgba(61,78,59,.10), transparent 60%);
    opacity: 1; transition: opacity .4s ease;
}
.fn-boot.is-gone { opacity: 0; pointer-events: none; }
.fn-boot-mark svg {
    width: 84px; height: 84px; display: block; border-radius: 20px;
    filter: drop-shadow(0 7px 16px rgba(40, 52, 42, .18));
    animation: app-breathe 1.9s cubic-bezier(.4, 0, .3, 1) infinite;
}
.fn-boot-text {
    margin: 0; font-family: var(--fn-font-hand); font-size: 1.35rem; color: var(--fn-forest-700);
    animation: app-fade 1.9s ease-in-out infinite;
}

/* Friendly error fallback (global error boundary) */
.app-error {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .6rem;
    min-height: 60vh; text-align: center; padding: 2rem 1.25rem; max-width: 26rem; margin: 0 auto;
}
.app-error-ic { color: var(--fn-amber-600); }
.app-error-title { font-family: var(--fn-font-display); font-size: 1.3rem; color: var(--fn-forest-900); margin: .2rem 0 0; }
.app-error-text { color: var(--fn-ink-500); margin: 0 0 .5rem; line-height: 1.5; }
.app-error-actions { display: flex; gap: .5rem; flex-wrap: wrap; justify-content: center; }
.app-error-detail { margin-top: .5rem; width: 100%; max-width: 30rem; text-align: left; }
.app-error-detail > summary { cursor: pointer; font-size: .85rem; color: var(--fn-ink-500); }
.app-error-detail pre { margin: .5rem 0 0; padding: .65rem .8rem; background: var(--fn-paper-2); border: 1px solid var(--fn-line-strong);
    border-radius: var(--fn-radius-sm); font-size: .72rem; line-height: 1.4; color: var(--fn-ink-700);
    white-space: pre-wrap; word-break: break-word; max-height: 40vh; overflow: auto; }

/* ---------- Session runner ---------- */
.run-stepper { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 1.5rem; }
.run-step { font-family: var(--fn-font-hand); font-size: 1.15rem; color: var(--fn-ink-300); padding: 4px 16px; border-radius: var(--fn-radius-pill); border: 1.5px dashed var(--fn-line-strong); background: transparent; cursor: pointer; }
.run-step:disabled { cursor: default; opacity: .5; }
.run-step.is-done:not(:disabled):hover { border-color: var(--fn-forest-500); color: var(--fn-forest-700); }
.run-step.is-done { color: var(--fn-forest-600); border-style: solid; border-color: var(--fn-leaf-400); }
.run-step.is-current { color: #fff; background: var(--fn-forest-600); border: 1.5px solid var(--fn-forest-700); }
.run-grid { display: grid; grid-template-columns: 1.4fr 1fr; gap: 1.75rem; align-items: start; }
.run-actions { display: flex; gap: 1rem; margin-top: 1.5rem; align-items: center; flex-wrap: wrap; }
.run-actions .btn--xl { width: auto; min-width: 230px; }

/* One-page runner: sticky section jump-nav + stacked sections. Single row — the pills scroll sideways on a
   narrow phone and Refresh stays pinned to the right, so it never wraps onto its own line. */
.run-nav { position: sticky; top: 0; z-index: 6; display: flex; align-items: center; gap: .6rem; flex-wrap: nowrap;
    margin: 0 0 1.25rem; padding: .5rem 0; background: rgba(253,250,242,.95); backdrop-filter: blur(6px);
    border-bottom: 1.5px solid var(--fn-line); }
.run-nav-links { display: flex; gap: .4rem; flex: 1 1 auto; min-width: 0; overflow-x: auto;
    scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.run-nav-links::-webkit-scrollbar { display: none; }
.run-nav-links a { font-family: var(--fn-font-hand); font-size: 1.05rem; line-height: 1.6; color: var(--fn-forest-700);
    text-decoration: none; padding: 1px 13px; border-radius: var(--fn-radius-pill); border: 1.5px solid var(--fn-line);
    background: transparent; white-space: nowrap; }
.run-nav-links a:hover { background: var(--fn-leaf-200); border-color: var(--fn-leaf-400); color: var(--fn-forest-800); text-decoration: none; }
.run-nav .run-refresh { flex: 0 0 auto; margin-left: 0; }
/* Generous rhythm so the one long page breathes: clear gaps between sections, and between the stacked
   blocks within a section (heading → cards → action). */
.run-sec { scroll-margin-top: 76px; margin-bottom: 2.75rem; }
.run-sec > * + * { margin-top: 1.1rem; }
.run-sec-head { font-family: var(--fn-font-display); font-size: 1.2rem; color: var(--fn-forest-900); margin: 0 0 .25rem; }
.add-more { margin: .75rem 0; border: 1.5px solid var(--fn-line-strong); border-radius: var(--fn-radius-sm); background: var(--fn-paper); padding: 0 .85rem; }
.add-more > summary { cursor: pointer; font-weight: 600; padding: .65rem 0; color: var(--fn-forest-800); list-style: none; display: flex; align-items: center; gap: .4rem; }
.add-more > summary::-webkit-details-marker { display: none; }
.add-more[open] > summary { border-bottom: 1px solid var(--fn-line); }
.add-more-body { padding: .75rem 0; display: flex; flex-direction: column; gap: .5rem; }

/* Session dashboard: the plan up top, then a hub of status tiles — tap to drill into a section */
.dash-top { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-bottom: 1rem; }
.status-pill { display: inline-flex; align-items: center; gap: 8px; padding: 5px 14px; border-radius: var(--fn-radius-pill);
    background: var(--fn-paper-2); border: 1.5px solid var(--fn-line-strong); font-family: var(--fn-font); font-weight: 600;
    font-size: var(--fn-text-sm); color: var(--fn-ink-700); }
.status-pill::before { content: ""; width: 9px; height: 9px; border-radius: 50%; background: var(--fn-ink-300); }
.status-pill--live { color: var(--fn-forest-800); border-color: var(--fn-leaf-400); }
.status-pill--live::before { background: var(--fn-leaf-cta); box-shadow: 0 0 0 3px var(--fn-leaf-200); }

/* Plan — a warm leafy band at the top, not a card */
.dash-plan { margin: 0 0 1.25rem; padding: .9rem 1.1rem; border-radius: var(--fn-radius);
    background: linear-gradient(155deg, var(--fn-leaf-200), var(--fn-paper-2) 85%); border: 1.5px solid var(--fn-leaf-400); }
/* flex, not inline-flex: the row spans the card so an "Edit →" can sit out at the right-hand end of it. */
.dash-plan-kicker { display: flex; align-items: center; gap: 6px; font-family: var(--fn-font); font-weight: 700;
    font-size: var(--fn-text-xs); text-transform: uppercase; letter-spacing: .06em; color: var(--fn-forest-700); }
.dash-plan-lead { margin: .25rem 0 .55rem; color: var(--fn-ink-900); font-size: 1.02rem; line-height: 1.5; }
.dash-plan-acts { display: flex; flex-wrap: wrap; gap: .4rem; }
.dash-plan-act { display: inline-flex; align-items: center; gap: 5px; padding: 4px 12px; border-radius: var(--fn-radius-pill);
    background: var(--fn-card); border: 1.5px solid var(--fn-leaf-400); font: inherit; font-size: .85rem; color: var(--fn-forest-800);
    cursor: pointer; transition: background .12s ease, transform .1s ease; }
.dash-plan-act:hover { background: var(--fn-leaf-200); transform: translateY(-1px); }
.dash-plan-act-go { color: var(--fn-forest-500); font-weight: 700; opacity: .55; }
.obs-activity { display: inline-flex; align-items: center; gap: 6px; margin: 0 0 .7rem; padding: 5px 12px;
    border-radius: var(--fn-radius-pill); background: var(--fn-leaf-200); color: var(--fn-forest-800); font-size: .88rem; }

/* Band labels group the tiles into "state" (top) and "logs you build up" (bottom). */
.dash-band-label { font-family: var(--fn-font); font-size: var(--fn-text-xs); font-weight: 700; text-transform: uppercase;
    letter-spacing: .07em; color: var(--fn-ink-300); margin: 1.4rem 0 .6rem; }
.dash-band-label:first-of-type { margin-top: 0; }

.dash { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .7rem; }
.dash-tile { position: relative; overflow: hidden; display: flex; flex-direction: column; align-items: stretch; gap: .55rem;
    text-align: left; cursor: pointer; font: inherit;
    padding: .85rem .95rem; border: 1.5px solid var(--fn-line-strong); border-radius: var(--fn-radius);
    background: var(--fn-card); transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease; }
/* Icon + label ride on top; the value sits directly beneath — compact, no dead vertical gap. */
.dash-tile-head { display: flex; align-items: center; gap: .5rem; min-width: 0; }
/* The lone 3rd tile in each band spans the full width (same card style), so a band never has a ragged empty half. */
.dash-tile:nth-child(3):last-child { grid-column: 1 / -1; }
/* A little hills-and-trees horizon in the corner, tinted to the tile's category — decorative, low opacity so
   the text stays crisp. Sits behind the content (children are lifted above it). */
.dash-tile > * { position: relative; z-index: 1; }
.dash-tile::after {
    content: ""; position: absolute; right: 10px; bottom: 8px; width: 60px; height: 60px; z-index: 0; pointer-events: none; opacity: .15;
    background: var(--tile-accent, var(--fn-forest-700));
    -webkit-mask: var(--tile-motif, var(--fn-hills)) right bottom / contain no-repeat;
            mask: var(--tile-motif, var(--fn-hills)) right bottom / contain no-repeat;
}
/* Each tile gets a genuinely different, relevant emblem — sun, a little group, a shield, a leaf, a branch, a cross */
.dash-tile--weather  { --tile-accent: var(--fn-amber-600); --tile-motif: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Ccircle cx='40' cy='40' r='13' fill='%23000'/%3E%3Cg stroke='%23000' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M40 19v6'/%3E%3Cpath d='M19 40h6'/%3E%3Cpath d='M55 40h7'/%3E%3Cpath d='M40 55v7'/%3E%3Cpath d='M25 25l4 4'/%3E%3Cpath d='M51 51l5 5'/%3E%3Cpath d='M55 25l-4 4'/%3E%3Cpath d='M29 51l-4 4'/%3E%3C/g%3E%3C/svg%3E"); }
.dash-tile--register { --tile-accent: var(--fn-forest-600); --tile-motif: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Cg fill='%23000'%3E%3Ccircle cx='22' cy='35' r='5'/%3E%3Cpath d='M15 63a7 7 0 0 1 14 0z'/%3E%3Ccircle cx='39' cy='28' r='6'/%3E%3Cpath d='M30 63a9 9 0 0 1 18 0z'/%3E%3Ccircle cx='54' cy='37' r='5'/%3E%3Cpath d='M47 63a7 7 0 0 1 14 0z'/%3E%3C/g%3E%3C/svg%3E"); }
.dash-tile--risk     { --tile-accent: var(--fn-sky-600); --tile-motif: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Cpath d='M38 12l20 8v15c0 14-10 23-20 27-10-4-20-13-20-27V20z' fill='%23000'/%3E%3C/svg%3E"); }
.dash-tile--obs      { --tile-accent: var(--fn-leaf-cta); --tile-motif: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Cpath d='M28 60C22 38 36 20 62 20c1 24-13 39-34 40z' fill='%23000'/%3E%3Cpath d='M28 60L16 64' stroke='%23000' stroke-width='3.5' stroke-linecap='round'/%3E%3C/svg%3E"); }
.dash-tile--risklog  { --tile-accent: var(--fn-amber-600); --tile-motif: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Cg fill='none' stroke='%23000' stroke-width='3.5' stroke-linecap='round'%3E%3Cpath d='M6 60C26 50 44 52 62 36'/%3E%3Cpath d='M40 48l8-13'/%3E%3Cpath d='M52 44l6-14'/%3E%3Cpath d='M26 52l-6-11'/%3E%3C/g%3E%3C/svg%3E"); }
.dash-tile--incident { --tile-accent: var(--fn-red-600); --tile-motif: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Cg fill='%23000'%3E%3Crect x='33' y='22' width='14' height='40' rx='4'/%3E%3Crect x='20' y='35' width='40' height='14' rx='4'/%3E%3C/g%3E%3C/svg%3E"); }
.dash-tile:hover { transform: translateY(-2px); box-shadow: var(--fn-shadow-sm); border-color: var(--fn-leaf-400); }
.dash-tile:active { transform: translateY(0); }
.dash-tile:focus-visible { outline: 3px solid var(--fn-ember); outline-offset: 2px; }
.dash-tile-label { min-width: 0; font-family: var(--fn-font); font-size: var(--fn-text-xs); font-weight: 600; text-transform: uppercase;
    letter-spacing: .05em; color: var(--fn-ink-500); line-height: 1.1; }
/* A coloured icon badge per category — now a compact top-left anchor. */
.dash-ic { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border-radius: 10px; flex: none; }
.dash-ic--weather  { background: var(--fn-sun-soft);  color: var(--fn-amber-600); }
.dash-ic--register { background: var(--fn-leaf-200);  color: var(--fn-forest-700); }
.dash-ic--risk     { background: var(--fn-sky-200);   color: var(--fn-sky-600); }
.dash-ic--obs      { background: var(--fn-leaf-200);  color: var(--fn-leaf-cta); }
.dash-ic--risklog  { background: var(--fn-amber-200); color: var(--fn-amber-600); }
.dash-ic--incident { background: var(--fn-red-200);   color: var(--fn-red-600); }
.dash-tile-main { font-family: var(--fn-font-display); font-size: 1.7rem; line-height: 1; color: var(--fn-forest-900); }
.dash-tile .dash-unit { font-family: var(--fn-font); font-size: .8rem; font-weight: 500; color: var(--fn-ink-500); }
.dash-tile-sub { font-size: .78rem; color: var(--fn-ink-500); line-height: 1.2; margin-top: .05rem;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The action affordance that stands in for a number when there's nothing to count yet — readable, inviting,
   never a lonely "0". Full tile width, one clean line. */
.dash-tile-cta { font-family: var(--fn-font); font-weight: 700; font-size: 1.05rem; color: var(--fn-forest-700); line-height: 1.1;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Log tiles carry a count badge only once they hold something — top-right, in the tile's own accent. */
.dash-count { position: absolute; top: 9px; right: 10px; z-index: 2; min-width: 22px; height: 22px; padding: 0 6px;
    display: inline-flex; align-items: center; justify-content: center; border-radius: 999px;
    font-family: var(--fn-font); font-weight: 700; font-size: .8rem; color: #fff;
    background: var(--tile-accent, var(--fn-forest-700)); }
.dash-tile--incident .dash-count { background: var(--fn-red-600); }
/* weather tile — the bold "are we go?" hero state */
.dash-tile--go { border-color: var(--fn-leaf-400); background: linear-gradient(155deg, var(--fn-leaf-200), var(--fn-card) 72%); }
.dash-tile--go .dash-tile-main { color: var(--fn-forest-700); }
.dash-tile--mod { border-color: #d9a531; background: linear-gradient(155deg, #faf0d6, var(--fn-card) 72%); }
.dash-tile--nogo { border-color: var(--fn-red-300, #e0a59a); background: linear-gradient(155deg, var(--fn-red-200, #f6dcd5), var(--fn-card) 72%); }
.dash-tile--nogo .dash-tile-main { color: var(--fn-red-600); }
.dash-actions { display: flex; flex-direction: column; align-items: center; gap: .35rem; margin-top: 1.1rem; }
.dash-actions .btn--xl { width: auto; min-width: 240px; }
.dash-back { margin: 0 0 1.5rem; padding-left: 0; }
@media (max-width: 380px) { .dash { grid-template-columns: 1fr; } }

/* ============================================================================
   Session hub — a real hierarchy (not a uniform grid). Headcount + weather set
   the scene; Observations is the solid hero; risk-log/incident are colour-coded
   secondary actions; risk assessments is demoted to a quiet reference link.
   Importance is encoded by size AND solid colour, so nothing reads as falsely equal.
   ============================================================================ */

/* Headcount — "how many children in the woods", taps into the register. */
.hub-count { display: flex; align-items: center; gap: .85rem; width: 100%; text-align: left; cursor: pointer;
    margin: 0 0 .65rem; padding: .8rem 1rem; border-radius: var(--fn-radius);
    background: var(--fn-card); border: 1.5px solid var(--fn-line-strong); }
.hub-count-ic { display: inline-grid; place-items: center; width: 44px; height: 44px; border-radius: 13px;
    background: var(--fn-leaf-200); color: var(--fn-forest-700); flex: none; }
.hub-count-body { flex: 1 1 auto; display: flex; flex-direction: column; min-width: 0; }
.hub-count-num { font-family: var(--fn-font-display); font-size: 1.55rem; line-height: 1.1; color: var(--fn-forest-900); }
.hub-count-word { font-family: var(--fn-font); font-size: .95rem; font-weight: 500; color: var(--fn-ink-700); margin-left: .35rem; }
.hub-count-sub { font-size: var(--fn-text-sm); color: var(--fn-ink-500); }
.hub-go { color: var(--fn-ink-300); font-size: 1.3rem; line-height: 1; flex: none; }

/* Weather — a prompt before the call (gently amber to invite the decision), a small status chip after. */
/* Weather, site-check, headcount and checks are ALL "a status row that opens a sheet" — one tier, so they now
   share one calm treatment: a cream card with a coloured icon badge as the only differentiator. (They used to be
   a cream tile, an amber gradient and a leaf gradient — three looks for the same verb.) The badge still carries
   the cue: amber sun = weather, leaf = checks/site. */
.hub-wx-prompt { display: flex; align-items: center; gap: .85rem; width: 100%; text-align: left; cursor: pointer;
    margin: 0 0 1.1rem; padding: .75rem 1rem; border-radius: var(--fn-radius);
    background: var(--fn-card); border: 1.5px solid var(--fn-line-strong);
    transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease; }
.hub-count { transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease; }
.hub-count:hover, .hub-wx-prompt:hover { border-color: var(--fn-leaf-400); box-shadow: var(--fn-shadow-sm); }
.hub-wx-ic { display: inline-grid; place-items: center; width: 40px; height: 40px; border-radius: 12px;
    background: var(--fn-sun-soft); color: var(--fn-amber-600); flex: none; }
.hub-wx-title { font-weight: 700; color: var(--fn-forest-900); }
/* Checks & reminders reuses the prompt layout but in the forest palette (not the amber weather treatment),
   with a 44px icon to line up with the headcount tile above it. */
.hub-prompt--checks { background: var(--fn-card); border-color: var(--fn-line-strong); }
.hub-prompt--checks .hub-wx-ic { width: 44px; height: 44px; border-radius: 13px; background: var(--fn-leaf-200); color: var(--fn-forest-600); }
.hub-wx-chip { display: inline-flex; align-items: center; gap: 6px; margin: 0 0 1.1rem; padding: 6px 13px;
    border-radius: var(--fn-radius-pill); font-size: var(--fn-text-sm); cursor: pointer; border: 1.5px solid var(--fn-line-strong); background: var(--fn-card); }
.hub-wx-chip.wx-go   { color: var(--fn-forest-800); border-color: var(--fn-leaf-400); background: var(--fn-leaf-200); }
.hub-wx-chip.wx-mod  { color: #8a5a12; border-color: var(--fn-amber-600); background: var(--fn-amber-200); }
.hub-wx-chip.wx-nogo { color: var(--fn-red-600); border-color: var(--fn-red-600); background: var(--fn-red-200); }
.hub-wx-note { color: var(--fn-ink-500); font-weight: 400; }
/* Once set, the weather chip sits in the top status row next to "In session" — compact, no bottom margin. */
.dash-top { justify-content: flex-start; gap: .5rem; flex-wrap: wrap; }
.dash-top .run-refresh { margin-left: auto; }
.hub-wx-chip--top { margin: 0; padding: 4px 11px; font-size: var(--fn-text-xs); }

/* Observations — the solid hero. */
/* The single hero action carries a firelight (ember) edge down its left — the one place on the hub the accent
   appears at size, marking "this is THE thing you do here" without another colour or box. */
.hub-hero { display: flex; align-items: center; gap: 1rem; width: 100%; text-align: left; cursor: pointer;
    margin: 0 0 .75rem; padding: 1.1rem 1.15rem; border: 0; border-radius: var(--fn-radius-lg);
    background: linear-gradient(135deg, var(--fn-forest-700), var(--fn-forest-900)); color: var(--fn-paper);
    box-shadow: var(--fn-shadow), inset 5px 0 0 var(--fn-ember); transition: transform .12s ease, box-shadow .12s ease; }
.hub-hero:hover { transform: translateY(-2px); box-shadow: var(--fn-shadow-lg), inset 5px 0 0 var(--fn-ember); }
.hub-hero:active { transform: translateY(0); }
.hub-hero-ic { display: inline-grid; place-items: center; width: 50px; height: 50px; border-radius: 15px;
    background: rgba(255, 255, 255, .15); color: var(--fn-sun-soft); flex: none; }
.hub-hero-body { flex: 1 1 auto; display: flex; flex-direction: column; gap: .15rem; min-width: 0; }
.hub-hero-title { font-family: var(--fn-font-display); font-size: 1.4rem; line-height: 1; }
.hub-hero-sub { font-size: var(--fn-text-sm); color: var(--fn-leaf-200); }
.hub-hero-go { font-family: var(--fn-font); font-size: 2.1rem; font-weight: 300; line-height: 1; color: var(--fn-sun-soft); flex: none; }

/* Secondary logs — two colour-coded cards. */
.hub-logs { display: grid; grid-template-columns: 1fr 1fr; gap: .7rem; margin: 0 0 1.1rem; }
.hub-log { position: relative; overflow: hidden; display: flex; align-items: center; text-align: left;
    cursor: pointer; min-height: 84px; padding: .85rem .95rem; border-radius: var(--fn-radius); border: 1.5px solid;
    transition: transform .12s ease, box-shadow .12s ease; }
.hub-log:hover { transform: translateY(-1px); box-shadow: var(--fn-shadow-sm); }
.hub-log:active { transform: scale(.985); }
.hub-log-body { position: relative; z-index: 1; display: flex; flex-direction: column; gap: .12rem; }
/* The icon now sits LARGE and faint in the card's right edge — a background motif, not a top badge that
   pushed the text down unevenly. Text stays left, vertically centred, so both cards read at the same height. */
.hub-log-ic { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); z-index: 0; opacity: .12; pointer-events: none; }
.hub-log-label { font-family: var(--fn-font); font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
    font-size: var(--fn-text-xs); color: var(--fn-ink-500); }
.hub-log-sub { font-family: var(--fn-font); font-weight: 700; font-size: 1.05rem; }
.hub-log--risk { background: linear-gradient(155deg, var(--fn-amber-200), var(--fn-card) 86%); border-color: var(--fn-amber-600); }
.hub-log--risk .hub-log-ic { color: var(--fn-amber-600); }
.hub-log--risk .hub-log-sub { color: #8a5a12; }
.hub-log--risk .dash-count { background: var(--fn-amber-600); }
.hub-log--incident { background: linear-gradient(155deg, var(--fn-red-200), var(--fn-card) 86%); border-color: var(--fn-red-600); }
.hub-log--incident .hub-log-ic { color: var(--fn-red-600); }
.hub-log--incident .hub-log-sub { color: var(--fn-red-600); }
.hub-log--incident .dash-count { background: var(--fn-red-600); }

/* Risk assessments — quiet reference link. */
.hub-ra-link { display: flex; align-items: center; gap: .55rem; width: 100%; text-align: left; cursor: pointer;
    margin: 0; padding: .7rem .3rem; background: none; border: 0; border-top: 1px solid var(--fn-line);
    color: var(--fn-ink-700); font-size: var(--fn-text-sm); }
.hub-ra-link .fn-icon { color: var(--fn-sky-600); }
.hub-ra-label { font-weight: 600; }
.hub-ra-status { color: var(--fn-ink-300); margin-left: auto; }

/* In-session references bar — safety/reference you might need WHILE running; each opens a sheet over the
   session so you never leave it. Sits at the foot of the hub. */
.refbar { display: flex; gap: .6rem; margin: 1.5rem 0 .25rem; padding-top: 1.1rem; border-top: 1px solid var(--fn-line); }
.refbar-item { flex: 1 1 0; display: flex; flex-direction: column; align-items: center; gap: .4rem; cursor: pointer;
    padding: .8rem .5rem; border-radius: var(--fn-radius); border: 1.5px solid var(--fn-line-strong);
    background: var(--fn-card); font: inherit; font-size: var(--fn-text-xs); font-weight: 700; text-transform: uppercase;
    letter-spacing: .04em; color: var(--fn-forest-800); text-align: center; line-height: 1.2;
    transition: transform .1s ease, border-color .12s ease, background .12s ease; }
.refbar-item:hover { border-color: var(--fn-leaf-400); background: var(--fn-paper-2); }
.refbar-item:active { transform: scale(.97); }
.refbar-item .fn-icon { color: var(--fn-forest-600); }
.refbar-item--eap .fn-icon { color: var(--fn-red-600); }

/* Emergency action plan — a clean label/value list; the phone number is a tap-to-call link. */
.eap { margin: .4rem 0 0; }
.eap-row { display: flex; flex-direction: column; gap: 1px; padding: .65rem 0; border-bottom: 1px solid var(--fn-line); }
.eap-row:last-child { border-bottom: 0; }
.eap-row dt { font-size: var(--fn-text-xs); text-transform: uppercase; letter-spacing: .05em; color: var(--fn-ink-300); font-weight: 700; }
.eap-row dd { margin: 0; font-size: 1.05rem; color: var(--fn-ink-900); }
.eap-mono { font-variant-numeric: tabular-nums; letter-spacing: .02em; }
.eap-row--call dd a { font-weight: 800; font-size: 1.2rem; color: var(--fn-red-600); text-decoration: none; }

/* Terms-acceptance row on signup — checkbox aligned with a short wrapping label. */
.checkbox-row { display: flex; align-items: flex-start; gap: .55rem; margin: .2rem 0 .4rem; font-size: var(--fn-text-sm); }
.checkbox-row input[type="checkbox"] { margin-top: .15rem; flex: none; width: 18px; height: 18px; }

/* Drill-in bottom sheet — the hub stays mounted underneath; a section slides up over it like a native sheet. */
.sheet-scrim { position: fixed; inset: 0; z-index: 60; background: rgba(20, 32, 26, .45); animation: sheet-scrim-in .2s ease both; }
.sheet {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 61; max-width: 720px; margin: 0 auto;
    max-height: 90vh; max-height: 90dvh; display: flex; flex-direction: column;   /* vh fallback if dvh unsupported */
    background: var(--fn-paper); border-radius: 22px 22px 0 0; box-shadow: 0 -10px 34px rgba(20, 32, 26, .28);
    padding: 0 1.1rem calc(1.1rem + env(safe-area-inset-bottom, 0px));
    animation: sheet-up .3s cubic-bezier(.2, .82, .25, 1) both;
}
.sheet-grip {
    align-self: center; flex: none; width: 42px; height: 5px; margin: 11px 0 8px; padding: 0;
    border: 0; border-radius: 999px; background: var(--fn-line-strong); cursor: pointer;
}
.sheet-grip::after { content: ""; position: absolute; left: 0; right: 0; top: -10px; height: 28px; }   /* bigger tap target */
.sheet-grip { position: relative; }
/* flex:1 + min-height:0 is what actually lets a flex child scroll: without it, long content overflows the
   sheet (pushing the save button off-screen / behind the tab bar) instead of scrolling inside it. */
.sheet-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; padding-bottom: .4rem; }
/* Drill-in forms are compact: the primary action doesn't need to be full-bleed XL, and it wants clear space
   from the field above it (the old full-page sizing felt huge and crowded once these moved into a sheet). */
.sheet-body .btn--xl { min-height: 48px; font-size: 1rem; margin-top: 1rem; }
.sheet-body .card input, .sheet-body .card textarea { margin-bottom: .15rem; }
.sheet-body > .card:first-child { margin-top: .2rem; }
@keyframes sheet-up { from { transform: translateY(100%); } to { transform: none; } }
@keyframes sheet-scrim-in { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .sheet, .sheet-scrim { animation: none; } }
/* Desktop: the field sheet becomes a centred dialog rather than a phone bottom-sheet stranded at the screen edge. */
@media (min-width: 760px) {
    .sheet {
        top: 50%; bottom: auto; left: 50%; right: auto;
        width: min(720px, 92vw); max-height: 86vh;
        transform: translate(-50%, -50%);
        border-radius: 20px;
        padding: .3rem 1.5rem 1.5rem;
        animation: sheet-pop .2s ease both;
    }
    @keyframes sheet-pop {
        from { opacity: 0; transform: translate(-50%, calc(-50% + 14px)); }
        to   { opacity: 1; transform: translate(-50%, -50%); }
    }
}

/* Sticky page action bar — a form's ONE home for its primary action. Pinned to the bottom of the
   scroll so Save is never below the fold on a tall form; secondary/back sits left as a ghost, the
   primary right. Mirrors .focus-bar (solid bg, no backdrop-filter — cheap to paint on field phones).
   Use for a page's single bottom action row; .run-actions stays for in-flow / multi-row cases. */
.page-actions {
    position: sticky; bottom: 0; z-index: 30;
    display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
    margin: 2rem 0 0; padding: 1rem 0 calc(1rem + env(safe-area-inset-bottom, 0px));
    background: var(--fn-paper);
    border-top: 1px solid var(--fn-line);
}
.page-actions .btn--xl { width: auto; min-width: 230px; }
.page-actions .pa-spacer { flex: 1 1 auto; }   /* pushes the primary to the right of any secondary/back */

/* End-of-session bar — the leader's single primary action, pinned to the foot of the session hub so it's
   always thumb-reachable without scrolling. Full-bleed (it's THE action here), solid paper bg so hub content
   scrolls cleanly under it. Mirrors the .page-actions sticky chrome. */
.run-end {
    position: sticky; bottom: 0; z-index: 30;
    margin: 1.4rem 0 0; padding: .8rem 0 calc(.8rem + env(safe-area-inset-bottom, 0px));
    background: var(--fn-paper); border-top: 1px solid var(--fn-line);
}
.run-end .btn--xl { width: 100%; }

/* The site's day forecast, shown in the weather sheet to inform (not replace) the leader's go/no-go call. */
.wx-forecast {
    display: flex; align-items: center; gap: .5rem;
    background: var(--fn-sky-50, var(--fn-paper-2)); border: 1px solid var(--fn-line);
    border-radius: var(--fn-radius); padding: .6rem .75rem; margin: .2rem 0 .5rem;
    font-size: .95rem; color: var(--fn-forest-900); font-weight: 600;
}
.wx-forecast svg { color: var(--fn-amber-600); flex: none; }
/* Segmented control — a recessed paper "track" holding raised, pressed-in tabs. Gentle radius + tabs inset
   from the track edge (was a full pill whose 24px corner clipped labels like "Away"); the selected tab reads
   as pressed-in, matching the buttons. */
.seg { display: inline-flex; gap: 3px; padding: 3px; margin: 8px 0;
    background: var(--fn-paper-2); border: 1.5px solid var(--fn-line-strong);
    border-radius: var(--fn-radius); box-shadow: inset 0 1px 2px rgba(40,52,42,.09); }
.seg-btn { min-height: 44px; padding: 0 18px; border: none; background: transparent; white-space: nowrap;
    border-radius: calc(var(--fn-radius) - 3px); font: inherit; font-weight: 600; cursor: pointer;
    color: var(--fn-forest-800); transition: background .12s ease, color .12s ease, box-shadow .12s ease; }
.seg-btn:not(.is-on):hover { background: rgba(74,97,71,.08); }
.seg-btn.is-on { background: var(--fn-card); color: var(--fn-forest-800);
    box-shadow: 0 1px 2px rgba(40,52,42,.12), 0 2px 5px rgba(74,55,39,.10); }   /* raised, pressed-in tab */
.seg-btn.is-on.ok { background: var(--fn-forest-600); color: #fff; }
.seg-btn.is-on.warn { background: var(--fn-amber-600); color: #fff; }
.seg-btn.is-on.danger { background: var(--fn-red-600); color: #fff; }
.seg-sm { padding: 3px; }
.seg-sm .seg-btn { min-height: 40px; padding: 0 14px; }
/* The go/no-go call is the whole point of the weather sheet — it gets the full width and three equal targets,
   not three little tabs huddled in the corner. */
.seg--full { display: flex; width: 100%; }
.seg--full .seg-btn { flex: 1 1 0; min-width: 0; padding: 0 8px; min-height: 52px; font-size: 1rem; }
/* ---- Register "Who's here?" — warm, scannable, field-friendly. Monogram per child, medical info as chips,
   a clear Present/Absent toggle, and absent children fade back so you can glance who's actually in. ---- */
/* One list read top to bottom — children, then the adults with them. It used to be two columns, which on a
   desktop sheet squeezed the names to a sliver and stacked the toggles into a wall of buttons. */
.reg-stack { display: flex; flex-direction: column; gap: 1.25rem; }
/* Tapping "5 adults" or the ratio in the header opens the register ON the adults — landing you at the top of a
   long list of children and making you scroll to what you asked for is just a wrong answer. */
.reg-stack--adults .reg-adults { order: -1; }
/* Same for a check tapped on the timeline: the sheet leads with the one you asked for, and marks it. */
.chk-cat.is-focus { border-color: var(--fn-forest-600); box-shadow: var(--fn-shadow-sm); }
/* "Tick all" does the whole group at once. Outlined, NOT filled: a filled green chip is what a done/selected one
   looks like everywhere else in here, so filling this read as "all 8 are already done" rather than as the button
   that does them. It's an action, so it looks like an action. */
.chip--all { background: transparent; border: 1.5px solid var(--fn-forest-700); color: var(--fn-forest-700); font-weight: 700; }
.chip--all:hover { background: var(--fn-forest-700); color: var(--fn-card); }
.reg-head { display: flex; align-items: baseline; justify-content: space-between; gap: .5rem; margin-bottom: .5rem; }
.reg-count { font-family: var(--fn-font); font-size: var(--fn-text-sm); font-weight: 700; color: var(--fn-forest-700); white-space: nowrap; }
.reg-count-of { color: var(--fn-ink-300); font-weight: 500; }
.reg-list { display: flex; flex-direction: column; }
.reg-child { padding: .8rem 0; border-bottom: 1px solid var(--fn-line); transition: opacity .15s ease; }
.reg-child:first-child { padding-top: .2rem; }
.reg-child:last-child { border-bottom: 0; padding-bottom: .2rem; }
.reg-child.is-absent { opacity: .5; }
.reg-child-id { display: flex; align-items: flex-start; gap: .7rem; }
.reg-avatar { flex: none; width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center;
    font-family: var(--fn-font-display); font-size: 1.05rem; font-weight: 600; color: #fff; }
.reg-avatar--0 { background: var(--fn-forest-600); }
.reg-avatar--1 { background: var(--fn-bark-700); }
.reg-avatar--2 { background: var(--fn-sky-600); }
.reg-avatar--3 { background: var(--fn-amber-600); }
.reg-avatar--4 { background: var(--fn-forest-800); }
.reg-child-text { min-width: 0; flex: 1 1 auto; }
.reg-name { font-family: var(--fn-font-display); font-size: 1.1rem; color: var(--fn-forest-900); display: block; line-height: 1.2; }
.reg-alerts { display: flex; flex-wrap: wrap; gap: .3rem; margin-top: .3rem; }
.reg-chip { display: inline-flex; align-items: center; gap: 4px; padding: 2px 9px; border-radius: var(--fn-radius-pill);
    font-size: var(--fn-text-xs); font-weight: 600; }
.reg-chip--allergy { background: var(--fn-red-200); color: var(--fn-red-600); }
.reg-chip--med { background: var(--fn-amber-200); color: #8a5a12; }
.reg-chip--cond { background: var(--fn-paper-2); color: var(--fn-ink-700); }
.reg-chip--nophoto { background: var(--fn-paper-2); color: var(--fn-ink-500); }
.reg-toggle { display: flex; gap: .45rem; margin-top: .65rem; }
.reg-tog { flex: 1; min-height: 44px; border-radius: var(--fn-radius-pill); border: 1.5px solid var(--fn-line-strong);
    background: var(--fn-card); font: inherit; font-weight: 700; color: var(--fn-ink-500); cursor: pointer;
    transition: background .12s ease, color .12s ease, border-color .12s ease; }
.reg-tog:active { transform: scale(.98); }
.reg-tog--in.is-on { background: var(--fn-forest-600); border-color: var(--fn-forest-600); color: #fff; }
.reg-tog--out.is-on { background: var(--fn-bark-700); border-color: var(--fn-bark-700); color: #fff; }
.reg-tog--left.is-on { background: var(--fn-amber-600); border-color: var(--fn-amber-600); color: #fff; }
.reg-child.is-left { opacity: .8; }
.med-alert { color: var(--fn-red-600); font-weight: 700; font-size: .85rem; margin-top: 3px; }

/* Adults, below the children and full width: names in columns rather than one tall skinny stack, and the
   ratio stated once in the card head (no giant number block). */
.reg-adult-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 0 1.25rem; }
.reg-adult { display: flex; justify-content: space-between; align-items: center; gap: .5rem;
    padding: .4rem 0; border-bottom: 1px solid var(--fn-line); }
.reg-adult-name { min-width: 0; }

/* "Add an adult" — one quiet line under the adults, not a grid of fat pills. The names sit inline with the
   label; the last chip is dashed, because naming someone who isn't on the staff list is a different kind of
   act from tapping someone who is. */
.reg-addadult { display: flex; align-items: center; flex-wrap: wrap; gap: .35rem; margin-top: .8rem; }
.reg-addadult-label { margin-right: .2rem; color: var(--fn-ink-500); font-size: var(--fn-text-sm); }
.reg-addadult-chip { min-height: 30px; padding: 2px 11px; border-radius: var(--fn-radius-pill);
    border: 1px solid var(--fn-line-strong); background: transparent; font: inherit; font-size: var(--fn-text-sm);
    color: var(--fn-forest-700); white-space: nowrap; cursor: pointer;
    transition: background .12s ease, border-color .12s ease; }
.reg-addadult-chip:hover { background: var(--fn-paper-2); border-color: var(--fn-forest-600); }
.reg-addadult-chip.is-other { border-style: dashed; color: var(--fn-ink-500); }
.reg-addadult-form { display: flex; align-items: center; gap: 8px; margin-top: .8rem; }
.reg-addadult-form input { flex: 1 1 auto; margin: 0; }

/* Roomy enough for the name and its toggles to sit side by side — so a register of 17 children is a list you
   scroll, not a page of buttons. Below this the toggles keep their full-width, thumb-sized phone layout. */
@media (min-width: 700px) {
    .reg-child { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; column-gap: 1.25rem; }
    .reg-toggle { margin-top: 0; width: 300px; }
    .reg-more { grid-column: 1 / -1; }
}

/* "Who's taking the register?" — the app's one-time choice per session per device (#41938). Two big answers,
   each with its consequence written under it; no small print, no guessing. */
.reg-who-choices { display: flex; flex-direction: column; gap: .6rem; margin-top: 1rem; }
.reg-who-btn { display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
    width: 100%; min-height: 64px; padding: .8rem 1.1rem; text-align: left; }
.reg-who-lead { font-weight: 700; }
.reg-who-sub { font-size: var(--fn-text-xs); font-weight: 500; opacity: .82; white-space: normal; line-height: 1.35; }

/* Register: emergency contacts & permissions, collapsed until needed (#41571 — the paper-register replacement). */
.reg-more { margin-top: .6rem; }
.reg-add { margin-top: .9rem; padding-top: .6rem; border-top: 1px dashed var(--fn-line); }

/* GROUP RAIL (#41606): pick a group — a swipeable strip of group cards on a phone, a left rail on a wide
   screen. This is the pattern for FILTERING BY GROUP (the Diary, the risk library); .subnav above is for
   navigating between a section's SCREENS (Settings, a term). The .diary-* names are kept as aliases so
   nothing that used them breaks. */
.page-head-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.grouprail, .diary-groups { display: flex; align-items: stretch; gap: .5rem; margin: 0 0 1.3rem; overflow-x: auto;
    padding: 2px 0 .45rem; scroll-snap-type: x proximity; }
.grouprail::-webkit-scrollbar, .diary-groups::-webkit-scrollbar { height: 6px; }
.grouprail::-webkit-scrollbar-thumb, .diary-groups::-webkit-scrollbar-thumb { background: var(--fn-line-strong); border-radius: 3px; }
.grouprail-card, .diary-gcard { flex: 0 0 auto; scroll-snap-align: start; width: 140px; display: flex; flex-direction: column;
    align-items: flex-start; gap: 1px; text-align: left; cursor: pointer; padding: .5rem .65rem;
    border: 1.5px solid var(--fn-line); border-radius: var(--fn-radius); background: var(--fn-card);
    color: var(--fn-ink-700); text-decoration: none; }
.grouprail-card:hover, .diary-gcard:hover { border-color: var(--fn-leaf-400); background: var(--fn-paper-2); }
.grouprail-card.is-active, .diary-gcard.is-active { border-color: var(--fn-forest-600); background: var(--fn-leaf-200); }
.grouprail-name, .diary-gcard-name { font-family: var(--fn-font-display); font-weight: 700; font-size: .92rem; line-height: 1.15; color: var(--fn-forest-900); }
.grouprail-meta, .diary-gcard-meta { font-size: var(--fn-text-xs); color: var(--fn-ink-500); }
.diary-gcard-main { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; border: 0; background: none;
    padding: 0; cursor: pointer; text-align: left; width: 100%; }
/* Split tile: the name/count is one target, the cog its own — a divider + faint tint make the manage
   segment obviously separate, so a near-miss no longer lands on the filter button. */
.diary-gcard--split { flex-direction: row; align-items: stretch; gap: 0; padding: 0; overflow: hidden; }
.diary-gcard--split .diary-gcard-main { flex: 1 1 auto; min-width: 0; padding: .5rem .65rem; border-radius: 0; }
.diary-gcard-edit { flex: 0 0 auto; align-self: stretch; display: flex; align-items: center; justify-content: center;
    padding: 0 .6rem; color: var(--fn-forest-700); text-decoration: none;
    border-left: 1.5px solid var(--fn-line); background: var(--fn-paper-2); }
.diary-gcard-edit:hover { background: var(--fn-leaf-200); color: var(--fn-forest-900); }
.diary-gcard--split.is-active .diary-gcard-edit { border-left-color: var(--fn-forest-600); }
.grouprail-card--new, .diary-gcard--new { width: auto; justify-content: center; align-items: center; font-weight: 700; color: var(--fn-forest-700);
    border-style: dashed; background: transparent; white-space: nowrap; }

/* Desktop: the group cards stand as a left rail with the content alongside (the hubs' master-detail
   pattern). On a phone they stay the swipeable strip above the lists. */
@media (min-width: 1000px) {
    .grouprail-shell, .diary-shell { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: 1.75rem; align-items: start; }
    .grouprail-shell .grouprail-main, .diary-shell .diary-main { min-width: 0; }
    .grouprail-shell .grouprail, .diary-shell .diary-groups { flex-direction: column; align-items: stretch; overflow-x: visible; margin: 0; padding: 0; }
    .grouprail-shell .grouprail-card, .diary-shell .diary-gcard { width: auto; }
    .grouprail-shell .grouprail-card--new, .diary-shell .diary-gcard--new { padding: .6rem .65rem; }
}

/* Child page "Groups & sessions" — current state + explicit add actions that reveal a picker (#41608). */
.enrol-now { margin: 0 0 .85rem; display: flex; flex-direction: column; gap: .45rem; }
.enrol-now-row { display: flex; gap: .6rem; align-items: baseline; }
.enrol-now-row dt { flex: 0 0 80px; font-weight: 700; color: var(--fn-ink-500); font-size: .82rem; }
.enrol-now-row dd { margin: 0; flex: 1 1 auto; min-width: 0; }
.enrol-chips { display: flex; flex-wrap: wrap; gap: 4px; }
.enrol-actions { display: flex; gap: .5rem; flex-wrap: wrap; }
.enrol-pick { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; margin-top: .6rem; }
.enrol-pick select { flex: 1 1 220px; min-width: 0; margin: 0; }
.reg-more > summary { cursor: pointer; font-size: .82rem; font-weight: 600; color: var(--fn-forest-700); list-style: none; }
.reg-more > summary::-webkit-details-marker { display: none; }
.reg-more > summary::before { content: "▸ "; color: var(--fn-ink-500); }
.reg-more[open] > summary::before { content: "▾ "; }
.reg-more-body { margin: .5rem 0 .2rem; padding: .6rem .7rem; background: var(--fn-paper); border: 1px solid var(--fn-line); border-radius: var(--fn-radius-sm); display: flex; flex-direction: column; gap: .7rem; }
.reg-more-block { display: flex; flex-direction: column; gap: .3rem; }
.reg-more-h { font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--fn-ink-500); }
.reg-contact { display: flex; align-items: center; justify-content: space-between; gap: .5rem; flex-wrap: wrap; }
.reg-contact-who { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; }
.reg-call { display: inline-flex; align-items: center; gap: 5px; padding: 5px 12px; border-radius: var(--fn-radius-pill);
    background: var(--fn-forest-600); color: #fff; font-weight: 700; font-size: .85rem; text-decoration: none; white-space: nowrap; }
.reg-call:active { transform: scale(.98); }
.reg-consents { display: flex; flex-wrap: wrap; gap: .3rem; }
.reg-consent { display: inline-flex; align-items: center; gap: 3px; padding: 2px 9px; border-radius: var(--fn-radius-pill);
    font-size: .78rem; font-weight: 600; background: var(--fn-paper-2); color: var(--fn-ink-500); }
.reg-consent.is-on { background: var(--fn-leaf-200, #e3f0d6); color: var(--fn-forest-700); }
.reg-consent.is-off { background: var(--fn-red-200); color: var(--fn-red-600); }

/* Daily site check (#41570): a tick-list of hazards, each with an optional note + remove. */
.sc-list { display: flex; flex-direction: column; gap: .5rem; margin: .3rem 0 .8rem; }
.sc-item { display: flex; align-items: flex-start; gap: .6rem; padding: .55rem .6rem; background: var(--fn-paper);
    border: 1px solid var(--fn-line); border-radius: var(--fn-radius-sm); transition: background .12s ease, border-color .12s ease; }
.sc-item.is-clear { background: var(--fn-leaf-200, #e9f3df); border-color: var(--fn-forest-600); }
.sc-tick { flex: none; width: 30px; height: 30px; border-radius: 8px; border: 2px solid var(--fn-line-strong);
    background: var(--fn-card); color: #fff; font-weight: 800; cursor: pointer; line-height: 1; }
.sc-item.is-clear .sc-tick { background: var(--fn-forest-600); border-color: var(--fn-forest-600); }
.sc-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: .3rem; }
.sc-label { font-weight: 600; font-size: .92rem; }
.sc-note { width: 100%; font: inherit; font-size: .85rem; padding: 5px 8px; border: 1px solid var(--fn-line); border-radius: var(--fn-radius-sm); background: var(--fn-card); }
.sc-del { flex: none; width: 28px; height: 28px; border: 0; background: transparent; color: var(--fn-ink-500); font-size: 20px; line-height: 1; cursor: pointer; }
.sc-del:hover { color: var(--fn-red-600); }
.sc-add { display: flex; gap: .5rem; }
.sc-add input { flex: 1 1 auto; font: inherit; padding: 8px 10px; border: 1px solid var(--fn-line); border-radius: var(--fn-radius-sm); background: var(--fn-card); }

/* Sub-nav shell: a persistent left sub-menu + the section's content (main nav → sub-menu → content). Used by
   Settings and by a term's own pages — anywhere a thing has several screens and you should always be able to see
   which one you're on. The .settings-* names are kept as aliases so nothing that used them breaks. */
.subnav-shell, .settings-shell { display: flex; gap: 1.5rem; align-items: flex-start; }
.subnav, .settings-subnav { flex: 0 0 210px; position: sticky; top: 1rem; display: flex; flex-direction: column; gap: 2px; }
.subnav-head, .settings-subnav-head { font-family: var(--fn-font-display); font-size: .8rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: .05em; color: var(--fn-ink-500); padding: 0 .7rem .4rem; }
.subnav-link, .settings-subnav-link { display: block; padding: .55rem .7rem; border-radius: var(--fn-radius-sm); color: var(--fn-ink-700);
    text-decoration: none; font-weight: 600; border-left: 3px solid transparent; }
.subnav-link:hover, .settings-subnav-link:hover { background: var(--fn-paper-2); }
.subnav-link.active, .settings-subnav-link.active { background: var(--fn-leaf-200); color: var(--fn-forest-800); border-left-color: var(--fn-forest-600); }
.subnav-content, .settings-content { flex: 1 1 auto; min-width: 0; }
/* A quiet "back to the thing this belongs to" link at the top of the sub-menu. */
.subnav-back { display: block; padding: 0 .7rem .5rem; font-size: var(--fn-text-sm); color: var(--fn-ink-500); text-decoration: none; }
.subnav-back:hover { color: var(--fn-forest-700); }
/* On desktop the <details> is invisible machinery: no summary, and its children flow as the column they always
   were. It only becomes a disclosure on a phone. */
.subnav-drop { display: flex; flex-direction: column; gap: 2px; }
.subnav-drop > summary { display: none; }

/* On a phone the sub-menu can't be a column beside the content — there's no beside. Two earlier answers were
   wrong: wrapped links read as a paragraph rather than as navigation, and a sideways-scrolling strip of pills
   hid half its own destinations off both edges (it tells you there's more without telling you what). Settings is
   eight long-named places you visit rarely and need to FIND — not three peers you flip between — so it collapses
   to one control naming where you are, and opening it shows every section at once. */
@media (max-width: 820px) {
    .subnav-shell, .settings-shell { flex-direction: column; gap: .75rem; }
    .subnav, .settings-subnav { flex-basis: auto; position: static; display: block; width: 100%; min-width: 0; }
    .subnav-drop { display: block; }

    /* The closed control. Looks like the select it behaves as. */
    .subnav-drop > summary {
        display: flex; align-items: center; justify-content: space-between; gap: .6rem;
        padding: .7rem .9rem; border: 1.5px solid var(--fn-card-edge); border-radius: var(--fn-radius);
        background: var(--fn-card); box-shadow: var(--fn-shadow-sm);
        font-weight: 600; color: var(--fn-forest-900); cursor: pointer; list-style: none;
    }
    .subnav-drop > summary::-webkit-details-marker { display: none; }   /* Safari's default triangle */
    .subnav-drop > summary::after { content: "▾"; color: var(--fn-ink-500); font-size: .9rem; }
    .subnav-drop[open] > summary { border-radius: var(--fn-radius) var(--fn-radius) 0 0; border-bottom-color: transparent; }
    .subnav-drop[open] > summary::after { content: "▴"; }

    /* The open list — one card hanging off the control, every section visible, nothing clipped. */
    .subnav-drop[open] {
        border: 1.5px solid var(--fn-card-edge); border-radius: var(--fn-radius);
        background: var(--fn-card); box-shadow: var(--fn-shadow);
    }
    .subnav-drop[open] > summary { border: 0; border-bottom: 1px solid var(--fn-line); box-shadow: none; }
    .subnav-drop > .subnav-head, .subnav-drop > .settings-subnav-head { display: none; }   /* the summary says it */
    .subnav-drop > .subnav-back { padding: .6rem .9rem; }
    .subnav-drop > .subnav-link, .subnav-drop > .settings-subnav-link {
        border-left: 0; border-radius: 0; padding: .75rem .9rem;
    }
    .subnav-drop > .subnav-link.active, .subnav-drop > .settings-subnav-link.active {
        border-left: 0; background: var(--fn-leaf-200); color: var(--fn-forest-800);
    }
}
.sc-signoffs { margin: .6rem 0; padding-top: .5rem; border-top: 1px solid var(--fn-line); }

/* Session reminders / on-the-day checks (#41572) — a card per category with a per-child tick-list. */
.chk-cat { margin-top: .8rem; }
.chk-cat-title { margin: 0 0 .4rem; font-size: 1rem; }

/* The check sheet leads with WHAT IT IS and WHETHER IT'S DONE. Everything under that is the optional detail —
   who you actually told — because being here is what makes the round done, not ticking every name. */
.chk-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap;
    margin-bottom: .6rem; }
.chk-title { display: inline-flex; align-items: center; gap: 8px; margin: 0;
    font-family: var(--fn-font-display); font-weight: 600; font-size: 1.15rem; color: var(--fn-forest-900); }
.chk-state { display: inline-flex; align-items: center; gap: 7px; padding: 4px 6px 4px 10px; border-radius: 999px;
    background: var(--fn-leaf-200, #e9f3df); color: var(--fn-forest-800); font-size: .82rem; font-weight: 600; }
.chk-state-tick { display: grid; place-items: center; width: 17px; height: 17px; border-radius: 50%;
    background: var(--fn-forest-600); color: #fff; font-size: .66rem; }
.chk-undo { border: 0; background: none; cursor: pointer; padding: 2px 6px; border-radius: 999px;
    font: 600 .78rem var(--fn-font); color: var(--fn-forest-700); text-decoration: underline; }
.chk-undo:hover { color: var(--fn-red-600); }
.chk-lead { margin: 0 0 8px; font-size: .88rem; font-weight: 600; color: var(--fn-forest-900); }
.chk-count { margin: 10px 0 0; font-size: .85rem; color: var(--fn-ink-300); }
/* Notes are the exception, not the rule — so they fold away rather than putting a text box against every name. */
.chk-notes { margin-top: 10px; }
.chk-notes summary { cursor: pointer; font-size: .85rem; font-weight: 600; color: var(--fn-forest-700); }
.chk-note-row { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
.chk-note-who { flex: 0 0 88px; font-weight: 700; font-size: .85rem; }
/* A parent request is a thing someone said, not a child — it reads as a line with a tick, not a grid chip. */
.chk-req { display: flex; align-items: center; gap: .5rem; padding: .45rem .55rem; margin-bottom: .45rem;
    background: var(--fn-paper); border: 1px solid var(--fn-line); border-radius: var(--fn-radius-sm); }
.chk-req.is-done { background: var(--fn-leaf-200, #e9f3df); border-color: var(--fn-forest-600); }
.chk-req.is-done .chk-tick { background: var(--fn-forest-600); border-color: var(--fn-forest-600); color: #fff; }
.chk-req-text { flex: 1 1 auto; min-width: 0; font-size: .9rem; }
.chk-req.is-done .chk-req-text { color: var(--fn-ink-300); text-decoration: line-through; }

.chk-list { list-style: none; padding: 0; margin: 0 0 .5rem; display: flex; flex-direction: column; gap: .45rem; }
.chk-item { display: flex; align-items: center; gap: .5rem; padding: .45rem .55rem; background: var(--fn-paper);
    border: 1px solid var(--fn-line); border-radius: var(--fn-radius-sm); }
.chk-item.is-done { background: var(--fn-leaf-200, #e9f3df); border-color: var(--fn-forest-600); }
.chk-tick { flex: none; width: 28px; height: 28px; border-radius: 8px; border: 2px solid var(--fn-line-strong);
    background: var(--fn-card); color: #fff; font-weight: 800; cursor: pointer; line-height: 1; }
.chk-item.is-done .chk-tick { background: var(--fn-forest-600); border-color: var(--fn-forest-600); }
.chk-body { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: .5rem; }
.chk-child { font-weight: 700; font-size: .9rem; white-space: nowrap; }
.chk-note { flex: 1 1 auto; min-width: 0; font: inherit; font-size: .85rem; padding: 5px 8px; border: 1px solid var(--fn-line); border-radius: var(--fn-radius-sm); background: var(--fn-card); }
.chk-del { flex: none; width: 26px; height: 26px; border: 0; background: transparent; color: var(--fn-ink-500); font-size: 19px; line-height: 1; cursor: pointer; }
.chk-del:hover { color: var(--fn-red-600); }
.chk-add { display: flex; gap: .5rem; margin-top: .3rem; }
.chk-add input { flex: 1 1 auto; font: inherit; padding: 8px 10px; border: 1px solid var(--fn-line); border-radius: var(--fn-radius-sm); background: var(--fn-card); }

/* Body map (safeguarding injury locations) */
.bodymap { display: flex; gap: 1.25rem; flex-wrap: wrap; margin: 6px 0; }
.bodymap-cap { font-weight: 600; font-size: .85rem; color: var(--fn-ink-500); margin-bottom: 2px; text-align: center; }
.bodymap-svg { width: 130px; height: auto; touch-action: manipulation; }
.bodymap-zone { fill: transparent; stroke: var(--fn-forest-500); stroke-width: 1; stroke-dasharray: 2 2; cursor: pointer; opacity: .5; transition: fill .1s ease, opacity .1s ease; }
.bodymap-zone:hover { opacity: .9; }
.bodymap-zone.on { fill: var(--fn-red-600); stroke: var(--fn-red-600); opacity: .8; stroke-dasharray: none; }
.stepper-ctl { display: flex; align-items: center; gap: 12px; }
.stepper-ctl .btn { min-height: 44px; min-width: 44px; padding: 0; font-size: 1.4rem; }
.stepper-num { font-family: var(--fn-font-display); font-size: 1.8rem; min-width: 40px; text-align: center; }
.chip-grid { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
.chip-grid .chip { cursor: pointer; }
.feed { list-style: none; margin: 0; padding: 0; }
.feed li { padding: 9px 0; border-bottom: 1px solid var(--fn-line); display: flex; gap: 8px; align-items: baseline; }
@media (max-width: 900px) { .run-grid { grid-template-columns: 1fr; } }
/* Two-column form layout — fills desktop width, stacks to one column on mobile. */
.form-2col { display: grid; grid-template-columns: 1fr 1fr; gap: 1.25rem; align-items: start; max-width: 1060px; }
.form-2col > .form-col { display: flex; flex-direction: column; gap: 1.25rem; min-width: 0; }
@media (max-width: 900px) { .form-2col { grid-template-columns: 1fr; } }
/* Day-of-week toggles — clearly OFF (dashed outline) vs ON (filled green), so an empty selection is obvious. */
.day-toggle { min-height: 40px; padding: 0 16px; border-radius: var(--fn-radius-pill); cursor: pointer;
    background: transparent; border: 1.5px dashed var(--fn-line-strong); color: var(--fn-forest-700);
    font-size: var(--fn-text-sm); font-weight: 600; transition: background .12s ease, border-color .12s ease, color .12s ease; }
.day-toggle:hover { border-color: var(--fn-forest-500); }
.day-toggle.on { background: var(--fn-forest-600); border: 1.5px solid var(--fn-forest-700); color: #fff; }
.live-status { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
/* In-session RA reference (collapsible, rendered from the session's snapshot) */
.ra-ref { margin: 0 0 14px; border: 1.5px solid var(--fn-line-strong); border-radius: var(--fn-radius-sm); background: var(--fn-paper-2); overflow: hidden; }
.ra-ref > summary { cursor: pointer; padding: 11px 14px; font-weight: 600; color: var(--fn-forest-800); list-style: none; min-height: 44px; display: flex; align-items: center; }
.ra-ref > summary::-webkit-details-marker { display: none; }
.ra-ref[open] > summary { border-bottom: 1px solid var(--fn-line); }
.ra-ref-item { padding: 10px 14px; border-bottom: 1px solid var(--fn-line); }
.ra-ref-item:last-child { border-bottom: none; }
.ra-ref-head { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin-bottom: 4px; flex-wrap: wrap; }
.ra-ref-head .chip { flex: 0 0 auto; }
.live-actions { display: flex; width: 100%; margin: 0 0 1.25rem; }
.live-actions .seg-btn { flex: 1; padding: 0 8px; }
.run-stage-head { font-family: var(--fn-font-hand); font-size: 1.3rem; color: var(--fn-forest-700); margin: 0 0 8px; }
.run-stage-head strong { color: var(--fn-forest-900); }
.run-refresh { margin-left: 10px; padding: 3px 10px; min-height: 0; font-size: .8rem; font-weight: 600;
    background: var(--fn-paper-2); border: 1.5px solid var(--fn-line-strong); border-radius: var(--fn-radius-pill);
    color: var(--fn-forest-700); cursor: pointer; vertical-align: middle; }
.run-refresh:disabled { opacity: .5; cursor: default; }
/* Just-refreshed: the control becomes its own confirmation — no separate stray line of text. */
.run-refresh.is-fresh, .btn.btn--fresh { background: var(--fn-leaf-200); border-color: var(--fn-leaf-400); color: var(--fn-forest-800); }
.run-refresh.is-fresh:disabled, .btn.btn--fresh:disabled { opacity: 1; }
/* Helper (read-only) session view header */
.helper-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; margin-bottom: 1.25rem; flex-wrap: wrap; }
.helper-head .btn { flex: 0 0 auto; }

/* ═══════════════════════════════════════════════════════════════════════════════════════════════════════
   THE SESSION HUB — the day, down one page.
   header = what's true right now · timeline = what happened · bar = what you can do.
   Colour is never decoration here: a card is always paper, and the only colour is a 3px left rule and a
   node on the spine saying WHAT KIND of thing happened. That keeps amber and red meaning "hazard".
   ═══════════════════════════════════════════════════════════════════════════════════════════════════════ */

/* The runner takes the whole column: the header band, the treeline and the action bar all run edge to edge,
   while the reading content stays in a comfortable column inside them. Without this the focus shell's 980px
   cap would crop the woodland to the middle of the page.

   BOTH wrappers have to give way, not just the focus shell. .fn-content carries the app's own page padding and
   a 1320px cap, so leaving it alone left the session inset — paper showing down both sides and, worse, a strip
   of it UNDER the action bar, which is why the bar could never reach the bottom of the window. */
.fn-focus:has(.run-hub) { max-width: none; padding: 0; }
.fn-content:has(.run-hub) { max-width: none; padding: 0; animation: none; }
/* The sidebar's torn right edge is painted with the PAGE's paper gradient, so it dissolves into a normal page.
   Against a full-bleed session it has nothing to dissolve into — it just reads as a 14px gap between the nav and
   the session. Butt them together instead; the session is the one page with no paper for the teeth to sit on. */
.fn-shell:has(.run-hub) .fn-sidebar::after { display: none; }

/* A full-height root is what the action bar sticks TO. Bar is the last child with `margin-top: auto`, so on a
   short session it sits at the bottom of the screen, and on a long one it pins there while the log scrolls.
   Capped and centred: at a desk the content column is ~1300px, and letting the stats strip stretch across all
   of it turned the header into a spreadsheet. On a phone / in the app the viewport is under the cap, so it's
   full-bleed there, which is what the woodland at the foot needs. */
.run-hub { display: flex; flex-direction: column; min-height: 100dvh; width: 100%; }

/* ── HEADER. Sticky: the numbers you'd be asked for in an emergency never scroll away. ── */
.run-hd { position: sticky; top: 0; z-index: 20; padding: 0;
    background: var(--fn-paper); border-bottom: 1px solid var(--fn-line); }
.run-hd-title { display: flex; align-items: baseline; gap: 10px; padding: 10px 18px 8px; width: 100%; }
.run-hd-place { margin: 0; font-family: var(--fn-font-display); font-weight: 600; font-size: 1.5rem; line-height: 1.15;
    color: var(--fn-forest-900); background: var(--fn-underline) no-repeat left bottom / 100% 7px; padding-bottom: 6px; }
.run-hd-date { font-family: var(--fn-font-hand); font-size: 1.2rem; color: var(--fn-moss); line-height: 1; }
.run-hd-right { margin-left: auto; display: inline-flex; align-items: center; gap: 10px; flex: 0 0 auto; }
.run-hd-concern { display: inline-flex; align-items: center; gap: 5px; flex: 0 0 auto;
    color: var(--fn-red-600); font-weight: 600; font-size: .9rem; text-decoration: none; }
.run-hd-concern:hover { text-decoration: underline; }

.run-live { display: flex; align-items: stretch; gap: 1px; background: var(--fn-line);
    border-top: 1px solid var(--fn-line); width: 100%; }
.run-live-back, .run-live-stat, .run-live-refresh { background: var(--fn-paper); border: 0; cursor: pointer; font: inherit; }
.run-live-back { flex: 0 0 auto; width: 42px; display: grid; place-items: center; color: var(--fn-forest-700);
    font-size: 1.15rem; text-decoration: none; }
.run-live-back:hover { background: var(--fn-paper-2); }
.run-live-stat { flex: 1 1 0; min-width: 0; display: flex; align-items: baseline; justify-content: center; gap: 5px;
    padding: 8px 4px; }
.run-live-stat:hover { background: var(--fn-paper-2); }
.run-live-n { font-family: var(--fn-font-display); font-weight: 700; font-size: 1.1rem; color: var(--fn-forest-900);
    font-variant-numeric: tabular-nums; }
.run-live-l { font-size: .78rem; color: var(--fn-ink-300); }
.run-live-wx { font-size: .82rem; font-weight: 600; color: var(--fn-forest-700); }
.run-live-stat--wx.wx-nogo .run-live-wx { color: var(--fn-red-600); }
.run-live-stat--wx.wx-caution .run-live-wx { color: var(--fn-amber-600); }
.run-live-refresh { flex: 0 0 auto; width: 40px; color: var(--fn-ink-300); font-size: .95rem; }
.run-live-refresh:hover:not(:disabled) { background: var(--fn-paper-2); }
.run-live-refresh.is-fresh { color: var(--fn-forest-600); }

/* ── THE TIMELINE. Three columns: time | node on the spine | entry. Wide enough that none of them touch. ── */
/* The bands (header, treeline, action bar) run FULL WIDTH — they're the session's furniture. Only the LOG keeps
   a reading column: a 1300px line of text is unreadable, and the spine needs a margin to live in. */
.run-log { flex: 1 1 auto; position: relative; width: 100%; max-width: 980px; margin: 0 auto;
    padding: 20px 18px 24px 100px; }
.run-log::before { content: ""; position: absolute; left: 78px; top: 26px; bottom: 20px; width: 2px;
    background: linear-gradient(to bottom, var(--fn-line), var(--fn-line) 92%, transparent); }

.log-e { position: relative; margin-bottom: 14px; }
.log-time { position: absolute; left: -100px; top: 1px; width: 48px; text-align: right; font-size: .8rem;
    font-weight: 600; color: var(--fn-ink-300); font-variant-numeric: tabular-nums; }
/* The node on the spine carries the ICON for what kind of thing this was, in its own colour. FILLED = it
   happened and it's on the record; HOLLOW = it hasn't yet. That's what lets you read the shape of a whole day
   straight down the margin — a run of green sparks is a good session, an amber triangle is where it turned —
   without reading a single word. The colour is doing work here; it isn't decoration. */
.log-node { position: absolute; left: -34px; top: -2px; width: 26px; height: 26px; box-sizing: border-box;
    border-radius: 50%; display: grid; place-items: center;
    background: var(--fn-forest-600); border: 2px solid var(--fn-forest-600); color: #fff; }
.log-e--obs  .log-node { background: var(--fn-forest-700); border-color: var(--fn-forest-700); }
.log-e--risk .log-node { background: var(--fn-amber-600); border-color: var(--fn-amber-600); }
.log-e--inc  .log-node { background: var(--fn-red-600); border-color: var(--fn-red-600); }
.log-e--plan .log-node { background: var(--fn-moss); border-color: var(--fn-moss); }
.log-e--end  .log-node { background: var(--fn-bark-600, #8a4b23); border-color: var(--fn-bark-600, #8a4b23); }
/* Not on the record yet: hollow, and the colour drops back to the outline. */
.log-e.is-open .log-node { background: var(--fn-card); color: var(--fn-line-strong); border-color: var(--fn-line-strong); }
.log-e--end.is-open .log-node { color: var(--fn-bark-600, #8a4b23); border-color: var(--fn-bark-600, #8a4b23); }


/* A whisper of the kind's colour in the card itself — enough to tell the day's texture apart at arm's length in
   the woods, nowhere near enough to turn the log back into a set of unrelated coloured boxes. */
.log-e--obs  .log-card { background: color-mix(in srgb, var(--fn-forest-700) 4%, var(--fn-card)); }
.log-e--risk .log-card { background: color-mix(in srgb, var(--fn-amber-600) 7%, var(--fn-card)); }
.log-e--inc  .log-card { background: color-mix(in srgb, var(--fn-red-600) 6%, var(--fn-card)); }

/* COMPACT — routine, done, on the record. One line is all it earns. */
.log-line { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; width: 100%; padding: 1px 0;
    background: none; border: 0; text-align: left; font: inherit; cursor: pointer; }
.log-line-t { font-weight: 600; font-size: .93rem; color: var(--fn-forest-900); }
.log-line-s { font-size: .85rem; color: var(--fn-ink-300); }
.log-line:hover .log-line-t { text-decoration: underline; text-decoration-color: var(--fn-line-strong); }

/* FULL — what mattered. Gets a card and a coloured rule. */
.log-card { background: var(--fn-card); border: 1px solid var(--fn-line); border-left: 3px solid var(--fn-line-strong);
    border-radius: var(--fn-radius-sm); padding: 11px 13px; }
.log-e--obs  .log-card { border-left-color: var(--fn-forest-700); }
.log-e--risk .log-card { border-left-color: var(--fn-amber-600); }
.log-e--inc  .log-card { border-left-color: var(--fn-red-600); }
.log-e--plan .log-card { border-left-color: var(--fn-leaf-cta); background: var(--fn-paper-2); }
.log-e--end  .log-card { border-left-color: var(--fn-bark-600, #8a4b23); }

.log-head { display: flex; align-items: center; justify-content: space-between; gap: 4px 10px; flex-wrap: wrap; }
.log-who { font-family: var(--fn-font-display); font-weight: 600; font-size: 1.02rem; color: var(--fn-forest-900); }
.log-kind { font-size: .67rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--fn-ink-300); }
.log-e--risk .log-kind { color: var(--fn-amber-600); }
.log-e--inc  .log-kind { color: var(--fn-red-600); }
.log-tags { display: flex; gap: 6px; flex-wrap: wrap; }
.log-tags .neta-tag { margin: 0; }
/* Text and photos side by side, so one thumbnail doesn't leave a band of dead space beside it. The text's
   200px basis means the photos drop underneath once the card is too narrow — no breakpoint needed. */
.log-body { display: flex; align-items: flex-start; flex-wrap: wrap; gap: 10px; margin-top: 6px; }
.log-text { flex: 1 1 200px; min-width: 0; margin: 0; font-size: .9rem; line-height: 1.5; white-space: pre-wrap; }
.log-photos { flex: 0 0 auto; max-width: 160px; }
.log-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 8px;
    font-size: .8rem; color: var(--fn-ink-300); flex-wrap: wrap; }
.log-acts { display: flex; align-items: center; gap: 6px; }
.log-act { border: 1px solid var(--fn-line); background: var(--fn-paper); color: var(--fn-forest-700);
    font: 600 .78rem var(--fn-font); padding: 3px 9px; border-radius: 999px; cursor: pointer; }
.log-act:hover { background: var(--fn-paper-2); }
.log-act--danger { color: var(--fn-red-600); border-color: color-mix(in srgb, var(--fn-red-600) 35%, var(--fn-line)); }
.log-acts-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.log-plan-act { display: inline-flex; align-items: center; gap: 6px; padding: 5px 11px; border-radius: 999px;
    border: 1px solid var(--fn-line-strong); background: var(--fn-card); color: var(--fn-forest-800);
    font: 600 .82rem var(--fn-font); cursor: pointer; }
.log-plan-act:hover { background: var(--fn-paper); }

/* OPEN — hasn't happened yet, so it isn't on the record: dashed, hollow node, and it carries its own action. */
.log-e.is-open .log-card { background: none; border-style: dashed; border-left-style: dashed;
    border-left-color: var(--fn-line-strong); }
.log-e--end.is-open .log-card { border-left-style: solid; border-left-color: var(--fn-bark-600, #8a4b23); }
.log-open { display: flex; align-items: center; gap: 10px; }
.log-open-b { flex: 1 1 auto; min-width: 0; }
.log-open-t { display: block; font-weight: 600; font-size: .95rem; color: var(--fn-forest-900); }
.log-open-s { display: block; font-size: .84rem; color: var(--fn-ink-300); margin-top: 2px; }
.log-open-s--hand { font-family: var(--fn-font-hand); font-size: 1.05rem; color: var(--fn-moss); }
.log-done { flex: 0 0 auto; padding: 7px 15px; border-radius: 999px; border: 1.5px solid var(--fn-forest-700);
    background: none; color: var(--fn-forest-700); font: 700 .84rem var(--fn-font); cursor: pointer; }
.log-done:hover { background: var(--fn-forest-700); color: var(--fn-card); }
/* The whole card is the tap target where the action is just "go and do it" — a gloved leader in a wood should
   never have to hunt for a chevron. The chevron is now only a hint that this goes somewhere. */
.log-card--tap { display: block; width: 100%; text-align: left; font: inherit; cursor: pointer; }
.log-card--tap:hover { background: var(--fn-paper-2); border-color: var(--fn-line-strong); }
.log-card--tap .log-open { display: flex; align-items: center; gap: 10px; }
.log-go { flex: 0 0 auto; width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center;
    color: var(--fn-ink-300); font-size: 1.2rem; line-height: 1; }
.log-card--tap:hover .log-go { color: var(--fn-forest-700); }
/* The close earns its prominence from the clock, not from shouting all session long. */
.log-end-btn { flex: 0 0 auto; padding: 8px 16px; border-radius: 999px; cursor: pointer;
    border: 1.5px solid var(--fn-bark-600, #8a4b23); background: none; color: var(--fn-bark-600, #8a4b23);
    font: 700 .84rem var(--fn-font); }
.log-end-btn:hover, .log-end-btn.is-due { background: var(--fn-bark-600, #8a4b23); color: #fff; }
.log-end-btn.is-due { box-shadow: var(--fn-shadow-sm); }

/* The present, drawn across the spine. */
.log-now { display: flex; align-items: center; gap: 10px; margin: 2px 0 16px; }
.log-now-l { font-family: var(--fn-font-hand); font-size: 1.3rem; color: var(--fn-moss); }
.log-now-r { flex: 1 1 auto; height: 1px;
    background: repeating-linear-gradient(90deg, var(--fn-line-strong) 0 5px, transparent 5px 10px); }
.log-note { margin: 4px 0 0; font-size: .85rem; color: var(--fn-ink-300); }

/* ── THE ACTION BAR — you're standing at the edge of the wood, and the actions rise out of it.
      Sticky, not fixed: at a desk the app shell is still there and a fixed bar would sit over the sidebar. ── */
/* margin-top: auto pins it to the foot of the run-hub when the day is short; sticky keeps it there when the
   day is long. Sticky rather than fixed, so at a desk it stays inside the content column and never sails
   over the sidebar. */
.run-bar { position: sticky; bottom: 0; z-index: 25; margin-top: auto; }
/* The woodland TILES. A single strip (hills + two firs, drawn so its left and right edges meet) repeated across
   the bar at a capped height: trees stay one size whatever the screen, and the strip can't grow to 160px on a
   wide monitor. Scaling one wide graphic to fit was a dead end — `slice` cropped the treetops, `meet` either
   letterboxed or ballooned. Two firs per tile, not four: the marketing hero puts three across 1440px, and a
   dense picket fence of them looked nothing like it.

   TWO background layers: the tile on top, and under it a transparent→paper fade. The sky between the trees is
   still see-through (which is what Paul wanted), but the log fades out as it scrolls behind them instead of
   entries colliding head-on with a treetop. */
.run-bar-trees { display: block; width: 100%; height: clamp(56px, 6vw, 88px); margin-bottom: -1px;
    background-repeat: repeat-x, no-repeat;
    background-position: bottom center, bottom center;
    background-size: auto 100%, 100% 100%;
    background-image:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='480' height='120' viewBox='0 0 480 120'%3E%3Cpath fill='%23a7b994' fill-opacity='.5' d='M0 120 L0 50 C 80 38, 160 62, 240 50 C 320 38, 400 62, 480 50 L480 120 Z'/%3E%3Cpath fill='%236f8a5e' fill-opacity='.65' d='M0 120 L0 74 C 80 62, 160 86, 240 74 C 320 62, 400 86, 480 74 L480 120 Z'/%3E%3Cg fill='%2343583f' fill-opacity='.85'%3E%3Cg transform='translate(150,50) scale(.78)'%3E%3Cpath d='M0 0 l13 30 h-26 z'/%3E%3Cpath d='M0 -14 l10 22 h-20 z'/%3E%3Crect x='-3' y='27' width='6' height='11'/%3E%3C/g%3E%3Cg transform='translate(340,40)'%3E%3Cpath d='M0 0 l13 30 h-26 z'/%3E%3Cpath d='M0 -14 l10 22 h-20 z'/%3E%3Crect x='-3' y='27' width='6' height='11'/%3E%3C/g%3E%3C/g%3E%3Cpath fill='%233d4e3b' d='M0 120 L0 96 C 90 86, 150 104, 240 96 C 330 88, 390 104, 480 96 L480 120 Z'/%3E%3Cpath fill='%2328342a' d='M0 120 L0 110 C 120 104, 240 114, 360 108 C 410 105, 445 112, 480 110 L480 120 Z'/%3E%3C/svg%3E"),
        linear-gradient(to bottom, rgba(247,241,228,0) 0%, rgba(247,241,228,.75) 45%, var(--fn-paper) 78%); }
.run-bar-inner { background: #28342a; padding: 12px 14px calc(14px + env(safe-area-inset-bottom)); }
.run-bar-row { display: flex; gap: 9px; align-items: stretch; max-width: 940px; margin: 0 auto; }
/* Paper on dark: the notebook itself is the button. It's a real .btn, so it inherits the app's hand-drawn edge,
   hover-rise, press-sink and ember focus ring — only its LAYOUT belongs here. Rust stays reserved for ending the
   day, and the bright leaf stays what it is everywhere else in the brand — an accent, never a fill. */
.run-bar-obs { flex: 1 1 auto; min-height: 54px; font-size: 1rem; font-weight: 700; }
.run-bar-spark { color: var(--fn-leaf-cta); display: inline-flex; }
.run-bar-x { position: relative; flex: 0 0 auto; width: 58px; min-height: 54px; display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 3px; cursor: pointer; border-radius: var(--fn-radius);
    background: rgba(255,255,255,.07); border: 1px solid rgba(255,255,255,.13);
    font: 600 .63rem var(--fn-font); color: rgba(255,255,255,.66); line-height: 1; }
.run-bar-x:hover, .run-bar-x.is-on { background: rgba(255,255,255,.15); color: #fff; }
.run-bar-ic { display: inline-flex; }
.run-bar-ic--glyph { font-size: 1.05rem; line-height: 1; }
.run-bar-x--risk .run-bar-ic { color: #e0a03a; }
.run-bar-x--inc .run-bar-ic { color: #e0765a; }
.run-bar-n { position: absolute; top: -6px; right: -5px; min-width: 18px; height: 18px; padding: 0 4px;
    display: grid; place-items: center; border-radius: 999px; background: var(--fn-paper); color: var(--fn-forest-900);
    font-size: .68rem; font-weight: 700; }
.run-more { position: absolute; right: 12px; bottom: calc(100% - 8px); z-index: 2; display: flex; flex-direction: column;
    min-width: 210px; padding: 6px; border-radius: var(--fn-radius); background: var(--fn-card);
    border: 1px solid var(--fn-line); box-shadow: var(--fn-shadow-lg, 0 10px 30px rgba(27,41,31,.22)); }
.run-more-item { display: flex; align-items: center; gap: 10px; padding: 11px 12px; border: 0; background: none;
    border-radius: var(--fn-radius-sm); cursor: pointer; text-align: left;
    font: 600 .9rem var(--fn-font); color: var(--fn-forest-800); }
.run-more-item:hover { background: var(--fn-paper-2); }
/* Observation actions: photo + save stack full-width with even spacing (no width mismatch). */
.obs-actions { display: flex; flex-direction: column; gap: 10px; margin-top: 16px; }
.obs-actions .btn--xl { margin-top: 0; }
.photo-btn { width: 100%; display: inline-flex; align-items: center; justify-content: center; gap: 8px; }
.photo-attached { display: flex; align-items: center; gap: 12px; margin: 0; }
.photo-attached img { width: 76px; height: 76px; object-fit: cover; border-radius: var(--fn-radius-sm); border: 2px solid var(--fn-card-edge); }

/* Several photos per observation (#41575): a wrapping strip of square thumbnails, each removable while composing. */
.photo-strip { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; }
.photo-thumb { position: relative; width: 76px; height: 76px; padding: 0; border: 0; background: none; display: block; }
button.photo-thumb { cursor: zoom-in; }
.photo-thumb img { width: 100%; height: 100%; object-fit: cover; border-radius: var(--fn-radius-sm); border: 2px solid var(--fn-card-edge); display: block; }
button.photo-thumb:hover img { border-color: var(--fn-forest-600); }

/* Full-size photo lightbox (tap a thumbnail). */
.lightbox { position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center; justify-content: center;
    background: rgba(0,0,0,.82); padding: 1.5rem; cursor: zoom-out; }
.lightbox-img { max-width: 100%; max-height: 100%; object-fit: contain; border-radius: var(--fn-radius-sm); box-shadow: var(--fn-shadow-lg); cursor: default; }
.lightbox-close { position: absolute; top: 1rem; right: 1.1rem; width: 40px; height: 40px; border-radius: 50%; border: 0;
    background: rgba(255,255,255,.16); color: #fff; font-size: 18px; line-height: 1; cursor: pointer; }
.lightbox-close:hover { background: rgba(255,255,255,.3); }
.photo-thumb-x { position: absolute; top: -7px; right: -7px; width: 22px; height: 22px; border-radius: 50%; border: 0;
    background: var(--fn-forest-900); color: var(--fn-paper); font-size: 15px; line-height: 1; cursor: pointer; box-shadow: var(--fn-shadow-sm); }
.obs-save-row { display: flex; gap: 10px; align-items: center; }
.obs-save-row .btn--xl { flex: 1 1 auto; }

/* The shared observations feed (#41574): every observation in the session, with who recorded it + edit/delete. */
.obs-feed { list-style: none; padding: 0; margin: .25rem 0 0; display: flex; flex-direction: column; gap: 10px; }
.obs-feed-item { padding: 10px 12px; background: var(--fn-paper); border: 1px solid var(--fn-line); border-radius: var(--fn-radius-sm); }

/* Head: who + when read left-to-right; the NETA tags are pushed to the right edge so they read as a
   classification of the note rather than competing with the child's name. If they don't fit they wrap
   to their own line and fall back to the left — space-between puts a lone wrapped item at flex-start. */
.obs-feed-head { display: flex; align-items: center; justify-content: space-between; gap: 4px 10px; flex-wrap: wrap; }
.obs-feed-who { display: inline-flex; align-items: baseline; gap: 5px; flex-wrap: wrap; min-width: 0; }
.obs-feed-tags { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.obs-feed-tags .neta-tag { margin: 0; }

/* Body: the note and its photos sit side by side, so a single thumbnail doesn't leave a band of dead
   space beside it. `flex: 1 1 200px` on the text means the photos drop underneath once the card is too
   narrow to hold both — no breakpoint needed, so it degrades the same in a narrow column or on a phone. */
.obs-feed-body { display: flex; align-items: flex-start; flex-wrap: wrap; gap: 10px; margin-top: 5px; }
.obs-feed-text { flex: 1 1 200px; min-width: 0; margin: 0; font-size: .9rem; white-space: pre-wrap; }
.obs-feed-photos { flex: 0 0 auto; max-width: 160px; }

.obs-feed-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
.obs-feed-actions { display: flex; align-items: center; gap: 6px; }
.obs-act { border: 1px solid var(--fn-line); background: var(--fn-card); color: var(--fn-forest-700); cursor: pointer;
    font-size: .8rem; font-weight: 600; padding: 4px 10px; border-radius: 999px; }
.obs-act:hover { background: var(--fn-paper); }
.obs-act--danger { color: var(--fn-danger, #b3261e); border-color: color-mix(in srgb, var(--fn-danger, #b3261e) 35%, var(--fn-line)); }

@media (max-width: 760px) {
    /* Five equal-width segments on ONE line (no wrapping to a second row). Each fills 1/5 of the width,
       stays a 44px-tall tap target, and the current step's label is also spelled out in the header above. */
    .run-stepper { flex-wrap: nowrap; gap: 5px; margin-bottom: 1.25rem; }
    .run-step {
        flex: 1 1 0; min-width: 0; justify-content: center; text-align: center;
        font-size: .82rem; padding: 10px 3px; min-height: 44px; border-radius: 12px;
        white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
        display: inline-flex; align-items: center;
    }
    /* Wizard nav: full-width, stacked, consistent — not a small back button orphaned above a wide primary. */
    .run-actions { flex-direction: column; gap: 10px; align-items: stretch; }
    .run-actions > *, .run-actions .btn--xl { width: 100%; min-width: 0; }
    /* Focus bar: keep the exit + concern reachable with a thumb; trim padding so the title still fits. */
    .focus-bar { gap: 6px; padding: 8px 12px; }
    .focus-leave, .focus-action { padding: 9px 10px; }
}

/* ---------- Onboarding guide bar ---------- */
.onboarding-bar {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    background: linear-gradient(168deg, var(--fn-leaf-100, #eaf4e1), var(--fn-paper-2, #f4f1e6));
    border: 1.5px solid var(--fn-leaf-400, #8cc572); border-radius: var(--fn-radius-lg);
    padding: 12px 16px; margin-bottom: 1.5rem;
}
.onboarding-bar .ob-leaf { display: inline-flex; color: var(--fn-forest-600); }
.onboarding-bar .ob-leaf .fn-icon { width: 26px; height: 26px; }

/* Brand field-sketch icons (inline SVG, inherit currentColor) — replace OS emoji used as icons. */
.fn-icon { display: inline-block; vertical-align: -.15em; flex: none; color: inherit; }
.more-ic .fn-icon, .wn-badge-ic .fn-icon, .wn-nudge-ic .fn-icon, .wn-note-ic .fn-icon { color: var(--fn-forest-600); }
.onboarding-bar .ob-text { display: flex; flex-direction: column; flex: 1 1 160px; }
.onboarding-bar .ob-text strong { color: var(--fn-forest-800); }
.onboarding-bar .ob-text span { color: var(--fn-ink-500); font-size: var(--fn-text-sm); }
.onboarding-bar .ob-go { white-space: nowrap; }
.onboarding-bar .ob-dash { color: var(--fn-forest-700); font-size: var(--fn-text-sm); white-space: nowrap; text-decoration: underline; }
@media (max-width: 760px) { .onboarding-bar .ob-go { width: 100%; } }

/* ---------- Billing / pricing (the in-app sales page) ---------- */
.bill-config-note { border-color: var(--fn-amber-600); background: var(--fn-amber-200); margin-bottom: var(--fn-sp-5); }

/* "Your plan" summary — a clear card for a live subscriber: plan + price + renewal on the left,
   the Stripe portal action on the right. Replaces the old cryptic status strip. */
.plan-summary {
    display: flex; align-items: center; justify-content: space-between; gap: 1rem 1.4rem; flex-wrap: wrap;
    margin-bottom: var(--fn-sp-6); border-left: 4px solid var(--fn-leaf-400);
}
.plan-summary-info { display: flex; flex-direction: column; gap: .2rem; }
.plan-summary-label { font-size: var(--fn-text-sm); color: var(--fn-ink-500); text-transform: uppercase; letter-spacing: .04em; }
.plan-summary-top { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.plan-summary-name { font-family: var(--fn-font-display); font-size: var(--fn-text-xl); color: var(--fn-forest-900); font-weight: 700; }
.plan-summary-meta { display: flex; align-items: center; gap: .45rem; flex-wrap: wrap; color: var(--fn-ink-500); margin: 0; }
.plan-summary-sep { opacity: .5; }
.plan-summary-actions { display: flex; flex-direction: column; align-items: flex-end; gap: .25rem; text-align: right; }

/* Pure-trial reassurance line (no card on file yet), sitting above the sales hero. */
.bill-trial-note {
    display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
    color: var(--fn-ink-500); margin: 0 0 var(--fn-sp-5);
}

/* Warm sales hero — headline + ticks on paper, a soft sun-glow above and a low woodland horizon below. */
.bill-hero {
    position: relative; text-align: center; overflow: hidden;
    margin: var(--fn-sp-7) 0 var(--fn-sp-6); padding: var(--fn-sp-4) 0 3.4rem;
    background: radial-gradient(58% 80% at 50% -10%, rgba(247,227,166,.38), transparent 72%);
}
.bill-hero-scene { position: absolute; left: 0; right: 0; bottom: 0; width: 100%; height: 58%; z-index: 0; pointer-events: none; opacity: .85; }
.bill-hero-content { position: relative; z-index: 1; }
.bill-hero h2 { font-family: var(--fn-font-display); color: var(--fn-forest-900); font-size: var(--fn-text-2xl); margin: 0 0 .5rem; }
.bill-reassure { display: flex; justify-content: center; flex-wrap: wrap; gap: .35rem 1.6rem; color: var(--fn-ink-500); margin: 0; }
.bill-reassure .tick { color: var(--fn-leaf-cta); font-weight: 800; margin-right: .35rem; }
.bill-section { font-family: var(--fn-font-display); color: var(--fn-forest-900); margin: var(--fn-sp-6) 0 var(--fn-sp-4); }

/* Plan cards — paper notebook surface, the recommended one raised with a leaf badge. */
.pricing-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1.25rem; align-items: stretch; }
.pricing-card {
    position: relative; display: flex; flex-direction: column; gap: .5rem;
    background: var(--fn-card); border: 1.5px solid var(--fn-card-edge);
    border-radius: var(--fn-radius-lg, 18px); padding: 1.6rem 1.4rem;
}
.pricing-card--featured { border-color: var(--fn-leaf-400); border-width: 2px; box-shadow: 0 10px 34px rgba(40,54,38,.11); }
.pricing-card--current { border-color: var(--fn-forest-500); }
.pricing-badge {
    position: absolute; top: -.8rem; left: 1.4rem;
    background: var(--fn-leaf-cta); color: var(--fn-leaf-cta-ink);
    font-size: var(--fn-text-xs); font-weight: 800; letter-spacing: .02em;
    padding: .25rem .7rem; border-radius: var(--fn-radius-pill);
    box-shadow: 0 2px 7px rgba(40,54,38,.18);
}
.pricing-name { font-family: var(--fn-font-display); color: var(--fn-forest-900); margin: .2rem 0 0; font-size: var(--fn-text-xl); }
.pricing-price { font-family: var(--fn-font-display); font-weight: 700; font-size: 1.9rem; color: var(--fn-ink-900); margin: 0; line-height: 1.1; }
.pricing-price .per { font-family: var(--fn-font); font-weight: 500; font-size: var(--fn-text-sm); color: var(--fn-ink-500); }
/* Contact tier has no number — a warm hand-lettered "Let's talk" that sits under, not over, the plan name. */
.pricing-price--contact { font-family: var(--fn-font-hand); font-weight: 700; font-size: 1.7rem; color: var(--fn-forest-600); }
.pricing-for { color: var(--fn-ink-500); font-size: var(--fn-text-sm); margin: .1rem 0 .4rem; }
.pricing-features { list-style: none; margin: 0 0 .4rem; padding: 0; display: flex; flex-direction: column; gap: .55rem; }
.pricing-features li { position: relative; padding-left: 1.6rem; color: var(--fn-ink-700); font-size: var(--fn-text-sm); line-height: 1.35; }
.pricing-features li::before { content: "✓"; position: absolute; left: 0; top: 0; color: var(--fn-leaf-cta); font-weight: 800; }
.pricing-cta { margin-top: auto; width: 100%; justify-content: center; }
.pricing-card .btn.is-current { color: var(--fn-forest-700); border-color: var(--fn-leaf-400); background: var(--fn-leaf-200); opacity: 1; cursor: default; }

.confirm-card { border-color: var(--fn-leaf-400); box-shadow: inset 0 0 0 1px var(--fn-leaf-400); max-width: 560px; margin-bottom: var(--fn-sp-5); }
.bill-error { color: var(--fn-red-600); margin-top: var(--fn-sp-4); }
.bill-payments { margin-top: var(--fn-sp-7); }

/* ---------- NETA development areas (Forest School Association) ----------
   Each area carries a brand colour via --area; components read it so the picker, the child-profile
   roll-up bars and the inline observation tags all stay visually consistent. */
.neta-dot--confidence,   .neta-bar--confidence,   .neta-tag--confidence   { --area: #b5760a; }   /* warm gold  */
.neta-dot--creativity,   .neta-bar--creativity,   .neta-tag--creativity   { --area: #5a86a0; }   /* sky        */
.neta-dot--resilience,   .neta-bar--resilience,   .neta-tag--resilience   { --area: #806249; }   /* bark       */
.neta-dot--independence, .neta-bar--independence, .neta-tag--independence { --area: #4a6147; }   /* forest     */
.neta-dot--wellbeing,    .neta-bar--wellbeing,    .neta-tag--wellbeing    { --area: #b06b6b; }   /* warm rose  */

/* Capture picker (session runner): one thumb-friendly row of small circles + tiny labels.
   Familiar at a glance once learned; the whole circle+label is the tap target. */
.neta-row { display: flex; align-items: flex-start; gap: 4px; }
.neta-dot {
    flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 5px;
    padding: 4px 1px; border: 0; background: none; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.neta-dot-ring {
    width: 50px; height: 50px; border-radius: 50%; display: grid; place-items: center;
    background: var(--fn-card); border: 1.5px solid var(--fn-line); color: var(--area);
    transition: background .12s, border-color .12s, box-shadow .12s, transform .1s;
}
.neta-dot-label {
    font-size: .68rem; font-weight: 600; line-height: 1.1; text-align: center; color: var(--fn-ink-500);
}
.neta-dot:hover .neta-dot-ring { border-color: var(--area); }
.neta-dot:active .neta-dot-ring { transform: scale(.94); }
.neta-dot.is-on .neta-dot-ring {
    background: color-mix(in srgb, var(--area) 16%, var(--fn-card));
    border-color: var(--area); box-shadow: 0 0 0 2px color-mix(in srgb, var(--area) 38%, transparent);
}
.neta-dot.is-on .neta-dot-label { color: var(--area); }
/* Wellbeing is the overarching strand — a faint divider keeps it distinct while staying on the line. */
.neta-dot--wb { margin-left: 7px; border-left: 1px dashed var(--fn-line); padding-left: 8px; }

/* Child-profile roll-up bars. */
.neta-summary { display: flex; gap: 6px; flex-wrap: wrap; }
.neta-bars { display: flex; flex-direction: column; gap: 16px; }
.neta-bar { display: flex; gap: 12px; align-items: flex-start; }
.neta-bar--wb { padding-top: 16px; margin-top: 2px; border-top: 1px dashed var(--fn-line); }
.neta-bar-ico {
    width: 38px; height: 38px; border-radius: 11px; flex: 0 0 auto; display: grid; place-items: center;
    background: color-mix(in srgb, var(--area) 14%, var(--fn-paper)); color: var(--area);
}
.neta-bar-main { flex: 1; min-width: 0; }
.neta-bar-head { display: flex; justify-content: space-between; gap: 8px; align-items: baseline; }
.neta-bar-label { font-weight: 700; color: var(--fn-forest-800); }
.neta-bar-count { font-weight: 800; color: var(--area); font-variant-numeric: tabular-nums; white-space: nowrap; }
.neta-up { margin-left: 8px; font-size: .7rem; font-weight: 700; color: var(--fn-forest-600); }
.neta-track { height: 9px; border-radius: 6px; background: var(--fn-paper-2); overflow: hidden; margin: 6px 0; }
.neta-fill { height: 100%; border-radius: 6px; background: var(--area); min-width: 3px; transition: width .4s ease; }
.neta-blurb { margin: 2px 0 0; }

/* Inline area tags (observation list). */
.neta-tag {
    display: inline-flex; align-items: center; gap: 5px; margin: 0 6px 4px 0; padding: 3px 9px;
    border-radius: 999px; font-size: .78rem; font-weight: 600;
    background: color-mix(in srgb, var(--area) 13%, var(--fn-card)); color: var(--area);
    border: 1px solid color-mix(in srgb, var(--area) 35%, transparent);
}
.neta-tag .fn-icon { color: var(--area); }

/* Review step: a compact NETA tally of the day + a skimmable observation list (feeds the reflection). */
.review-neta { margin: 0 0 14px; padding: 0 0 14px; border-bottom: 1px solid var(--fn-line); }
.neta-tally { display: flex; gap: 6px; }
.neta-tally-item { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 3px; text-align: center; }
.neta-tally-ring {
    width: 42px; height: 42px; border-radius: 50%; display: grid; place-items: center;
    background: color-mix(in srgb, var(--area) 14%, var(--fn-paper)); color: var(--area);
    border: 1.5px solid color-mix(in srgb, var(--area) 30%, transparent);
}
.neta-tally-item.is-zero .neta-tally-ring { background: var(--fn-paper-2); color: var(--fn-ink-300); border: 1.5px dashed var(--fn-line); }
.neta-tally-count { font-weight: 800; font-size: .95rem; line-height: 1; color: var(--area); font-variant-numeric: tabular-nums; }
.neta-tally-item.is-zero .neta-tally-count { color: var(--fn-ink-300); }
.neta-tally-label { font-size: .64rem; font-weight: 600; line-height: 1.05; color: var(--fn-ink-500); }

.obs-skim { margin-top: 12px; }
.obs-skim > summary { cursor: pointer; font-size: .85rem; font-weight: 600; color: var(--fn-forest-700); }
.obs-skim-list { list-style: none; padding: 0; margin: 10px 0 0; max-height: 260px; overflow-y: auto; display: flex; flex-direction: column; gap: 8px; }
.obs-skim-list li { padding: 8px 10px; background: var(--fn-paper); border: 1px solid var(--fn-line); border-radius: var(--fn-radius-sm); }
.obs-skim-head { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.obs-skim-text { margin: 4px 0 0; font-size: .86rem; white-space: pre-wrap; }

/* ---------- End-of-session review: the team's attributed contributions (#41840) ---------- */
.refl-thread { margin-bottom: 1.1rem; }
.refl-thread-q { margin: 0 0 8px; font-weight: 600; color: var(--fn-forest-800); }
.refl-note { padding: 8px 10px; margin-bottom: 8px; background: var(--fn-paper); border: 1px solid var(--fn-line); border-radius: var(--fn-radius-sm); }
.refl-note-text { margin: 0; font-size: .92rem; white-space: pre-wrap; }
.refl-note-by { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 5px 0 0; font-size: var(--fn-text-xs); color: var(--fn-ink-500); }
.refl-note-actions { display: flex; gap: 8px; margin-top: 6px; }
.link-btn--danger { color: var(--fn-red-600); font-weight: 600; }

/* ---------- NETA distance-travelled (periodic ratings) ---------- */
.neta-rate-form { margin-top: 14px; padding: 14px; background: var(--fn-paper); border: 1px solid var(--fn-line); border-radius: var(--fn-radius); }
.neta-rate-meta { display: flex; gap: 14px; flex-wrap: wrap; margin-bottom: 10px; }
.neta-rate-meta label { display: flex; flex-direction: column; gap: 3px; font-weight: 600; }
/* Keep the scale rows compact so label + pips read as one control (not stranded across a wide card). */
.neta-rate-rows { max-width: 580px; }
.neta-rate-row, .neta-travel-row { display: flex; align-items: center; gap: 10px; padding: 5px 0; }
.neta-rate-formhead { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-bottom: 8px; }
.neta-stage-sel { width: auto; min-width: 130px; }
.neta-rate-actions { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.neta-rate-section { margin: 4px 0 16px; padding-top: 14px; border-top: 1px solid var(--fn-line); }

/* Share-with-family toggle — a clear pill button (was reading as static text). */
.btn-share {
    display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto; padding: 5px 12px;
    border-radius: var(--fn-radius-pill); border: 1.5px solid var(--fn-leaf-400); background: var(--fn-card);
    color: var(--fn-forest-700); font-size: .8rem; font-weight: 700; cursor: pointer; white-space: nowrap;
    transition: background .12s, border-color .12s;
}
.btn-share:hover { background: var(--fn-leaf-200); }
.btn-share .fn-icon { color: var(--fn-forest-600); }
.btn-share.is-shared { background: var(--fn-leaf-200); border-color: var(--fn-leaf-400); color: var(--fn-forest-800); }
.neta-rate-ico {
    width: 30px; height: 30px; border-radius: 50%; flex: 0 0 auto; display: grid; place-items: center;
    background: color-mix(in srgb, var(--area) 14%, var(--fn-card)); color: var(--area);
}
.neta-rate-label { flex: 1 1 auto; min-width: 0; font-weight: 600; color: var(--fn-forest-800); }

/* Editable score pips (1–4 buttons). */
.neta-pips { display: inline-flex; gap: 5px; flex: 0 0 auto; }
.neta-pip {
    width: 30px; height: 30px; border-radius: 50%; padding: 0; display: grid; place-items: center;
    border: 1.5px solid var(--fn-line); background: var(--fn-card); color: var(--fn-ink-500);
    font-weight: 700; font-size: .8rem; cursor: pointer; transition: background .1s, border-color .1s, box-shadow .1s;
}
.neta-pip.is-on { background: color-mix(in srgb, var(--area) 22%, var(--fn-card)); border-color: var(--area); color: var(--area); }
.neta-pip.is-sel { box-shadow: 0 0 0 2px color-mix(in srgb, var(--area) 40%, transparent); }
.neta-pip-word { width: 78px; text-align: right; flex: 0 0 auto; }

/* Read-only pips on the distance-travelled view: small dots; baseline gets a ring. */
.neta-pips--ro .neta-pip { width: 16px; height: 16px; cursor: default; background: var(--fn-paper-2); }
.neta-pips--ro .neta-pip.is-on { background: var(--area); border-color: var(--area); }
.neta-pips--ro .neta-pip.is-base { box-shadow: 0 0 0 2px var(--fn-card), 0 0 0 3.5px var(--area); }
.neta-travel { display: flex; flex-direction: column; gap: 10px; max-width: 580px; }

.neta-delta { flex: 0 0 auto; font-size: .8rem; font-weight: 700; color: var(--fn-ink-500); text-align: right; }
.neta-delta-num { font-weight: 800; }
.neta-delta.up, .neta-delta.up .neta-delta-num { color: var(--fn-forest-600); }
.neta-delta.down, .neta-delta.down .neta-delta-num { color: var(--fn-red-600); }
.neta-delta.flat { color: var(--fn-ink-300); }

/* Cohort report table. */
.neta-table-wrap { overflow-x: auto; }
.neta-table { width: 100%; border-collapse: collapse; font-size: .9rem; }
.neta-table th, .neta-table td { padding: 8px 10px; border-bottom: 1px solid var(--fn-line); text-align: left; }
.neta-th-area { text-align: center; width: 44px; color: var(--area); }
.neta-th-area .fn-icon { color: var(--area); }
.neta-cell { text-align: center; }
.neta-cell-score { font-weight: 800; color: var(--area); }
.neta-cell-delta { font-size: .7rem; font-weight: 700; margin-left: 3px; }
.neta-cell-delta.up { color: var(--fn-forest-600); }
.neta-cell-delta.down { color: var(--fn-red-600); }

/* Reports-hub tile linking to the NETA development report. */
.report-tile {
    display: flex; align-items: center; gap: 14px; padding: 16px; margin-bottom: 1.25rem;
    background: var(--fn-card); border: 1px solid var(--fn-line); border-radius: var(--fn-radius);
    text-decoration: none; color: inherit; box-shadow: var(--fn-shadow);
    transition: border-color .12s, transform .12s;
}
.report-tile:hover { border-color: var(--fn-forest-500); transform: translateY(-1px); }
.report-tile-ico {
    width: 46px; height: 46px; border-radius: 12px; flex: 0 0 auto; display: grid; place-items: center;
    background: color-mix(in srgb, #b06b6b 14%, var(--fn-paper)); color: #b06b6b;
}
.report-tile-main { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.report-tile-go { font-size: 1.3rem; color: var(--fn-forest-600); flex: 0 0 auto; }

/* ---------- Motion ---------- */
@keyframes leaf-sway { 0%,100% { transform: rotate(-6deg); } 50% { transform: rotate(6deg); } }
/* `to` must be `transform: none`, NOT translateY(0): with fill-mode:both the element keeps the end transform,
   and any non-none transform makes .fn-content a containing block that traps position:fixed sheets/modals. */
@keyframes rise-in { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
/* Steady vertical descent (linear → never pauses); opacity fades in/out at the edges of the travel. */
@keyframes leaf-descend {
    0%   { transform: translateY(-12vh); opacity: 0; }
    8%   { opacity: .8; }
    90%  { opacity: .6; }
    100% { transform: translateY(112vh); opacity: 0; }
}
/* Independent side-to-side flutter + rock; runs `alternate` on its own duration so the leaf rocks
   back and forth as it falls. Eased here (not on the descent) so only the sway slows at its extremes. */
@keyframes leaf-flutter {
    0%   { transform: translateX(-16px) rotate(-42deg); }
    100% { transform: translateX(16px) rotate(58deg); }
}
@media (prefers-reduced-motion: reduce) { *, ::before, ::after { animation: none !important; transition: none !important; } }

@media (max-width: 760px) {
    /* IN-SESSION FOCUS MODE, phones only. The session page renders inside the ordinary app layout (so a desktop
       keeps its nav — see .fn-focus), which means the shell has to come OFF here instead: no top bar, no bottom
       tabs, no billing nudges, no onboarding guide, no chat bubble. A leader in the wood sees the session and
       one way out, and can't fat-finger their way into the back-office. :has() scopes it to this page alone. */
    .fn-shell:has(.fn-focus) .fn-topbar,
    .fn-shell:has(.fn-focus) .bottomnav,
    .fn-shell:has(.fn-focus) .grace-banner,
    .fn-shell:has(.fn-focus) .onboarding-bar,
    .fn-shell:has(.fn-focus) .fsc-root { display: none; }
    .fn-shell:has(.fn-focus) .fn-content { padding: 0; }

    /* Phone shell: hide the desktop sidebar, surface the brand in the top bar,
       and put the daily essentials in a thumb-friendly bottom tab bar. */
    .fn-sidebar { display: none; }
    /* Dark-green top bar on mobile (matches the desktop sidebar) — the brand sits on it in its on-dark variant. */
    .fn-topbar { position: sticky; top: 0; z-index: 30; padding: 0 var(--fn-sp-4); min-height: 56px;
        background: linear-gradient(120deg, var(--fn-forest-800), var(--fn-forest-900));
        border-bottom: 1.5px solid var(--fn-forest-950); backdrop-filter: none; }
    .fn-topbar-brand { display: inline-flex; }
    .fn-topbar .me, .fn-topbar .logout-form.desktop-only { display: none; }
    .fn-content { padding: var(--fn-sp-4); padding-bottom: calc(72px + env(safe-area-inset-bottom, 0px)); }
    .bottomnav {
        display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
        background: var(--fn-card); border-top: 1.5px solid var(--fn-card-edge);
        padding-bottom: env(safe-area-inset-bottom, 0px); box-shadow: 0 -4px 18px rgba(40,54,38,.06);
    }
    /* The fixed bottomnav owns the bottom edge on phones, so the action bar can't stick there —
       drop it back into the flow, stacked full-width like .run-actions (Save still ends up last). */
    .page-actions {
        position: static; flex-direction: column; align-items: stretch; gap: 10px;
        margin-top: 1.25rem; padding: 0; border-top: none; background: transparent;
    }
    .page-actions > *, .page-actions .btn--xl { width: 100%; min-width: 0; }
    .page-actions .pa-spacer { display: none; }
    h1 { font-size: 2rem; }
    .page-head h1 { font-size: 1.9rem; }
    /* Stack the title and its action with real breathing room — the full-width button
       was butting straight against the subtitle on phones. */
    .page-head { flex-wrap: wrap; gap: 14px; margin-bottom: var(--fn-sp-5); }
    .page-head > div:first-child { width: 100%; }
    /* Header actions sit in a tidy wrapping row, not a stack of full-width buttons. The title takes the row
       above (width:100%), so the actions drop below and flow left-aligned. */
    .page-head > div:not(:first-child) { display: flex; gap: 8px; flex-wrap: wrap; width: 100%; }
    .page-head .btn, .page-head .btn-primary { width: auto; min-height: 44px; }
    /* A header with several actions (e.g. Child detail: All children · Quick note · Full report · Edit)
       compacts to a tight wrapping row of small buttons so the strip doesn't eat the top of the screen.
       Every action stays; the primary (ember) is still the loud one by colour, not size. */
    .page-head-actions { gap: 6px; }
    .page-head-actions .btn, .page-head-actions .btn-primary { min-height: 38px; padding: 6px 12px; font-size: var(--fn-text-sm); }
}

/* --- Risk rating: severity/likelihood segmented selectors + before→after layout --- */
.lvl-seg { display: inline-flex; gap: 6px; flex-wrap: wrap; }
.lvl-btn {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
    min-width: 60px; min-height: 50px; padding: 6px 12px; border: 1.5px solid var(--fn-line);
    border-radius: 14px; background: var(--fn-surface, #fff); color: var(--fn-ink, #2f2417);
    cursor: pointer; font: inherit; transition: border-color .12s ease, background .12s ease, transform .06s ease;
}
.lvl-btn .lvl-num { font-weight: 700; font-size: 1.1rem; line-height: 1; }
.lvl-btn .lvl-cap { font-size: .62rem; text-transform: uppercase; letter-spacing: .04em; color: var(--fn-muted, #8a7b63); }
.lvl-btn:hover:not(.is-off):not(.is-on) { border-color: #c8bba2; }
.lvl-btn:active:not(.is-off) { transform: translateY(1px); }
.lvl-btn.is-off { opacity: .38; cursor: not-allowed; }
.lvl-btn.is-on { font-weight: 700; box-shadow: inset 0 0 0 1px currentColor; }
.lvl-btn.lvl-1.is-on { background: var(--fn-leaf-200); border-color: var(--fn-leaf-400); }
.lvl-btn.lvl-2.is-on { background: #fdf2d8; border-color: #e6c66a; }
.lvl-btn.lvl-3.is-on { background: #f7dcd6; border-color: #d98b7a; }
.lvl-btn.is-on .lvl-cap { color: inherit; }

.risk-rate { display: flex; flex-direction: column; gap: 16px; }
.risk-rate--bordered { border-top: 1px dashed var(--fn-line); padding-top: 14px; }
.rr-label { display: block; font-weight: 600; font-size: .82rem; color: var(--fn-ink, #2f2417); margin-bottom: 7px; }
.rr-grid { display: grid; grid-template-columns: 1fr auto 1fr; gap: 16px; align-items: start; }
.rr-col { display: flex; flex-direction: column; gap: 10px; }
.rr-arrow { align-self: center; color: var(--fn-muted, #8a7b63); font-size: .76rem; font-weight: 700; white-space: nowrap; text-align: center; }
.rr-badge {
    display: inline-block; align-self: flex-start; padding: 7px 14px; border-radius: 999px;
    border: 1px solid var(--fn-line); font-weight: 700; font-size: .85rem;
}
.rr-badge.chip--ok { background: var(--fn-leaf-200); border-color: var(--fn-leaf-400); }
.rr-badge.chip--warn { background: #fdf2d8; border-color: #e6c66a; }
.rr-badge.chip--danger { background: #f7dcd6; border-color: #d98b7a; }
@media (max-width: 560px) {
    .rr-grid { grid-template-columns: 1fr; gap: 12px; }
    .rr-arrow { transform: rotate(90deg); margin: 2px 0; }
}

/* --- Public parent booking surface (the /book and /my-bookings pages, BareLayout) --- */
.public-book { max-width: 620px; margin: 0 auto; padding: 1.75rem 1.1rem 3rem; }
.public-book .brand-line { justify-content: center; margin-bottom: 1.25rem; font-size: 1.05rem; }
/* The setting owns the top of its booking page — a brand-accent rule + its name as the hero.
   Our own mark steps back to a quiet "powered by" footer (.book-powered) below the content. */
.book-brand { text-align: center; margin-bottom: 1.5rem; }
.book-accent-rule { display: block; width: 56px; height: 4px; margin: 0 auto .9rem; border-radius: 99px; background: var(--book-accent, var(--fn-forest-700)); }
.book-cover { margin: 0 0 1.25rem; border-radius: var(--fn-radius); overflow: hidden; border: 1px solid var(--fn-line); }
.book-cover img { display: block; width: 100%; height: 180px; object-fit: cover; }
.book-logo { display: block; max-height: 84px; max-width: 70%; margin: 0 auto .8rem; object-fit: contain; }
.book-title { text-align: center; margin: 0 0 .25rem; }
.book-sub { text-align: center; margin: 0 auto 0; max-width: 46ch; }
.book-powered { display: flex; align-items: center; justify-content: center; gap: .55rem; margin-top: 2.75rem; padding-top: 1.4rem; border-top: 1px solid var(--fn-line); color: var(--fn-ink-500); font-size: .82rem; }
.book-powered .fs-logo { font-size: .72rem; }
.book-powered .fs-logo__name { color: var(--fn-ink-500); }
/* (Full-width CTAs no longer need a special case — the pressed-paper border-image edge keeps fixed corners
   at any width, so the big public buttons get the same hand-drawn wave as everything else.) */
.book-card { background: var(--fn-surface, #fff); border: 1px solid var(--fn-line); border-radius: var(--fn-radius); padding: 1.25rem; margin-bottom: 1.25rem; }
.book-result { font-weight: 600; }
.book-result.is-ok { background: var(--fn-leaf-200); border-color: var(--fn-leaf-400); }
.book-result.is-wait { background: #fdf2d8; border-color: #e6c66a; }
.book-result.is-err { background: #f7dcd6; border-color: #d98b7a; }
.session-pick { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border: 1px solid var(--fn-line); border-radius: var(--fn-radius); margin-top: 10px; cursor: pointer; }
.session-pick.is-full { opacity: .85; }
.session-pick .session-meta { flex: 1; }
.session-pick input[type=radio] { width: auto; min-height: auto; margin: 0; }

/* --- Practitioner-first home dashboard (shared by the MAUI app and the web home) --- */
.wn-hero {
    position: relative; overflow: hidden; min-height: 205px; display: flex; align-items: flex-end;
    box-shadow: var(--fn-shadow); isolation: isolate; border-radius: var(--fn-radius-lg); margin-bottom: 1.4rem;
}
.wn-hero .scene { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0; }
.wn-hero-top { position: absolute; top: .65rem; right: .65rem; z-index: 3; }
.wn-hero-greet { position: relative; z-index: 2; padding: 1.1rem 1.4rem; }
.wn-hero-greet h1 { font-family: var(--fn-font-display); font-size: var(--fn-text-3xl); line-height: 1.05; margin: 0; color: #fff; text-shadow: 0 1px 7px rgba(20,32,26,.5); }
.wn-hero-greet p { font-family: var(--fn-font-hand); font-size: var(--fn-text-xl); margin: .1rem 0 0; color: var(--fn-sun-soft); text-shadow: 0 1px 5px rgba(20,32,26,.5); }
/* Within the banner the descent travels just the banner height (~220px) instead of a full viewport.
   The inner .leaf-flutter (shared keyframe above) still handles the side-to-side rock. */
.wn-hero .leaf-drift { z-index: 1; animation-name: wn-leaf-descend; }
@keyframes wn-leaf-descend {
    0%   { transform: translateY(-24px); opacity: 0; }
    12%  { opacity: .8; }
    88%  { opacity: .6; }
    100% { transform: translateY(224px); opacity: 0; }
}
.wn-switch { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; margin-bottom: 1rem; }

.wn-card { background: var(--fn-card); border: 1px solid var(--fn-card-edge); border-radius: var(--fn-radius); box-shadow: var(--fn-shadow-sm); padding: 1rem 1.1rem; }

.wn-note { display: flex; align-items: center; gap: .8rem; margin: 0 0 1.4rem; padding: .55rem .2rem; background-image: var(--fn-fern); background-repeat: no-repeat; background-position: right -16px bottom -22px; }
.wn-note-ic { font-size: 1.5rem; line-height: 1; flex: none; }
.wn-note-body { display: flex; flex-direction: column; }
.wn-note-date { font-size: var(--fn-text-xs); text-transform: uppercase; letter-spacing: .07em; color: var(--fn-ink-300); font-weight: 600; }
.wn-note-text { font-family: var(--fn-font); font-style: italic; font-size: var(--fn-text-sm); color: var(--fn-bark-700); line-height: 1.35; }

.wn-nudge { display: flex; align-items: center; gap: .5rem; text-decoration: none; margin: 0 0 1.3rem; padding: .1rem .15rem; color: var(--fn-forest-700); }
.wn-nudge-ic { font-size: 1rem; line-height: 1; }
.wn-nudge-text { flex: 1; font-size: var(--fn-text-sm); }
.wn-nudge-go { color: var(--fn-forest-600); font-weight: 700; }

.wn-sec { margin: 0 0 1.5rem; }
.wn-sec-h { display: flex; align-items: center; gap: .45rem; font-family: var(--fn-font-display); color: var(--fn-forest-800); font-size: var(--fn-text-lg); margin: 0 0 .6rem; }
.wn-sec-count { font-family: var(--fn-font); font-size: var(--fn-text-sm); color: var(--fn-ink-300); font-weight: 400; margin-left: .15rem; }
.wn-group { font-size: var(--fn-text-xs); text-transform: uppercase; letter-spacing: .08em; color: var(--fn-ink-300); margin: .9rem 0 .4rem; font-weight: 600; }

.wn-live-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--fn-leaf-cta); box-shadow: 0 0 0 0 rgba(70,185,61,.6); animation: wn-pulse 1.8s infinite; }
@keyframes wn-pulse { 0% { box-shadow: 0 0 0 0 rgba(70,185,61,.55); } 70% { box-shadow: 0 0 0 8px rgba(70,185,61,0); } 100% { box-shadow: 0 0 0 0 rgba(70,185,61,0); } }
.wn-live { display: flex; flex-direction: column; gap: .2rem; width: 100%; text-align: left; border: 0; cursor: pointer; margin-bottom: .65rem; padding: 1rem 1.15rem; border-radius: var(--fn-radius-lg); background: linear-gradient(135deg, var(--fn-forest-700), var(--fn-forest-900)); color: var(--fn-paper); box-shadow: var(--fn-shadow); transition: transform .12s ease, box-shadow .12s ease; }
.wn-live:hover { transform: translateY(-2px); box-shadow: var(--fn-shadow-lg); }
.wn-live-kicker { font-size: var(--fn-text-xs); color: var(--fn-leaf-400); letter-spacing: .04em; }
.wn-live-title { font-family: var(--fn-font-display); font-size: var(--fn-text-xl); }
.wn-live-meta { font-size: var(--fn-text-sm); color: var(--fn-leaf-200); opacity: .9; }
.wn-live-go { font-size: var(--fn-text-sm); color: var(--fn-sun-soft); margin-top: .35rem; font-weight: 600; }

.wn-session { display: flex; flex-direction: column; gap: .1rem; width: 100%; text-align: left; cursor: pointer; margin-bottom: .5rem; padding: .8rem 1rem; background: var(--fn-card); border: 1px solid var(--fn-card-edge); border-left: 3px solid var(--fn-forest-500); border-radius: var(--fn-radius); box-shadow: var(--fn-shadow-sm); transition: transform .12s ease; }
.wn-session:hover { transform: translateY(-1px); }
.wn-session--today { border-left-color: var(--fn-leaf-cta); }
.wn-session-date { font-size: var(--fn-text-xs); color: var(--fn-ink-300); letter-spacing: .04em; }
.wn-session-site { font-family: var(--fn-font-display); color: var(--fn-forest-900); font-size: var(--fn-text-lg); }
.wn-session-go { font-size: var(--fn-text-sm); color: var(--fn-forest-600); margin-top: .25rem; }
.wn-session--today .wn-session-date { color: var(--fn-leaf-cta); font-weight: 700; }

.wn-empty { text-align: center; padding: 1.6rem 1rem; }
.wn-empty-leaf { font-size: 1.7rem; line-height: 1; display: inline-grid; place-items: center; width: 56px; height: 56px; border-radius: 50%; background: var(--fn-leaf-200); box-shadow: inset 0 0 0 2px var(--fn-leaf-400); margin-bottom: .25rem; }

.wn-recent { display: flex; align-items: center; gap: .6rem; width: 100%; text-align: left; background: transparent; border: 0; border-bottom: 1px solid var(--fn-line); padding: .55rem .15rem; cursor: pointer; }
.wn-recent:hover { background: rgba(74,97,71,.05); }
.wn-recent-date { font-size: var(--fn-text-xs); color: var(--fn-ink-300); width: 5.5rem; flex: none; }
.wn-recent-site { flex: 1; color: var(--fn-ink-700); }
.wn-recent-tag { flex: none; }

.wn-ul { background: var(--fn-underline) left bottom no-repeat; background-size: 100% .4em; padding-bottom: .1em; }

.wn-you-top { display: flex; align-items: flex-start; justify-content: space-between; gap: .5rem; }
.wn-you-name { font-family: var(--fn-font-display); color: var(--fn-forest-900); font-size: var(--fn-text-lg); display: block; }
.wn-you-head { font-size: var(--fn-text-sm); color: var(--fn-ink-500); }
.wn-youstats { display: flex; margin: .85rem 0 .25rem; }
.wn-youstats > div { flex: 1; display: flex; flex-direction: column; align-items: center; gap: .05rem; border-left: 1px solid var(--fn-line); }
.wn-youstats > div:first-child { border-left: 0; }
.wn-youstats .n { font-family: var(--fn-font-display); font-size: var(--fn-text-xl); color: var(--fn-forest-800); line-height: 1.1; }
.wn-youstats .l { font-size: var(--fn-text-xs); color: var(--fn-ink-500); }

/* The readiness ring sits in the MIDDLE of the record card, with the "how you're doing" line under it — it's the
   thing the card is about, so it reads as the centrepiece rather than a bullet hugging the left edge. Shared by
   the web dashboard and the field app, which is why it's here and not in either page's own styles. */
.wn-progress { display: flex; flex-direction: column; align-items: center; text-align: center;
    gap: .6rem; margin: 1rem 0 .25rem; }
.wn-ring { position: relative; width: 88px; height: 88px; flex: none; border-radius: 50%; background: conic-gradient(var(--fn-leaf-cta) calc(var(--p) * 1%), var(--fn-line) 0); display: grid; place-items: center; }
.wn-ring::before { content: ""; position: absolute; inset: 9px; border-radius: 50%; background: var(--fn-card); box-shadow: var(--fn-shadow-sm); }
.wn-ring-num { position: relative; font-family: var(--fn-font-display); font-size: var(--fn-text-xl); color: var(--fn-forest-800); }
.wn-ring-num small { font-size: .55em; color: var(--fn-ink-300); }
.wn-ready { display: flex; flex-direction: column; align-items: center; gap: .15rem; max-width: 34rem; }
.wn-ready strong { font-family: var(--fn-font-display); color: var(--fn-forest-800); font-size: var(--fn-text-lg); }

.wn-badges { display: flex; gap: .55rem; margin-top: 1rem; }
.wn-badge { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: .3rem; text-align: center; text-decoration: none; }
.wn-badge-ring { position: relative; width: 58px; height: 58px; border-radius: 50%; display: grid; place-items: center; background: var(--fn-paper-2); box-shadow: inset 0 0 0 2px var(--fn-line-strong); transition: transform .12s ease; }
.wn-badge:hover .wn-badge-ring { transform: translateY(-2px); }
.wn-badge-ic { font-size: 1.4rem; line-height: 1; }
.wn-badge-num { font-family: var(--fn-font-display); font-size: 1.5rem; color: var(--fn-forest-800); }
.wn-badge-label { font-size: var(--fn-text-xs); color: var(--fn-ink-700); font-weight: 600; }
.wn-badge-status { font-size: var(--fn-text-xs); color: var(--fn-ink-300); }
.wn-badge--ok .wn-badge-ring { background: var(--fn-leaf-200); box-shadow: inset 0 0 0 2px var(--fn-leaf-400); }
.wn-badge--warn .wn-badge-ring { background: var(--fn-amber-200); box-shadow: inset 0 0 0 2px var(--fn-amber-600); }
.wn-badge--danger .wn-badge-ring { background: var(--fn-red-200); box-shadow: inset 0 0 0 2px var(--fn-red-600); }
.wn-badge--none .wn-badge-ring { background: transparent; box-shadow: none; border: 2px dashed var(--fn-line-strong); }
.wn-badge--none .wn-badge-num { color: var(--fn-ink-300); }
.wn-badge--none .wn-badge-status { color: var(--fn-leaf-cta); font-weight: 600; }
/* On the wider web layout the phone-sized dashboard groups stretch thin — keep them snug & centred.
   (No effect on a narrow phone, where the card is already < 480px.) */
.wn-youstats, .wn-progress, .wn-badges { max-width: 480px; margin-inline: auto; }

/* --- The day band: the dashboard's lead, in the session screen's own language ------------
   Canopy ground, the numbers strip the session pins to its top, and exactly one thing to press. It is the

/* The small ring, for the tappable "you" row on a phone. Lives here rather than in the app's own styles, which is
   where it used to be — and is why a change to the ring landed on one host and not the other. */
.wn-ring--sm { width: 52px; height: 52px; }
.wn-ring--sm::before { inset: 6px; }
.wn-ring--sm .wn-ring-num { font-size: var(--fn-text-sm); }

/* The record card ("You") — one component, both hosts. */
.wn-record-top { display: flex; align-items: flex-start; justify-content: space-between; gap: .5rem; }
.wn-record-head { display: block; font-size: var(--fn-text-sm); color: var(--fn-ink-500); }
.wn-badge { background: none; border: 0; font: inherit; cursor: pointer; }
.wn-badge.is-open .wn-badge-ring { box-shadow: inset 0 0 0 2px var(--fn-forest-700); }

/* --- Family access: invite banner + connected list (child profile) --------------------- */
.btn-sm { padding: .28rem .6rem; font-size: var(--fn-text-xs); min-height: 0; }

.family-invite {
    position: relative; display: flex; gap: 1.1rem; margin-top: 1.5rem;
    padding: 1.5rem 1.6rem; border-radius: var(--fn-radius-lg);
    background: linear-gradient(135deg, var(--fn-forest-700), var(--fn-forest-600));
    color: #fff; box-shadow: var(--fn-shadow); overflow: hidden;
}
.family-invite::after {
    content: ""; position: absolute; inset: 0; background-image: var(--fn-fern);
    background-size: 150px; opacity: .55; pointer-events: none;
}
.family-invite__art {
    flex: none; width: 56px; height: 56px; border-radius: 50%; display: grid; place-items: center;
    background: rgba(255,255,255,.16); color: #fff; position: relative; z-index: 1;
}
.family-invite__body { position: relative; z-index: 1; flex: 1; min-width: 0; }
.family-invite__title { font-family: var(--fn-font-display); font-size: var(--fn-text-xl); margin: 0 0 .4rem; color: #fff; }
.family-invite__lede { margin: 0 0 1.1rem; max-width: 64ch; color: rgba(255,255,255,.9); font-size: var(--fn-text-sm); line-height: 1.55; }
/* Two tidy rows: name + relationship, then email + the invite button — not a stack of full-width inputs. */
.family-invite__form { display: grid; grid-template-columns: 1fr 1fr; gap: .5rem; align-items: center; }
.family-invite__form input, .family-invite__form select { margin: 0; width: 100%; }
.family-invite__form .family-invite__cta { white-space: nowrap; }
@media (max-width: 560px) { .family-invite__form { grid-template-columns: 1fr; } }
.family-invite__cta { background: #fff; color: var(--fn-forest-700); border-color: #fff; font-weight: 600; }
.family-invite__cta::before, .family-invite__cta::after { display: none; }
.family-invite__cta:hover:not(:disabled) { background: var(--fn-paper); }
.family-invite__msg { margin: .75rem 0 0; color: #fff; font-size: var(--fn-text-sm); }
.family-invite__steps { list-style: none; display: flex; gap: 1.3rem; margin: 1.25rem 0 0; padding: 0; flex-wrap: wrap; }
.family-invite__steps li { display: flex; align-items: center; gap: .55rem; font-size: var(--fn-text-xs); color: rgba(255,255,255,.88); flex: 1; min-width: 190px; }
.family-invite__steps span {
    flex: none; width: 23px; height: 23px; border-radius: 50%; display: grid; place-items: center;
    background: var(--fn-leaf-cta); color: var(--fn-leaf-cta-ink); font-weight: 700; font-size: var(--fn-text-xs);
}

.family-card__head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; flex-wrap: wrap; margin-bottom: .5rem; }
.family-row { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 11px 0; border-bottom: 1px solid var(--fn-line); }
.family-row__who { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.family-row__name { font-weight: 600; }
.family-add { display: flex; gap: .5rem; margin-top: 1rem; flex-wrap: wrap; align-items: stretch; }
.family-invite__alt { background: none; border: 0; padding: .6rem 0 0; color: rgba(255,255,255,.92); font: inherit; font-size: var(--fn-text-xs); text-decoration: underline; cursor: pointer; }
.family-invite__alt:hover:not(:disabled) { color: #fff; }
.family-invite__alt:disabled { opacity: .6; cursor: default; }
.family-code { display: inline-flex; align-items: center; gap: .4rem; margin-top: 3px; font-size: var(--fn-text-xs); color: var(--fn-ink-500); }
.family-code code { font-family: ui-monospace, "SFMono-Regular", Menlo, monospace; font-size: var(--fn-text-sm); letter-spacing: .12em; background: var(--fn-paper-2); border: 1px solid var(--fn-line-strong); border-radius: var(--fn-radius-sm); padding: .12rem .45rem; color: var(--fn-ink-900); }

/* --- Family requests (parent self-service join code + staff approval) ------------------- */
.fn-nav-badge { display: inline-grid; place-items: center; min-width: 18px; height: 18px; padding: 0 5px; margin-left: auto; border-radius: var(--fn-radius-pill); background: var(--fn-red-600); color: #fff; font-size: var(--fn-text-xs); font-weight: 700; line-height: 1; }

/* DSL-only marker pill on a nav link — flags the safeguarding access boundary. */
.fn-nav-tag { margin-left: auto; padding: 1px 7px; border-radius: var(--fn-radius-pill); background: var(--fn-leaf-400); color: var(--fn-forest-900); font-size: var(--fn-text-xs); font-weight: 700; letter-spacing: .04em; line-height: 1.5; }
.family-joincode { display: flex; justify-content: space-between; align-items: center; gap: 1rem; flex-wrap: wrap; margin-top: 1.25rem; }
.family-joincode__code code { font-family: ui-monospace, "SFMono-Regular", Menlo, monospace; font-size: var(--fn-text-2xl); letter-spacing: .2em; font-weight: 700; color: var(--fn-forest-700); background: var(--fn-paper-2); border: 2px dashed var(--fn-line-strong); border-radius: var(--fn-radius); padding: .4rem 1rem; }
.family-req { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; padding: 12px 0; border-bottom: 1px solid var(--fn-line); }
.family-req__main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.family-req__act { display: flex; align-items: flex-end; gap: 8px; flex-wrap: wrap; }
.family-req__act select { min-width: 160px; }
