/* ==========================================================================
   GLP-Won design system — light/dark, teal + trophy-gold, mobile-first.
   Recreates the look & feel from the requirements mockups.
   ========================================================================== */

/* --- Brand typeface: Plus Jakarta Sans (self-hosted, no CDN) --- */
@font-face {
    font-family: "Plus Jakarta Sans";
    font-style: normal; font-weight: 400; font-display: swap;
    src: url("../fonts/plus-jakarta-sans-400.woff2") format("woff2");
}
@font-face {
    font-family: "Plus Jakarta Sans";
    font-style: normal; font-weight: 600; font-display: swap;
    src: url("../fonts/plus-jakarta-sans-600.woff2") format("woff2");
}
@font-face {
    font-family: "Plus Jakarta Sans";
    font-style: normal; font-weight: 700; font-display: swap;
    src: url("../fonts/plus-jakarta-sans-700.woff2") format("woff2");
}
@font-face {
    font-family: "Plus Jakarta Sans";
    font-style: normal; font-weight: 800; font-display: swap;
    src: url("../fonts/plus-jakarta-sans-800.woff2") format("woff2");
}

:root {
    /* Tells the UA which way the page leans, which is what colours native form
       controls, spinners, scrollbars and autofill. Without it those follow the
       *device* setting, so a member on a light OS running the dark theme gets
       black `fieldtext` in the transparent number inputs on /Onboarding/Nutrition. */
    color-scheme: light;

    /* Brand teal ramp. 500/700/400/300 are the anchor brand values; the rest
       are derived to keep an even lightness step across the ramp. */
    --teal-900: #072530;
    --teal-800: #0a3644;
    --teal-700: #0f4a5a;
    --teal-600: #105c72;
    --teal-500: #126d86;
    --teal-400: #118fbd;
    --teal-300: #9ad2d0;
    --teal-100: #e3f0f4;
    --gold: #e8b04b;
    --gold-light: #f5c868;
    --green: #22c07b;
    --green-soft: #d8f6e7;
    /* Inks are the text colours of their hues. Each clears WCAG AA (4.5:1) on white and on
       its own soft fill at the small sizes chips and deltas use; the hue colours above do
       not, which is why text never takes --green, --gold or --red directly. */
    --green-ink: #0f7a48;
    --gold-ink: #8a6413;
    --red-ink: #c22c3d;
    --warn-soft: rgba(245,158,66,.15);
    --warn-ink: #95550d;
    --red: #ef5b6b;
    --orange: #f59e42;

    /* Gradient stays dark enough that white button text clears AA at the light end. */
    --grad-primary: linear-gradient(135deg, #147a9c 0%, #0f4a5a 100%);
    --grad-hero: linear-gradient(160deg, #126d86 0%, #072530 100%);
    --grad-gold: linear-gradient(135deg, #f5c868 0%, #e0982f 100%);

    /* light theme tokens.
       The ground is a warm neutral rather than a tint of the brand teal. Every
       card in the product is pure white, so a cool blue-green page put the two
       within a few points of each other on the same hue and the cards stopped
       reading as objects sitting on something. A warm ground is the largest
       available contrast against white that is not a value change. */
    --bg: #f6f5f2;
    --bg-2: #eeece7;
    /* The ground under the hero, on the hero's own 160deg axis so the two read
       as one surface lit from the same corner rather than a flat panel butted
       under a graded one. --bg is the middle stop, not an endpoint, so the page
       keeps the value it was tuned at and only the ends move. The spread is
       ~24 points at the foot, which is where a warm neutral stops being a
       gradient you have to look for; the ceiling is --border (#e5e2db), since
       past that the darker end of the ground is darker than the line drawn
       around the cards sitting on it. */
    --grad-ground: linear-gradient(160deg, #fefdfb 0%, #f6f5f2 45%, #e7e3da 100%);
    --surface: #ffffff;
    --surface-2: #faf9f7;
    --card-shadow: 0 4px 16px rgba(30, 40, 45, 0.07);
    --text: #16232a;
    /* Warmed to sit with the ground, but not lightened: the warm neutral reads
       lighter than the old cool grey at equal luminance, and matching it by eye
       took --text-muted under AA on white (4.46). Measured 5.46 on --surface,
       5.19 on --surface-2, 4.33 on --track — better than the previous #5a747d
       on all three. */
    --text-muted: #5c6c73;
    --border: #e5e2db;
    --chip-bg: #eef0ee;
    --track: #e7e5df;
    /* Teal that has to carry *text* — links, .text-teal, outline buttons. The
       brand 500 is a dark teal, so it reads on a light ground and fails on a
       black one; dark mode swaps in the light end of the ramp. */
    --accent: var(--teal-500);
    /* Mobile bottom nav sits dark teal even in light mode. */
    --nav-bg: rgba(7, 37, 48, 0.94);
    --nav-border: #0a3644;
    --nav-fg: #93b8c2;
    --nav-fg-active: #ffffff;
}

:root[data-theme="dark"] {
    color-scheme: dark;
    /* Slate + teal. The ground is deliberately *not* #000: elevation here is
       carried by lightness, not by shadow — a shadow is invisible against black,
       so on a pure-black ground --card-shadow did nothing and the border was the
       only thing separating a card from the page. That inverted every surface
       built on --track — the dashboard's tiles, since replaced by the ring
       stack, read as raised while the card containing them read as a hole.
       Lifting the floor to #0a1519 gives the
       ladder bg -> surface -> surface-2 -> track four even steps with room
       underneath, and keeps one hue across ground and surfaces so a card reads
       as elevated rather than merely tinted.
       --text is off-white for the same reason: #fff on #000 is maximum contrast,
       which is not the same as best contrast — it halates on OLED. */
    --bg: #0a1519;
    --bg-2: #0f1f25;
    /* Same ramp, narrower: the dark ladder bg -> surface -> surface-2 -> track
       has four steps in about 26 points, so a ground ramp as wide as the light
       one would cross --surface and float the cards. The light end stops just
       under #14252c for that reason; the foot has the whole way down to black
       to spend, so this widens downward rather than symmetrically. */
    --grad-ground: linear-gradient(160deg, #102028 0%, #0a1519 45%, #040c0f 100%);
    --surface: #14252c;
    --surface-2: #1b3138;
    --card-shadow: 0 6px 20px rgba(0, 0, 0, 0.45);
    --text: #e8f1f3;
    --text-muted: #93aeb6;
    --border: #26424c;
    --chip-bg: #1c333c;
    --track: #24404a;
    --nav-bg: rgba(6, 15, 19, 0.92);
    --nav-border: #26424c;
    --nav-fg: #93aeb6;
    --nav-fg-active: #56c9d8;
    /* --teal-300 (#9ad2d0) is a pale mint that barely reads as the brand once it
       is the only teal on screen. This is the same ramp position with the chroma
       put back, and it clears AA on --bg, --surface and --surface-2 alike. */
    --accent: #56c9d8;
    /* The gradients live on :root, where they are tuned for a light ground —
       --grad-hero ended at #072530, within a few points of the old black page, so
       the hero card dissolved at its bottom edge. Both are restated here against
       this ground rather than inherited. */
    --grad-hero: linear-gradient(160deg, #12718b 0%, #0b2731 100%);
    --grad-primary: linear-gradient(135deg, #1a90b4 0%, #12657d 100%);
    /* The "selected / accented surface" tone. It has to sit *above* --surface-2,
       because that is what the unselected tile already is — below it, a chosen
       preference tile is fractionally darker than an unchosen one and the state
       is carried by the border alone. */
    --teal-100: #1d4d5e;
    /* Light-mode success and warning are pale fills with dark ink; unswapped
       they punch a bright mint or amber block through a black page. */
    --green-soft: rgba(34,192,123,.15);
    --green-ink: #6ee7b0;
    --warn-soft: rgba(245,158,66,.16);
    --warn-ink: #f6c07a;
    --gold-ink: #f5c868;
    --red-ink: #ff8a96;
}

* { box-sizing: border-box; }

html, body {
    margin: 0;
    padding: 0;
    background: var(--bg);
    color: var(--text);
    font-family: "Plus Jakarta Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    font-size: 16px;
    line-height: 1.45;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
/* A link inside a sentence is underlined. Colour alone does not tell it apart from the words
   around it for everyone (WCAG 1.4.1); buttons and chips are shaped, so they are left alone. */
p a:not(.btn):not(.chip),
.card li a:not(.btn):not(.chip) { text-decoration: underline; text-underline-offset: 2px; }

/* One keyboard focus indicator for everything that is not a text field (fields have their
   own ring below). Browser defaults differ, and on the teal hero some of them vanish —
   WCAG 2.4.7 needs focus to be visible everywhere, not only where the default happens to
   show. :focus-visible, so a mouse click does not leave a ring behind. */
a:focus-visible, button:focus-visible, summary:focus-visible,
[role="button"]:focus-visible, [tabindex]:focus-visible,
input[type="checkbox"]:focus-visible, input[type="radio"]:focus-visible, input[type="range"]:focus-visible {
    outline: 2px solid var(--teal-400);
    outline-offset: 2px;
}

/* --- App shell: phone-width column centered on desktop --- */
.app-shell {
    max-width: 460px;
    margin: 0 auto;
    min-height: 100vh;
    /* The shell, not body: with .has-nav this box is exactly the visible column
       and .app-main is the scroller, so the ramp spans the screen once and stays
       put as content moves over it — the same relationship the hero band has to
       its own box. On body it would span the document and flatten to nothing on
       a long page. */
    background: var(--grad-ground);
    position: relative;
    padding-bottom: 88px; /* room for bottom nav */
    box-shadow: 0 0 60px rgba(10, 60, 80, 0.07);
}

.app-main { padding: 16px 18px 24px; }

/* --- Native-app frame (mobile) ---------------------------------------------
   Screens with nav become a fixed-height column: top bar pinned, .app-main the
   only scroller, nav resting on the bottom edge. 100dvh (not vh) so the bar
   doesn't sit under a mobile browser's collapsing URL chrome. Full-screen flows
   (login, onboarding) have no .has-nav and keep normal document scrolling. */
.app-shell.has-nav {
    height: 100dvh;
    min-height: 0;
    padding-bottom: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
/* .app-content is display:contents on mobile, so .topbar and .app-main are the
   real flex children here. */
.app-shell.has-nav .topbar { flex: 0 0 auto; }
.app-shell.has-nav .app-main {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
}
.app-shell.wide { max-width: 480px; }

/* --- Top bar --- */
.topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 18px 18px 4px;
}
.topbar .brand { font-weight: 800; font-size: 1.5rem; letter-spacing: -0.5px; }
.brand .tm { font-size: .6em; vertical-align: super; color: var(--text-muted); }
.brand-teal { color: var(--teal-500); }
/* The mark, not a second headline — .78em keeps it under the cap height of the
   wordmark it sits beside, and the negative letter-spacing on .brand would
   otherwise pull the glyph into the G. */
.brand .brand-mark { color: var(--gold); margin-right: 7px; letter-spacing: normal; }
.brand .brand-mark .icon { width: .78em; height: .78em; vertical-align: -0.02em; stroke-width: 2.2; }

/* --- Cards --- */
.card {
    background: var(--surface);
    border-radius: 20px;
    padding: 18px;
    box-shadow: var(--card-shadow);
    border: 1px solid var(--border);
    margin-bottom: 16px;
}
.card.tight { padding: 14px 16px; }
.card-title { font-weight: 700; font-size: 1.02rem; margin: 0 0 12px; }
.card-hero {
    background: var(--grad-hero);
    color: #fff;
    border: none;
}
.card-hero .card-title, .card-hero .muted { color: rgba(255,255,255,.85); }

.muted { color: var(--text-muted); }
.small { font-size: .82rem; }
.tiny { font-size: .72rem; }
.strong { font-weight: 700; }
.center { text-align: center; }
.row { display: flex; }
.between { justify-content: space-between; }
.items-center { align-items: center; }
.items-start { align-items: flex-start; }
.gap-8 { gap: 8px; } .gap-12 { gap: 12px; } .gap-16 { gap: 16px; }
.wrap { flex-wrap: wrap; }
/* min-width:0 or a flex child floors at its content width and pushes the row
   past its card — the default min-width:auto is what breaks narrow phones. */
.grow { flex: 1; min-width: 0; }
.mt-8{margin-top:8px}.mt-12{margin-top:12px}.mt-16{margin-top:16px}.mt-24{margin-top:24px}
.mb-0{margin-bottom:0}.mb-8{margin-bottom:8px}.mb-12{margin-bottom:12px}.mb-16{margin-bottom:16px}

/* --- Buttons --- */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    border: none;
    border-radius: 14px;
    padding: 14px 20px;
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
    font-family: inherit;
    transition: transform .06s ease, box-shadow .2s ease, opacity .2s;
    text-decoration: none;
}
.btn:hover { text-decoration: none; }
.btn:active { transform: scale(.98); }
.btn-primary {
    background: var(--grad-primary);
    color: #fff;
    box-shadow: 0 8px 20px rgba(18, 109, 134, .32);
}
.btn-gold { background: var(--grad-gold); color: #3a2a00; box-shadow: 0 8px 20px rgba(224,152,47,.28); }
.btn-ghost { background: var(--chip-bg); color: var(--text); }
.btn-outline { background: transparent; border: 1.5px solid var(--teal-400); color: var(--accent); }
.btn-block { display: flex; width: 100%; }
.btn-sm { padding: 9px 14px; font-size: .85rem; border-radius: 11px; }

/* --- Chips / pills --- */
.chip {
    display: inline-flex; align-items: center; gap: 6px;
    background: var(--chip-bg); color: var(--text);
    border-radius: 999px; padding: 6px 12px; font-size: .8rem; font-weight: 600;
    border: 1px solid transparent;
    /* Chips sit in flex rows next to a fixed-width action button; on a 320px
       phone they have to give way rather than push the row wide. */
    min-width: 0; overflow-wrap: anywhere;
}
.chip.gold { background: rgba(232,176,75,.16); color: var(--gold-ink); }
.chip.green { background: var(--green-soft); color: var(--green-ink); }
.pill-phase {
    display:inline-block; background: rgba(255,255,255,.16);
    padding: 4px 12px; border-radius: 999px; font-size:.75rem; font-weight:700;
}

/* --- Stat tiles --- */
/* minmax(0,…) not 1fr: a plain 1fr floors at min-content, so one long value
   (a three-up grid on a 320px phone) pushes the whole grid past the card. */
.stat-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.stat-grid.three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.stat {
    background: var(--surface-2); border: 1px solid var(--border);
    border-radius: 16px; padding: 14px; min-width: 0;
}
.stat .val { font-size: 1.5rem; font-weight: 800; line-height: 1.1; overflow-wrap: anywhere; }
/* The editable tiles on /Onboarding/Nutrition drop the input's chrome inline, but
   an <input> does not inherit colour — without this it takes the UA's `fieldtext`
   and the value follows the *device* theme rather than the app's. */
.stat input { color: inherit; }
.stat .lbl { font-size: .74rem; color: var(--text-muted); margin-top: 2px; overflow-wrap: anywhere; }
.stat .delta { font-size: .74rem; font-weight: 700; }
.delta.up { color: var(--green-ink); } .delta.down { color: var(--red-ink); }
.text-green{color:var(--green-ink)}.text-red{color:var(--red-ink)}.text-gold{color:var(--gold-ink)}
.text-teal{color:var(--accent)}.text-orange{color:var(--orange)}

/* --- Momentum / progress ring --- */
.ring { --p: 0; --size: 96px; --stroke: 9px; width: var(--size); height: var(--size); position: relative; flex: 0 0 auto; }
.ring svg { transform: rotate(-90deg); width: 100%; height: 100%; }
.ring .track { stroke: var(--track); }
.ring .fill { stroke: url(#ringGrad); stroke-linecap: round; transition: stroke-dashoffset .6s ease; }
.ring .ring-label {
    position: absolute; inset: 0; display: flex; flex-direction: column;
    align-items: center; justify-content: center; text-align: center;
}
.ring .ring-num { font-size: 1.5rem; font-weight: 800; line-height: 1; }
.ring .ring-sub { font-size: .62rem; color: var(--text-muted); }

/* --- Activity-ring stack -------------------------------------------------
   Three concentric arcs, read on Home beside a legend that carries the tap
   targets. The hues are the brand's own — teal, trophy-gold, green — rather
   than the split-complementary coral/green/violet triad that stood here
   before. Two things bought that change: the stack now sits on a white card
   overlapping a teal hero, where a coral outer ring read as a warning, and
   the legend's percentages are *text* beside the arcs rather than muted
   detail lines, which needs an ink per hue anyway.

   So each tone carries two values, and the split is the whole point:

     --ring-<tone>-c1   the arc and the legend dot — a *graphic*, 3:1 on the card
     --ring-<tone>-ink  the legend's percentage — *text*, 4.5:1 on the card

   Gold is the reason the pair exists. #e8b04b is a fine 18px arc and a
   failing 11.5px label, so the arc keeps the brand value and the label takes
   #b96a12 (--warn-ink). Reading one variable for both is what would quietly
   ship the failing version.

   Declared on :root, not on .ring-stack: the legend is a sibling of the
   stack, so a variable set on the stack would not reach the row dots.
   initRingStacks() reads them by name — `--ring-<tone>-c1`, where <tone> is
   the lowercased RingDomain — and getComputedStyle resolves inherited
   custom properties. */
:root {
    --ring-nutrition-c1: #126d86; --ring-nutrition-ink: #126d86;  /* brand teal  */
    --ring-habits-c1:    #e8b04b; --ring-habits-ink:    #95550d;  /* trophy gold */
    --ring-care-c1:      #22c07b; --ring-care-ink:      #0f7a48;  /* green       */
}
/* The dark ground eats the deep end of every ramp: the brand teal goes muddy
   as an arc and both inks vanish, so all three inks lift to their light-mode
   partners. Gold and green hold as arcs and are left alone. */
:root[data-theme="dark"] {
    --ring-nutrition-c1: #56c9d8; --ring-nutrition-ink: #56c9d8;
    --ring-habits-c1:    #e8b04b; --ring-habits-ink:    #f6c07a;
    --ring-care-c1:      #22c07b; --ring-care-ink:      #6ee7b0;
}
.ring-stack {
    width: 150px; max-width: 100%; aspect-ratio: 1; flex: 0 0 auto;
}
.ring-stack svg { width: 100%; height: 100%; transform: rotate(-90deg); display: block; }
.ring-stack .arc { transition: stroke-dashoffset .9s cubic-bezier(.22,.9,.28,1); }
/* The overshoot lap sits over the closed ring. Its shadow is what separates the
   two laps — without it a 150% arc is indistinguishable from a 50% one. */
.ring-stack .arc-over { filter: drop-shadow(0 0 4px rgba(0, 0, 0, .45)); }
/* Vacation Mode: still legible, no longer shouting. */
.ring-stack.is-paused { opacity: .55; }

/* The mean, centred in the hole. A sibling of .ring-stack rather than a child:
   initRingStacks() calls replaceChildren() on the stack, so anything nested
   inside it is destroyed on every theme switch. */
.ring-stack-wrap { position: relative; flex: 0 0 auto; }
.ring-stack-mean {
    position: absolute; inset: 0; display: flex; align-items: center;
    justify-content: center; font-size: 20px; font-weight: 800; line-height: 1;
    pointer-events: none;
}
.ring-stack-mean span { font-size: 11px; font-weight: 700; color: var(--text-muted); }

/* A 0.9s triple sweep is a lot of motion for anyone who asked for less. The rings
   still render at their final value — only the travel is dropped. */
@media (prefers-reduced-motion: reduce) {
    .ring-stack .arc { transition: none; }
    .ring .fill { transition: none; }
}

/* ==========================================================================
   Home & Today — the two screens that share a hero.

   Both open on a full-bleed band carrying the date, the streak and today's
   Win Points, with the first card overlapping its lower edge. That overlap
   is the layout: it is what stops the band reading as a header bolted above
   a list of cards, and it is why these screens abandon the shared .card
   rhythm rather than compacting it.

   The gutter here is 26px, not the 18px .app-main uses elsewhere, because
   the band runs to the shell's edge and a card inset only 18px from a
   full-bleed surface reads as misaligned rather than inset.
   ========================================================================== */

/* .app-main hands its padding to the blocks inside, so the hero can bleed. The
   second selector is not redundant: the desktop rule restates the padding at
   the same specificity *later* in the file, so a tie would go to it. */
.app-main.flow-bleed,
.app-shell.has-nav .app-main.flow-bleed { padding: 0 0 26px; }

/* These screens have no .topbar — the hero is the header, as the design has it. So
   the band is the first thing under the notch and has to own the status-bar inset
   the way .bottom-nav already owns the home-indicator one; without it the date row
   sits under the clock. */
.screen-hero {
    background: var(--grad-hero);
    color: #fff;
    padding: calc(22px + env(safe-area-inset-top)) 26px 34px;
}
.screen-hero-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.hero-date {
    font-size: 11px; font-weight: 700; letter-spacing: .14em;
    text-transform: uppercase; color: rgba(255,255,255,.65);
}
/* Gold on the teal band, which is where --gold-light rather than --gold is the
   legible one — the brand 500 gold is tuned for a light card. */
.hero-streak {
    display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto;
    font-size: 11.5px; font-weight: 700; color: var(--gold-light); text-decoration: none;
    /* Padding for the finger, negative margin so the row keeps its height. */
    padding: 8px 4px; margin: -8px -4px;
}
.hero-streak:hover { text-decoration: none; color: var(--gold-light); }
.hero-streak i {
    width: 7px; height: 7px; border-radius: 50%; background: var(--gold-light); flex: 0 0 auto;
}
.hero-title { font-size: 26px; font-weight: 800; letter-spacing: -.02em; margin-top: 6px; }
.hero-metrics { display: flex; align-items: center; gap: 14px; margin-top: 14px; }
.hero-points { flex: 1; min-width: 0; }
.hero-points-row {
    display: flex; justify-content: space-between; gap: 8px;
    font-size: 11.5px; color: rgba(255,255,255,.85); margin-bottom: 6px;
}
.hero-points-row strong { color: #fff; }
/* Not .progress: that is 10px on --track, and this bar sits on the band where
   the track has to be the band's own tint. */
.hero-bar { height: 6px; border-radius: 3px; background: rgba(255,255,255,.2); overflow: hidden; }
.hero-bar > span { display: block; height: 100%; border-radius: 3px; background: var(--grad-gold); }
.hero-momentum { flex: 0 0 auto; text-align: right; }
.hero-momentum b { display: block; font-size: 26px; font-weight: 800; line-height: 1; }
.hero-momentum span { font-size: 10px; color: rgba(255,255,255,.65); }

/* --- The cards below it ---
   .overlap sits over the band's lower edge; everything after it stacks at
   14px. A deeper shadow on the overlapping card only: it is the one with a
   dark surface behind part of it, where the standard .07 alpha disappears. */
.screen-card {
    margin: 14px 26px 0; background: var(--surface); border-radius: 18px;
    padding: 14px 16px; box-shadow: var(--card-shadow); border: 1px solid transparent;
}
.screen-card.overlap { margin-top: -18px; border-radius: 20px; padding: 18px; box-shadow: 0 4px 16px rgba(30,40,45,.1); }
/* Light mode carries elevation on the shadow alone; the dark theme's ground is
   close enough to the surface that a border is what separates them. */
:root[data-theme="dark"] .screen-card { border-color: var(--border); }

.screen-card-head {
    display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 4px;
}
.eyebrow {
    font-size: 11px; font-weight: 700; letter-spacing: .14em;
    text-transform: uppercase; color: var(--text-muted);
}
.head-link {
    font-size: 12px; font-weight: 700; color: var(--accent); text-decoration: none;
    display: inline-flex; align-items: center; gap: 4px; flex: 0 0 auto; white-space: nowrap;
    padding: 8px 4px; margin: -8px -4px;
}
.head-link:hover { text-decoration: none; }
.head-link .icon { width: .95em; height: .95em; }

/* --- Rings card: the stack, and the legend that carries the tap targets --- */
.rings-body { display: flex; align-items: center; gap: 18px; }
.ring-legend { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.rl-row {
    --rl-c: var(--accent); --rl-ink: var(--accent);
    display: flex; align-items: center; gap: 8px; padding: 8px 0;
    border-bottom: 1px solid var(--border); text-decoration: none; color: inherit;
}
.rl-row:last-child { border-bottom: 0; }
/* One definition per hue, inherited from :root — a legend dot and its arc
   cannot drift apart, and the dark theme is handled where the variables are. */
.rl-row[data-tone="nutrition"] { --rl-c: var(--ring-nutrition-c1); --rl-ink: var(--ring-nutrition-ink); }
.rl-row[data-tone="habits"]    { --rl-c: var(--ring-habits-c1);    --rl-ink: var(--ring-habits-ink); }
.rl-row[data-tone="care"]      { --rl-c: var(--ring-care-c1);      --rl-ink: var(--ring-care-ink); }
.rl-row:hover { text-decoration: none; }
.rl-row:focus-visible { outline: 2px solid var(--rl-c); outline-offset: 2px; border-radius: 8px; }
.rl-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--rl-c); flex: 0 0 auto; }
.rl-text { flex: 1; min-width: 0; }
/* Both are spans inside an <a> — an anchor may not contain a <div>, so the two
   lines have to be made block-level here rather than by their element. */
.rl-label { display: block; font-size: 13px; font-weight: 700; line-height: 1.2; }
.rl-sub {
    display: block; font-size: 11px; color: var(--text-muted);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* The ink, not the arc colour: this is 11.5px text and needs 4.5:1, which the
   gold arc does not clear on white. See the ring variable block above. */
.rl-pct { font-size: 11.5px; font-weight: 800; color: var(--rl-ink); flex: 0 0 auto; }
.rl-check { display: flex; color: var(--rl-ink); flex: 0 0 auto; }
.rl-check .icon { width: 14px; height: 14px; stroke-width: 3; }
/* A closed domain drops its label to muted — the row is still there to be read,
   but it is no longer asking for anything. */
.rl-row.is-closed .rl-label { color: var(--text-muted); }

/* --- Up next: the single highest-value open task ---
   The whole card is one target, and gold because it is the only thing on the
   screen being asked for. */
.upnext {
    display: flex; align-items: center; gap: 14px;
    text-decoration: none; color: inherit;
}
.upnext:hover { text-decoration: none; }
.upnext-ico {
    width: 40px; height: 40px; border-radius: 50%; background: var(--grad-gold);
    display: grid; place-items: center; flex: 0 0 auto; color: var(--teal-900);
}
.upnext-ico .icon { width: 15px; height: 15px; fill: currentColor; stroke: none; }
.upnext-text { flex: 1; min-width: 0; }
/* Spans made block-level for the reason .rl-label is: the whole card is one <a>. */
.upnext-eyebrow {
    display: block; font-size: 11px; font-weight: 700; letter-spacing: .08em;
    text-transform: uppercase; color: var(--text-muted);
}
.upnext-title { display: block; font-size: 14.5px; font-weight: 800; }
.upnext-hint { display: block; font-size: 12px; color: var(--text-muted); margin-top: 2px; }
.upnext-chev { display: flex; color: var(--text-muted); flex: 0 0 auto; }
.upnext-chev .icon { width: 14px; height: 14px; stroke-width: 2.5; }
/* Today leads on this card, so it is a size up and carries the coaching line. */
.upnext.lg { gap: 14px; }
.upnext.lg .upnext-ico { width: 44px; height: 44px; }
.upnext.lg .upnext-ico .icon { width: 17px; height: 17px; }
.upnext.lg .upnext-title { font-size: 15px; }

/* --- The three-stat row --- */
/* minmax(0,…) not 1fr: a plain 1fr floors at min-content, so one long value
   pushes the whole row past the gutter on a 320px phone. */
.stat-row { margin: 14px 26px 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.stat-cell {
    background: var(--surface); border-radius: 14px; padding: 12px 14px;
    border: 1px solid transparent; min-width: 0;
}
:root[data-theme="dark"] .stat-cell { border-color: var(--border); }
.stat-cell .k { font-size: 11px; font-weight: 600; color: var(--text-muted); overflow-wrap: anywhere; }
.stat-cell .v { font-size: 16px; font-weight: 800; margin-top: 2px; overflow-wrap: anywhere; }
.stat-cell .v span { font-size: 11px; font-weight: 600; color: var(--text-muted); }

.phase-line { margin: 14px 26px 0; font-size: 12px; color: var(--text-muted); text-align: center; }

/* --- Today's timeline ---------------------------------------------------
   A 28px rail down the left with the connector drawn *between* nodes rather
   than as one absolute line, so the last row simply omits it and nothing has
   to know which row is last. */
.tl-head { padding: 22px 26px 8px; }
.timeline { padding: 0 26px; }
.tl-row { display: flex; gap: 16px; }
.tl-rail { display: flex; flex-direction: column; align-items: center; width: 28px; flex: 0 0 auto; }
.tl-node {
    width: 28px; height: 28px; border-radius: 50%; flex: 0 0 auto;
    display: grid; place-items: center;
    background: var(--surface); border: 2px solid var(--border); color: var(--text-muted);
}
.tl-node .icon { width: 12px; height: 12px; }
.tl-node i { width: 8px; height: 8px; border-radius: 50%; background: var(--tl-c, var(--border)); display: block; }
.tl-line { width: 2px; flex: 1; background: var(--border); }
/* Green above the next node once a row is behind the member — the connector is
   what makes the list read as a day rather than as a stack of cards. */
.tl-row.is-done .tl-node { background: var(--green); border-color: transparent; color: #fff; }
.tl-row.is-done .tl-node .icon { stroke: #fff; stroke-width: 3; width: 13px; height: 13px; }
.tl-row.is-done .tl-line { background: var(--green); }
.tl-row.is-now .tl-node { background: var(--accent); border-color: transparent; }
.tl-row.is-now .tl-node i { background: #fff; }
.tl-row.is-future .tl-body { opacity: .7; }

.tl-body { padding: 4px 0 18px; min-width: 0; }
/* Block-level regardless of element: a linkable row is an <a> holding spans, and a
   done row is a <div> holding divs — the two have to lay out identically. */
.tl-kicker { display: block; font-size: 11px; font-weight: 600; color: var(--text-muted); }
.tl-title { display: block; font-size: 14px; font-weight: 700; }
.tl-detail { display: block; font-size: 12px; color: var(--text-muted); margin-top: 2px; }
a.tl-body { display: block; text-decoration: none; color: inherit; }
a.tl-body:hover { text-decoration: none; }

/* The "now" row is a card rather than a line of text — one row on the screen
   is what is being asked for, and it has to be the one that looks like it. */
.tl-now {
    flex: 1; min-width: 0; margin-bottom: 14px; display: block;
    background: var(--surface); border: 2px solid var(--accent); border-radius: 16px;
    padding: 12px 14px; text-decoration: none; color: inherit;
}
.tl-now:hover { text-decoration: none; }
.tl-now .tl-kicker { color: var(--accent); font-weight: 700; }
.tl-now .tl-title { font-size: 14px; font-weight: 800; }
.tl-bar { display: block; height: 5px; border-radius: 3px; background: var(--track); margin-top: 10px; overflow: hidden; }
.tl-bar > span { display: block; height: 100%; border-radius: 3px; background: var(--accent); }
.tl-foot { display: block; font-size: 11px; color: var(--text-muted); margin-top: 6px; }

/* --- Dark: the hero is chrome, not the gradient -------------------------
   The band is the same near-black as the bottom nav, with a hairline under
   it, so the screen is bracketed by two matching bars rather than by a teal
   header over a black footer. */
:root[data-theme="dark"] .screen-hero {
    background: var(--nav-bg);
    border-bottom: 1px solid var(--border);
}

/* Above 768px the bottom nav is gone and the teal sidebar rail runs down the
   left, meeting the hero along its whole edge. Painted normally each element
   resolves the gradient against its own box — a tall narrow rail and a short
   wide band land on different points of the ramp and meet in a visible seam —
   so both anchor to the viewport, the same trick the desktop chrome already
   uses to turn its corner. Not applied on phones: there is nothing beside the
   hero to match there, and a fixed background does not travel with the band
   as it scrolls. */
@media (min-width: 768px) {
    .app-shell.has-nav .screen-hero { background-attachment: fixed; }
}

/* --- Linear progress --- */
.progress { background: var(--track); border-radius: 999px; height: 10px; overflow: hidden; }
.progress > span { display: block; height: 100%; background: var(--grad-primary); border-radius: 999px; }
.progress.gold > span { background: var(--grad-gold); }

/* --- Lists / wins --- */
.win-row { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--border); }
.win-row:last-child { border-bottom: none; }
.win-ico {
    width: 38px; height: 38px; border-radius: 12px; background: var(--chip-bg);
    display: grid; place-items: center; font-size: 1.1rem; flex: 0 0 auto;
}
.win-check { margin-left: auto; font-size: 1.2rem; color: var(--track); }
.win-check.done { color: var(--green); }

/* --- Icons (monochrome outline SVG; size follows container font-size) --- */
.icon { width: 1em; height: 1em; display: inline-block; vertical-align: -0.14em; stroke: currentColor; fill: none; flex: 0 0 auto; }
.delta .icon { width: .82em; height: .82em; vertical-align: -0.05em; }
.chip .icon, .btn .icon, .badge-cat .icon { vertical-align: -0.15em; }

/* --- Bottom navigation --- */
/* Sits in the shell's flex column (see the app-frame block above) rather than floating
   over the content, so it's always on screen and never overlaps the last card. */
.bottom-nav {
    flex: 0 0 auto;
    background: var(--nav-bg); backdrop-filter: blur(12px);
    border-top: 1px solid var(--nav-border);
    display: flex; justify-content: space-around; padding: 8px 6px calc(8px + env(safe-area-inset-bottom));
    z-index: 50;
}
.bottom-nav a {
    display: flex; flex-direction: column; align-items: center; gap: 3px;
    color: var(--nav-fg); font-size: .64rem; font-weight: 600; text-decoration: none;
    padding: 4px 8px; border-radius: 12px; flex: 1;
}
.bottom-nav a .ni, .bottom-nav .nav-menu-btn .ni { font-size: 1.15rem; line-height: 1; }
.bottom-nav a.active { color: var(--nav-fg-active); }
.bottom-nav .nav-menu-btn {
    display: flex; flex-direction: column; align-items: center; gap: 3px;
    background: none; border: none; cursor: pointer;
    color: var(--nav-fg); font-size: .64rem; font-weight: 600; font-family: inherit;
    padding: 4px 8px; border-radius: 12px; flex: 1;
}

/* --- Quick Capture ---------------------------------------------------------
   The floating button rides just above the bottom nav and the sheet slides up from
   underneath it. Positioned against .app-shell rather than the viewport: the shell is a
   460px column centred on a wide screen, and a viewport-anchored button would float off
   in the margin beside it. */
.capture-fab {
    position: absolute; z-index: 55;
    /* Anchored to the shell's right edge rather than the viewport's: the shell is a 460px
       column centred on a wide screen, and a viewport-anchored button would float off in the
       margin beside it. `transform` is left entirely to the press animation — sharing it with
       positioning means every hover and :active rule has to restate the offset, and the one
       that forgets snaps the button sideways mid-tap. */
    right: 16px;
    bottom: calc(70px + env(safe-area-inset-bottom));
    width: 54px; height: 54px; border-radius: 50%; border: none; cursor: pointer;
    background: linear-gradient(135deg, var(--teal-400, #118fbd), var(--teal-600, #126d86));
    color: #fff; display: grid; place-items: center;
    box-shadow: 0 10px 26px rgba(18,109,134,.42);
    transition: transform .18s ease, box-shadow .18s ease;
}
.capture-fab .ni { font-size: 1.45rem; line-height: 1; display: block; }
.capture-fab:hover { transform: translateY(-2px); box-shadow: 0 14px 30px rgba(18,109,134,.5); }
.capture-fab:active { transform: scale(.94); }
/* Out of the way while the sheet it opened is up. */
body.capture-open .capture-fab { opacity: 0; pointer-events: none; }

.capture-overlay {
    position: fixed; inset: 0; background: rgba(0,0,0,.45); z-index: 70;
    opacity: 0; visibility: hidden; transition: opacity .25s ease;
}
.capture-sheet {
    position: fixed; z-index: 71;
    /* Same reasoning as the button: centred by auto margins, so the slide-up owns `transform`. */
    left: 0; right: 0; bottom: 0; margin: 0 auto; width: 100%; max-width: 460px;
    transform: translateY(100%);
    /* Hidden, not just moved. Off-screen alone leaves the upward shadow bleeding over the
       bottom edge, and a sheet lifted off the bottom (desktop) peeking out entirely — and
       either way its controls stay in the Tab order under aria-hidden. The delay holds it
       visible for the slide-down; the open rule drops the delay so it shows at once. */
    visibility: hidden;
    transition: transform .26s ease, visibility 0s linear .26s;
    background: var(--surface); border-top: 1px solid var(--border);
    border-radius: 20px 20px 0 0;
    padding: 22px 20px calc(22px + env(safe-area-inset-bottom));
    max-height: 88dvh; overflow-y: auto;
    box-shadow: 0 -12px 40px rgba(0,0,0,.22);
}
body.capture-open .capture-overlay { opacity: 1; visibility: visible; }
body.capture-open .capture-sheet {
    transform: translateY(0); visibility: visible;
    transition: transform .26s ease, visibility 0s;
}

.capture-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 16px; }
.capture-title { font-weight: 700; font-size: 1.2rem; }
.capture-sub { font-size: .86rem; margin-top: 3px; }

.capture-input-row { position: relative; margin-bottom: 14px; }
/* Tall enough for all three placeholder examples: they are the only instructions the box
   has, and a third line cut in half reads as a rendering fault. */
.capture-input-row textarea {
    width: 100%; padding: 14px 52px 14px 15px; border-radius: 14px;
    border: 1.5px solid var(--border); background: var(--surface-2); color: var(--text);
    font-size: 1.02rem; line-height: 1.5; font-family: inherit; resize: vertical; min-height: 132px;
}
.capture-input-row textarea:focus {
    outline: none; border-color: var(--teal-400); box-shadow: 0 0 0 3px rgba(17,143,189,.18);
}
.capture-mic {
    position: absolute; top: 9px; right: 9px;
    width: 36px; height: 36px; border-radius: 50%; cursor: pointer;
    border: 1px solid var(--border); background: var(--surface);
    color: var(--text-muted); display: grid; place-items: center;
}
.capture-mic .ni { font-size: 1rem; line-height: 1; display: block; }
.capture-mic.listening { color: #fff; background: var(--teal-500); border-color: transparent; }
.capture-mic-status { font-size: .84rem; margin: -6px 0 12px; color: var(--text-muted); }
.capture-mic-status.is-error { color: var(--warn-ink); }

.capture-result:not(:empty) { margin-top: 16px; }
.capture-card {
    background: var(--surface-2); border: 1px solid var(--border);
    border-radius: 16px; padding: 14px 16px;
}
.capture-card-head { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; font-size: .95rem; }
.capture-card-head .ni { font-size: 1.1rem; line-height: 1; color: var(--accent); }
.capture-card .field:last-of-type { margin-bottom: 12px; }
.capture-note { font-size: .78rem; margin: -4px 0 12px; }
/* The guardrail result. Amber rather than red: nothing went wrong, and the member is being
   pointed at the right place rather than told off. */
.capture-card-block { border-color: rgba(224,152,47,.5); background: rgba(232,176,75,.1); }
.capture-card-block .capture-card-head .ni { color: var(--gold); }
.capture-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 12px; }

/* Photo capture. The photo button sits beside Continue as a second way in, rather than in the
   textarea's corner with the mic: it is the larger action, and a member reaching for it has
   usually typed nothing. */
.capture-actions { display: flex; gap: 10px; }
.capture-actions [data-capture-go] { flex: 1; }
.capture-photo-btn { display: inline-flex; align-items: center; gap: 6px; }
.capture-photo-btn .ni { line-height: 1; display: block; }
.capture-lock { font-size: .8em; opacity: .7; }
.capture-result .upgrade-prompt { margin: 0; }
.capture-photo { display: flex; gap: 12px; align-items: flex-start; margin-bottom: 12px; }
.capture-photo img {
    width: 72px; height: 72px; flex: none; object-fit: cover;
    border-radius: 12px; border: 1px solid var(--border); background: var(--surface);
}
.capture-portion-seen { margin-top: 4px; }
.capture-options { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 12px; }
/* Rounded rectangles rather than pills: a catalog title runs to two lines, and a two-line pill
   reads as a rendering fault. */
.capture-option {
    cursor: pointer; border: 1.5px solid var(--border); background: var(--surface);
    border-radius: 12px; font: inherit; font-size: .78rem; font-weight: 600; text-align: left;
}
.capture-option[aria-pressed="true"] { border-color: var(--accent); box-shadow: 0 0 0 2px rgba(17,143,189,.18); }
.capture-option-kind {
    flex: none; white-space: nowrap;
    color: var(--text-muted); font-weight: 700; text-transform: uppercase; font-size: .66rem; letter-spacing: .04em;
}
/* The estimate marker on a food-log row. Gold ink on its soft fill clears 4.5:1 (see .chip.gold). */
.chip-est { padding: 1px 7px; font-size: .68rem; margin-left: 4px; vertical-align: 1px; }

@media (min-width: 768px) {
    /* The bottom nav is gone on desktop, so the button drops to the corner of the content
       pane. Still inside the shell, which is what keeps it off a 1600px-wide margin. */
    .capture-fab { right: 26px; bottom: 26px; }
    /* Lifted 26px off the bottom, so closing has to travel that far as well as its own
       height — translateY(100%) alone parks the top 26px of it on screen. */
    .capture-sheet {
        border-radius: 22px; bottom: 26px; max-width: 680px; padding: 28px 30px;
        transform: translateY(calc(100% + 26px));
    }
    .capture-title { font-size: 1.35rem; }
    .capture-sub { font-size: .92rem; }
    .capture-input-row textarea { min-height: 176px; font-size: 1.06rem; }
}

/* --- Shared nav menu (desktop sidebar + mobile drawer) --- */
.navmenu { display: flex; flex-direction: column; gap: 2px; }
.navmenu a, .navmenu summary, .navmenu button {
    display: flex; align-items: center; gap: 10px;
    padding: 9px 12px; border-radius: 10px;
    color: var(--text-muted); font-weight: 600; font-size: .84rem;
    text-decoration: none; cursor: pointer; list-style: none; user-select: none;
}
/* The log-out control is a button inside a POST form, not a link — strip the UA
   chrome so it sits on the same rail as every row above it. */
.navmenu button { width: 100%; background: none; border: 0; font-family: inherit; text-align: left; }
.navmenu summary::-webkit-details-marker { display: none; }
.navmenu summary::marker { content: ""; }
.navmenu a:hover, .navmenu summary:hover, .navmenu button:hover { background: var(--chip-bg); color: var(--text); text-decoration: none; }
.navmenu a.active, .navmenu summary.active { background: var(--teal-100); color: var(--teal-600); }
:root[data-theme="dark"] .navmenu a.active,
:root[data-theme="dark"] .navmenu summary.active { color: var(--teal-300); }
/* The icon does not shrink with the label — at .84rem the glyph is what keeps
   each row scannable, and a matching drop would make the rail read as disabled. */
.navmenu .ni { font-size: 1.05rem; line-height: 1; width: 20px; text-align: center; }
.navmenu .nav-caret { margin-left: auto; font-size: .85rem; color: var(--text-muted); transition: transform .2s ease; }
.navmenu .nav-group[open] > summary .nav-caret { transform: rotate(180deg); }
.navmenu .nav-sub { display: flex; flex-direction: column; gap: 2px; margin: 2px 0 4px; padding-left: 18px; }
/* Explicit display above overrides the UA rule that hides <details> content — re-hide when closed. */
.navmenu .nav-group:not([open]) .nav-sub { display: none; }
.navmenu .nav-sub a { font-size: .78rem; padding: 7px 10px; }
/* Pinned to the bottom of whichever menu holds it — margin-top:auto against the
   flex column of .side-nav and .nav-drawer alike. */
.nav-foot { margin-top: auto; padding-top: 10px; border-top: 1px solid var(--border); }
.nav-foot form { margin: 0; }
/* Notifications, settings, theme, log out: one row of icons. Each takes an equal share of the
   rail, so the hit area stays row-wide even though only the glyph is drawn. */
.nav-foot-icons { display: flex; gap: 2px; }
.nav-foot-icons > a, .nav-foot-icons > button, .nav-foot-icons > form { flex: 1 1 0; min-width: 0; }
.navmenu .nav-foot-icons a, .navmenu .nav-foot-icons button { justify-content: center; padding: 10px 0; position: relative; }
.navmenu .nav-foot-icons .ni { font-size: 1.15rem; width: auto; }
/* Fixed rather than --red-ink: the dark theme lifts that token to a pink white text fails on,
   and the badge has to read on the teal rail and the drawer's surface alike. */
.nav-count {
    position: absolute; top: 3px; left: calc(50% + 3px);
    min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px;
    background: #c22c3d; color: #fff;
    font-size: .62rem; font-weight: 800; line-height: 16px; text-align: center;
}

/* --- Mobile slide-in drawer (< 768px) --- */
.nav-drawer-overlay {
    position: fixed; inset: 0; background: rgba(0,0,0,.45); z-index: 60;
    opacity: 0; visibility: hidden; transition: opacity .25s ease;
}
.nav-drawer {
    position: fixed; top: 0; left: 0; bottom: 0; z-index: 61;
    width: 82%; max-width: 300px; padding: 18px 14px calc(18px + env(safe-area-inset-bottom));
    background: var(--surface); border-right: 1px solid var(--border);
    display: flex; flex-direction: column; gap: 4px; overflow-y: auto;
    transform: translateX(-100%); transition: transform .25s ease;
}
.nav-drawer .drawer-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.nav-drawer .side-brand { font-weight: 800; font-size: 1.3rem; letter-spacing: -.5px; }
.nav-drawer .side-brand .brand-teal { color: var(--teal-500); }
.nav-drawer .side-brand .tm { font-size: .6em; vertical-align: super; color: var(--text-muted); }
body.menu-open .nav-drawer-overlay { opacity: 1; visibility: visible; }
body.menu-open .nav-drawer { transform: translateX(0); }

/* --- Forms --- */
.field { margin-bottom: 14px; }
.field label { display: block; font-size: .82rem; font-weight: 600; margin-bottom: 6px; color: var(--text-muted); }
.field input, .field select, .field textarea {
    width: 100%; padding: 12px 14px; border-radius: 12px;
    border: 1.5px solid var(--border); background: var(--surface-2); color: var(--text);
    font-size: 1rem; font-family: inherit;
}
.field input:focus, .field select:focus, .field textarea:focus {
    outline: none; border-color: var(--teal-400); box-shadow: 0 0 0 3px rgba(17,143,189,.18);
}
.field-inline { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.field-inline label { margin: 0; color: var(--text); font-size: .95rem; }
/* .field-inline is a sibling of .field, not a child, so the control styling above
   never reached it — these rendered as bare 21px UA inputs (and, under 16px, made
   iOS zoom the page on focus). Same skin, sized to sit on one line. */
.field-inline input:not([type="checkbox"]):not([type="radio"]), .field-inline select {
    padding: 10px 12px; border-radius: 12px;
    border: 1.5px solid var(--border); background: var(--surface-2); color: var(--text);
    font-size: 1rem; font-family: inherit;
    width: auto; min-width: 120px; max-width: 60%; text-align: right;
}
.field-inline input:focus, .field-inline select:focus {
    outline: none; border-color: var(--teal-400); box-shadow: 0 0 0 3px rgba(17,143,189,.18);
}

/* Sliders: the UA's 2px side margins pushed a width:100% range past its card. */
input[type="range"] { width: 100%; margin: 8px 0 0; accent-color: var(--teal-500); }
.validation-summary-errors, .field-validation-error, .text-danger {
    color: var(--red); font-size: .82rem;
}

/* --- Selectable option cards (onboarding) --- */
.opt {
    display: flex; align-items: center; gap: 12px; width: 100%;
    background: var(--surface-2); border: 1.5px solid var(--border);
    border-radius: 14px; padding: 14px 16px; margin-bottom: 10px; cursor: pointer;
    color: var(--text); font-size: .95rem; font-weight: 600; text-align: left;
}
.opt .opt-ico { font-size: 1.2rem; }
.opt input { margin-left: auto; width: 20px; height: 20px; accent-color: var(--teal-500); }
.opt.selected { border-color: var(--teal-400); background: var(--teal-100); }
.opt-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.opt-grid .opt-tile {
    display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center;
    background: var(--surface-2); border: 1.5px solid var(--border); border-radius: 14px;
    padding: 14px 8px; cursor: pointer; font-size: .78rem; font-weight: 600; color: var(--text);
}
.opt-grid .opt-tile.selected { border-color: var(--teal-400); background: var(--teal-100); }
.opt-grid .opt-tile .ti { font-size: 1.3rem; }

/* --- Onboarding progress header --- */
.ob-head { text-align: center; margin-bottom: 18px; }
.ob-step { font-size: .72rem; color: var(--text-muted); font-weight: 700; letter-spacing: .5px; }
.ob-title { font-size: 1.4rem; font-weight: 800; margin: 6px 0 4px; letter-spacing: -.4px; }
.ob-sub { color: var(--text-muted); font-size: .88rem; }
.ob-progress { height: 5px; background: var(--track); border-radius: 999px; margin: 12px auto 0; max-width: 260px; overflow: hidden; }
.ob-progress > span { display: block; height: 100%; background: var(--grad-primary); }

/* --- Hero / trophy --- */
.trophy-badge {
    width: 132px; height: 132px; margin: 8px auto; border-radius: 28px;
    background: var(--grad-hero); display: grid; place-items: center;
    box-shadow: 0 12px 30px rgba(7,37,48,.35); font-size: 4rem;
    border: 3px solid var(--gold);
}
.hero-feature { display: flex; justify-content: space-around; text-align: center; margin: 18px 0; }
.hero-feature .hf { font-size: .72rem; color: var(--text-muted); max-width: 84px; }
.hero-feature .hf .hf-ico { font-size: 1.3rem; display:block; margin-bottom: 4px; color: var(--accent); }

/* --- Theme toggle --- */
.theme-toggle {
    background: var(--chip-bg); border: 1px solid var(--border); color: var(--text);
    width: 38px; height: 38px; border-radius: 12px; cursor: pointer; font-size: 1.1rem;
    display: inline-grid; place-items: center;
}

/* --- Segmented control --- */
.segment { display: inline-flex; background: var(--chip-bg); border-radius: 12px; padding: 3px; gap: 2px; }
.segment a, .segment button {
    border: none; background: transparent; color: var(--text-muted);
    padding: 6px 14px; border-radius: 10px; font-size: .82rem; font-weight: 600; cursor: pointer; text-decoration:none;
}
.segment a.active, .segment button.active { background: var(--surface); color: var(--text); box-shadow: 0 2px 6px rgba(0,0,0,.08); }
/* Light mode lifts the active pill to white against a tinted track. In dark the
   same two tokens invert — --surface (#14252c) is *darker* than --chip-bg
   (#1c333c) — so the selected segment read as the recessed one. Drop the track
   and raise the pill instead; the shadow reads as nothing on a dark ground either. */
:root[data-theme="dark"] .segment { background: var(--bg-2); }
:root[data-theme="dark"] .segment a.active,
:root[data-theme="dark"] .segment button.active { background: var(--surface-2); box-shadow: none; }

/* --- Alerts --- */
.alert { border-radius: 14px; padding: 12px 14px; font-size: .88rem; margin-bottom: 14px; }
.alert-info { background: var(--teal-100); color: var(--teal-700); }
.alert-warn { background: var(--warn-soft); color: var(--warn-ink); }
.alert-success { background: var(--green-soft); color: var(--green-ink); }
/* Urgent symptom escalation. Deliberately the loudest thing in the design system — it is
   used for exactly one message ("get medical help now") and losing it in a wall of teal
   cards is the failure mode the escalation engine exists to prevent. */
.alert-danger { background: #c22c3d; color: #fff; font-weight: 600; }
.alert-danger a { color: #fff; text-decoration: underline; }
:root[data-theme="dark"] .alert-info { color: var(--teal-300); }

/* --- Escalation & readiness ------------------------------------------------------- */

/* The four-level symptom banner. Level drives the accent only; the copy carries the meaning. */
.escalate-card { border-left: 4px solid var(--border); padding-left: 14px; }
.escalate-card.lvl-expected { border-left-color: var(--green); }
.escalate-card.lvl-selfcare { border-left-color: var(--teal-500); }
.escalate-card.lvl-prescriber { border-left-color: var(--orange); }
.escalate-card.lvl-urgent { border-left-color: var(--red); }

/* One dimension of the Transition Readiness Index: label, bar, explanation. */
.dim-row { padding: 10px 0; border-bottom: 1px solid var(--border); }
.dim-row:last-child { border-bottom: 0; }
.dim-bar { height: 7px; border-radius: 99px; background: var(--surface-2); overflow: hidden; margin: 6px 0 4px; }
.dim-bar > span { display: block; height: 100%; border-radius: 99px; background: var(--teal-500); }
/* Below TransitionReadinessService.DimensionFloor a dimension blocks the verdict on its
   own, whatever the mean is — so it is coloured as the blocker it is. */
.dim-bar.below-floor > span { background: var(--orange); }

.cycle-strip { display: flex; gap: 6px; flex-wrap: wrap; }
.cycle-day {
    flex: 1 1 0; min-width: 2.4rem; text-align: center;
    font-size: .7rem; font-weight: 700; padding: 6px 0;
    border-radius: 8px; background: var(--surface-2); color: var(--text-muted);
}
.cycle-day.is-today { background: var(--accent); color: #fff; }

.photo-strip { display: flex; gap: 10px; overflow-x: auto; -webkit-overflow-scrolling: touch; }
.photo-strip figure { margin: 0; flex: 0 0 112px; }
.photo-strip img { width: 112px; height: 140px; object-fit: cover; border-radius: 12px; display: block; }

/* Graduation criteria on the transcript. Replaces the synthesised credit totals. */
.criterion { display: flex; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--border); }
.criterion:last-child { border-bottom: 0; }
.criterion-mark { flex: 0 0 26px; height: 26px; border-radius: 50%; display: grid; place-items: center;
                  background: var(--surface-2); color: var(--text-muted); font-size: .78rem; font-weight: 700; }
.criterion.met .criterion-mark { background: var(--green-soft); color: var(--green-ink); }

/* Clinician packet: print-first, since the common case is a member taking paper to an
   appointment. Screen styling is the secondary concern here, not the other way round. */
.packet { max-width: 760px; margin: 0 auto; }
.packet h2 { font-size: 1.05rem; margin: 22px 0 8px; }
.packet table { width: 100%; border-collapse: collapse; font-size: .84rem; }
.packet th, .packet td { text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--border); }
.packet th { font-weight: 600; color: var(--text-muted); font-size: .78rem; text-transform: uppercase; letter-spacing: .03em; }
.packet-notice { border: 1px solid var(--border); border-radius: 12px; padding: 12px 14px;
                 font-size: .82rem; line-height: 1.5; margin-bottom: 18px; }
@media print {
    .topbar, .bottom-nav, .side-nav, .no-print { display: none !important; }
    .packet { max-width: none; }
    .packet-notice { border: 1px solid #000; }
}

/* --- Chat (AI coach) --- */
.chat-log { display: flex; flex-direction: column; gap: 10px; margin-bottom: 14px; }
.bubble { max-width: 82%; padding: 11px 14px; border-radius: 16px; font-size: .9rem; line-height: 1.4; }
.bubble.ai { background: var(--surface); border: 1px solid var(--border); align-self: flex-start; border-bottom-left-radius: 5px; }
.bubble.me { background: var(--grad-primary); color: #fff; align-self: flex-end; border-bottom-right-radius: 5px; }
.bubble.escalate { border: 1.5px solid var(--orange); background: rgba(245,158,66,.1); }
.chat-input { display: flex; gap: 8px; }
.chat-input input { flex: 1; }

/* --- Course cards --- */
.course-card { display: flex; gap: 12px; align-items: center; }
.course-ico { width: 46px; height: 46px; border-radius: 14px; background: var(--grad-primary); color:#fff; display:grid; place-items:center; font-size:1.3rem; flex:0 0 auto; }
.badge-cat { font-size: .68rem; font-weight: 700; color: var(--accent); text-transform: uppercase; letter-spacing: .4px; }

/* --- Misc --- */
.divider { height: 1px; background: var(--border); margin: 14px 0; }
.list-plain { list-style: none; padding: 0; margin: 0; }
hr { border: none; border-top: 1px solid var(--border); }
.footer-note { text-align: center; color: var(--text-muted); font-size: .72rem; padding: 8px 0 4px; }
canvas { max-width: 100%; }

/* ==========================================================================
   Second layout — tablet & desktop (>= 768px).
   Phones keep the mobile layout above, untouched. From 768px up, navigated
   app screens gain a persistent left sidebar (replacing the bottom nav) and
   their stacked cards flow into balanced columns to fill the wider canvas.
   Full-screen flows (login, onboarding) have no .has-nav and stay centered.
   ========================================================================== */

/* Wrapper is invisible on mobile so the shell lays out exactly as before. */
.app-content { display: contents; }
/* Sidebar is desktop/tablet only. */
.side-nav { display: none; }

@media (min-width: 768px) {
    /* Two-pane shell: sidebar rail + content pane. Still a fixed-height frame — the
       rail is always on screen and the content pane is the only thing that scrolls. */
    .app-shell.has-nav {
        display: grid;
        grid-template-columns: 224px minmax(0, 1fr);
        align-items: stretch;
        max-width: 1160px;
        padding-bottom: 0;
    }
    .app-shell.has-nav .app-content {
        display: block; min-width: 0;
        overflow-y: auto;
    }
    /* The content pane scrolls on desktop, so hand .app-main back to normal flow. */
    .app-shell.has-nav .app-main { overflow-y: visible; min-height: 0; }
    .app-shell.has-nav .bottom-nav { display: none; }

    /* --- Sidebar rail (full height, never scrolls away) --- */
    .side-nav {
        align-self: stretch;
        overflow-y: auto;
        display: flex; flex-direction: column; gap: 2px;
        padding: 22px 14px;
        background: var(--surface);
        border-right: 1px solid var(--border);
    }
    .side-brand { font-weight: 800; font-size: 1.4rem; letter-spacing: -.5px; padding: 4px 12px 18px; }
    .side-brand .brand-teal { color: var(--teal-500); }
    .side-brand .tm { font-size: .6em; vertical-align: super; color: var(--text-muted); }

    /* Drawer is mobile-only; sidebar carries the menu on desktop. */
    .nav-drawer, .nav-drawer-overlay { display: none !important; }

    /* Brand now lives in the sidebar — drop the duplicate from the top bar. */
    .app-shell.has-nav .topbar .brand { display: none; }

    /* Roomier gutters, aligned between the top bar and the content. */
    .app-shell.has-nav .topbar { padding: 22px 28px 6px; }
    .app-shell.has-nav .app-main { padding: 14px 28px 32px; }

    /* Card-stack screens: flow cards into balanced columns (masonry-style). */
    .app-shell.has-nav .app-main:not(.flow-single) {
        columns: 340px;
        column-gap: 22px;
    }
    .app-shell.has-nav .app-main:not(.flow-single) > * {
        break-inside: avoid;
        margin-bottom: 16px;
    }

    /* Reading / conversation screens stay a single comfortable measure. */
    .app-shell.has-nav .app-main.flow-single { max-width: 760px; }
}

/* Wide desktops: allow a third column of cards and a bit more breathing room. */
@media (min-width: 1280px) {
    .app-shell.has-nav { max-width: 1360px; }
}

/* ==========================================================================
   Touch pointers — the same markup, sized for a fingertip.
   Keyed off (pointer: coarse) rather than a width breakpoint: a touch laptop
   or a tablet in landscape needs these too, and a 375px-wide desktop window
   does not. Desktop density is left exactly as designed.
   ========================================================================== */
@media (pointer: coarse) {
    /* Every control a finger has to hit clears ~44px. */
    .segment a, .segment button { padding: 12px 16px; min-height: 44px; align-items: center; }
    a.chip, button.chip { min-height: 44px; padding: 10px 14px; }
    .btn-sm { padding: 12px 16px; }
    .theme-toggle { width: 44px; height: 44px; }
    .bottom-nav a, .bottom-nav .nav-menu-btn { min-height: 44px; justify-content: center; }

    /* iOS zooms the whole page when a focused control is under 16px. */
    input, select, textarea { font-size: 16px; }
    .field-inline input:not([type="checkbox"]):not([type="radio"]), .field-inline select { min-height: 44px; }

    /* A fatter slider thumb — the default is ~12px on Android. */
    input[type="range"] { height: 28px; }
}

/* ==========================================================================
   Landing page — the only screen with two genuinely different layouts.

   Phone: headline, trophy, and the two calls to action. The 12-month arc used
   to carry this page and now has one of its own (see "How it works" below) —
   four steps ahead of the CTA meant the phone's only button sat a screenful
   past the fold.

   Desktop (768px+): a hero band with the trophy beside the copy, features as
   cards below. This is the one screen that breaks the 460px column — .marketing
   on the shell, set by the view, is what unlocks it. Every other hideNav screen
   (login, onboarding) keeps the phone column at every width.

   One DOM serves both, and everything in it renders at both widths now that the
   arc has moved out — .landing-eyebrow is the only piece left that is phone-only.
   .landing-art and .landing-cards are in both, at two sizes and two column
   counts respectively.
   ========================================================================== */
.app-shell.marketing { padding-bottom: 0; }

.landing-hero { padding: 14px 18px 0; }

/* Sits on --bg, where the brand --gold (#e8b04b) is barely legible; .chip.gold
   is designed for a card, and this is the first line on the page. */
/* .chip.gold is two classes, so the colour override has to be too. */
.chip.gold.landing-eyebrow {
    font-size: .72rem; letter-spacing: .3px; text-transform: uppercase;
    color: #8a6413;
}
:root[data-theme="dark"] .landing-eyebrow { color: var(--gold-light); }

.landing-title {
    font-size: 2.1rem; line-height: 1.12; font-weight: 800;
    letter-spacing: -1.1px; margin: 16px 0 12px;
}
/* Relative to .landing-title so it tracks the clamp() the desktop rule sets,
   rather than needing a second absolute size at that breakpoint. */
.landing-title .lt-lead { font-size: 1.16em; letter-spacing: -.04em; }
.landing-title em { font-style: normal; color: var(--accent); }
.landing-sub { font-size: .95rem; color: var(--text-muted); line-height: 1.55; margin: 0; }

/* --- The arc ---
   Kept in the .landing- namespace after the move to /Home/HowItWorks: it is the
   same component wearing the same band, and renaming it would have made the two
   marketing pages look unrelated in a stylesheet where they are not. */
.landing-arc { margin: 26px 0 0; }
.landing-step { display: flex; gap: 14px; position: relative; padding-bottom: 20px; }
.landing-step:last-child { padding-bottom: 0; }
/* The rail runs from under one dot to the next, so it is drawn per step rather
   than as one absolute line — the last step simply omits it. */
.landing-step::before {
    content: ""; position: absolute; left: 15px; top: 34px; bottom: 0;
    width: 2px; background: var(--track);
}
.landing-step:last-child::before { display: none; }
.landing-dot {
    flex: 0 0 32px; width: 32px; height: 32px; border-radius: 50%;
    display: grid; place-items: center; font-size: 15px;
    background: var(--surface); border: 1.5px solid var(--border);
    color: var(--accent); position: relative; z-index: 1;
}
/* --grad-primary, not --teal-500: the gradient is restated per theme, and a
   flat brand teal under a white glyph goes muddy on the dark ground. */
.landing-step.filled .landing-dot { background: var(--grad-primary); border-color: transparent; color: #fff; }
.landing-step.gold .landing-dot {
    background: var(--grad-gold); border-color: transparent; color: #3a2a00;
    box-shadow: 0 4px 12px rgba(224,152,47,.3);
}
.landing-step .k { font-size: .68rem; font-weight: 800; letter-spacing: 1px; text-transform: uppercase; color: var(--text-muted); }
.landing-step .t { font-size: .95rem; font-weight: 700; margin: 1px 0 2px; }
.landing-step .d { font-size: .8rem; color: var(--text-muted); line-height: 1.45; }

.landing-actions { margin-top: 26px; }
/* The route to the arc, which used to be the second half of this page. It is
   the answer to "what am I signing up for", so it sits under the CTA rather
   than beside the log-in line, where it would read as account housekeeping. */
.landing-alt { margin-top: 10px; }
.landing-login { text-align: center; font-size: .85rem; color: var(--text-muted); margin: 14px 0 0; }

/* --- The trophy (phone) ---
   A right float rather than a block of its own, so the eyebrow and the first
   headline lines set beside it and the sub-copy below reclaims the full column
   once the float clears. The width is what makes that work: the column is
   339px at a 375px viewport and "Take control" measures 216px, so the float
   plus its gutter has to stay under ~120px.

   The top margin drops it clear of the eyebrow chip so it centres on the first
   headline line rather than on the chip row — and no further: the float has to
   end above "Keep the victory." (line 3, top ≈208px at 375) or that line
   shortens too and wraps. 20px leaves ~8px. */
.landing-art { float: right; margin: 20px 0 6px 12px; }
.landing-halo {
    width: clamp(76px, 25vw, 104px); height: clamp(76px, 25vw, 104px);
    border-radius: 50%; display: grid; place-items: center;
    font-size: clamp(36px, 11vw, 46px); color: var(--gold-light);
    /* The band's own gradient, so the trophy reads as a badge lifted off the
       page rather than a gold outline sitting on cream. */
    background: var(--grad-hero);
    border: 1.5px solid rgba(232,176,75,.42);
    box-shadow: 0 8px 20px rgba(7,37,48,.22);
}
/* Under ~360px the arithmetic above stops working — no trophy small enough to
   be worth drawing leaves room for the headline on one line, and "Take /
   control" broken across two is a worse trade than no trophy. */
@media (max-width: 359.98px) { .landing-art { display: none; } }

/* --- The three tiles ---
   Stacked on the phone, three across on the desktop. They used to be
   desktop-only because the arc was already carrying the phone page; with the
   arc gone there is room for them, and they are the only thing on the phone
   that says what the program actually is. */
.landing-cards { display: grid; gap: 12px; margin-top: 26px; }
/* An <a>, so the whole tile is the target rather than a "learn more" under it.
   color: inherit is what keeps the heading and the sub-line reading as a card
   instead of as two links stacked. */
.landing-card {
    background: var(--surface); border: 1px solid var(--border); border-radius: 16px;
    padding: 15px 16px; box-shadow: var(--card-shadow);
    display: flex; gap: 12px; align-items: flex-start;
    color: inherit; text-decoration: none;
    transition: transform .12s ease, border-color .2s ease, box-shadow .2s ease;
}
.landing-card:hover {
    text-decoration: none; border-color: var(--teal-400); transform: translateY(-2px);
}
.landing-card:active { transform: none; }
.landing-card-ico { font-size: 20px; color: var(--accent); margin-top: 1px; }
.landing-card b { display: block; font-size: .9rem; font-weight: 700; }
.landing-card span { font-size: .78rem; color: var(--text-muted); line-height: 1.4; }

.landing-below { padding: 0 18px 20px; }
/* The disclaimer used to be an .alert-info block — visually the second-loudest
   thing on the page, competing with the CTA. It is a footnote. */
.landing-fine {
    margin: 24px 2px 0; padding-left: 12px; border-left: 2px solid var(--border);
    font-size: .74rem; line-height: 1.5; color: var(--text-muted);
}
.landing-fine strong { color: var(--text); font-weight: 700; }

/* 768px, the same breakpoint the rest of the app uses to swap the bottom nav for
   the sidebar rail — so the phone header below and the desktop band here meet
   exactly, with no width where the page has neither. */
@media (min-width: 768px) {
    .app-shell.marketing { max-width: none; box-shadow: none; }

    .landing-band { background: var(--grad-hero); color: #fff; padding: 4px clamp(20px, 4vw, 40px) 56px; }
    .landing-band .topbar { max-width: 1080px; margin: 0 auto; padding: 18px 0 6px; }
    /* _AppHeader emits an empty span in the back-button slot to hold the brand
       centred on a phone. Dropping it here left-aligns the brand on the band. */
    .landing-band .topbar > span:empty { display: none; }
    /* .brand-teal sets the colour on the inner span, so colouring .brand alone
       leaves the wordmark dark teal on a dark teal band — invisible. */
    .landing-band .brand, .landing-band .brand .brand-teal { color: #fff; }
    .landing-band .brand .tm { color: rgba(255,255,255,.5); }
    .landing-band .brand .brand-mark { color: var(--gold-light); }
    .landing-band .theme-toggle {
        background: rgba(255,255,255,.12); border-color: rgba(255,255,255,.2); color: #fff;
    }

    .landing-hero {
        max-width: 1080px; margin: 0 auto; padding: 34px 0 0;
        display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, .75fr);
        gap: clamp(26px, 4.5vw, 56px); align-items: center;
    }
    /* Scoped to the hero: the same chip is the head of /Home/HowItWorks, where
       it is the only thing naming the length of the program and has to show. */
    .landing-hero .landing-eyebrow { display: none; }

    /* Scales down rather than orphaning "battle." onto its own line between 900
       and ~1200px, where the copy column is at its narrowest. */
    .landing-title {
        font-size: clamp(2.2rem, 3.3vw, 3rem); line-height: 1.08;
        letter-spacing: -1.8px; margin: 0 0 16px; color: #fff;
    }
    .landing-title em { color: var(--gold-light); }
    .landing-sub { font-size: 1.05rem; color: #a9cdd8; max-width: 44ch; }

    .landing-actions { display: flex; align-items: center; gap: 18px; margin-top: 28px; }
    .landing-actions .btn { width: auto; padding: 15px 30px; }
    /* Gold, not the teal --grad-primary: a teal button on the teal band has
       nowhere to stand, and trophy-gold is what the headline is about. */
    .landing-cta { background: var(--grad-gold); color: #3a2a00; box-shadow: 0 10px 24px rgba(224,152,47,.34); }
    /* .btn-outline's --teal-400 border and --accent ink are both teal, and this
       row sits on the teal band — white at two opacities is the only pair that
       reads here, the same treatment .landing-band gives the theme toggle. */
    .landing-alt {
        margin-top: 0; border-color: rgba(255,255,255,.34); color: #fff;
    }
    .landing-login { margin: 0; text-align: left; color: #8fb6c3; }
    .landing-login a { color: #fff; font-weight: 700; text-decoration: underline; text-underline-offset: 3px; }

    /* order: 2 puts it back on the right of the grid — it leads the DOM only so
       the phone float has line boxes after it to wrap. */
    .landing-art { float: none; order: 2; margin: 0; display: grid; place-items: center; }
    .landing-halo {
        width: clamp(168px, 22vw, 230px); height: clamp(168px, 22vw, 230px);
        font-size: clamp(72px, 9.5vw, 100px); color: var(--gold-light);
        /* The band here is already --grad-hero, so the phone's teal fill would
           vanish into it — back to the gold wash that reads against it. */
        background: radial-gradient(circle at 50% 45%, rgba(232,176,75,.30) 0%, rgba(232,176,75,.09) 46%, transparent 70%);
        box-shadow: none;
    }

    .landing-below { padding: 26px clamp(20px, 4vw, 40px) 30px; }
    .landing-cards {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 16px; max-width: 1080px; margin: 0 auto;
    }
    .landing-card { padding: 18px 20px; gap: 13px; }
    .landing-card-ico { font-size: 21px; }
    .landing-card b { font-size: .92rem; }
    .landing-card span { font-size: .79rem; }

    .landing-fine, .landing-foot { max-width: 1080px; margin-left: auto; margin-right: auto; }
    .landing-fine { margin-top: 24px; }
}

/* ==========================================================================
   How it works — the 12-month arc, on a page of its own.

   Nothing here restyles the arc: .landing-arc / .landing-step / .landing-dot
   are reused verbatim, which is the point of having moved the markup rather
   than rewritten it. What this section adds is the head band above it and, at
   768px+, the column that keeps the rail readable — a four-step vertical
   timeline stretched across 1080px is a list with a lot of whitespace in it.

   The head is .landing-band, so it inherits the desktop gradient, the white
   wordmark and the toggle treatment from the landing rules above and the two
   marketing pages cannot drift apart at the top.
   ========================================================================== */
.how-head { padding: 16px 18px 4px; }
.how-title {
    font-size: 1.9rem; line-height: 1.14; font-weight: 800;
    letter-spacing: -1px; margin: 14px 0 10px;
}
.how-sub { font-size: .95rem; color: var(--text-muted); line-height: 1.55; margin: 0; }
.how-body { padding: 24px 18px 20px; }
/* The arc's own top margin exists for the hero it used to sit under. */
.how-body .landing-arc { margin-top: 0; }
.how-actions { margin-top: 30px; }

@media (min-width: 768px) {
    /* 720 and the same 20px gutter as .how-body, not the landing's 1080: the
       head and the rail below it have to share a left edge, or the headline
       starts 200px outside the sequence it introduces. */
    .how-head {
        max-width: 720px; margin: 0 auto; padding: 30px 20px 6px;
    }
    .how-title {
        font-size: clamp(2.1rem, 3vw, 2.7rem); letter-spacing: -1.6px;
        margin: 16px 0 12px; color: #fff;
    }
    .how-sub { font-size: 1.05rem; color: #a9cdd8; max-width: 52ch; }
    /* The eyebrow's #8a6413 is chosen for cream; here the chip sits on the teal
       band, where dark gold on a 16%-gold fill is barely a shade apart. Four
       classes because the base rule is three. */
    .how-head .chip.gold.landing-eyebrow {
        background: rgba(255,255,255,.12); color: var(--gold-light);
    }

    /* 720, not the 1080 the landing uses: the rail is one column of text and a
       32px dot, and the measure is what makes it read as a sequence. */
    .how-body { max-width: 720px; margin: 0 auto; padding: 34px 20px 34px; }
    .how-body .landing-step { padding-bottom: 26px; }
    .how-body .landing-step .t { font-size: 1.05rem; }
    .how-body .landing-step .d { font-size: .87rem; }
    /* The CTA here is on --bg rather than the teal band, so the gold fill the
       landing gives it has no band to stand against — back to the brand teal. */
    .how-actions { display: flex; align-items: center; gap: 18px; margin-top: 34px; }
    .how-actions .btn { width: auto; padding: 15px 30px; }
    .how-actions .landing-cta { background: var(--grad-primary); color: #fff; box-shadow: 0 8px 20px rgba(18, 109, 134, .32); }
    .how-actions .landing-login { color: var(--text-muted); }
    .how-actions .landing-login a { color: var(--accent); font-weight: 700; }
}

/* Photographs on the three landing-tile pages. Same radius, border, shadow
   and 16px stack gap as .card, so they sit in the column as the same kind
   of object the copy already is — not a new surface. */
.how-figure {
    margin: 0 0 16px;
    border-radius: 20px;
    overflow: hidden;
    box-shadow: var(--card-shadow);
    border: 1px solid var(--border);
    background: var(--surface-2);
}
.how-figure img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 9;
    object-fit: cover;
}

/* ==========================================================================
   Teal header (phone) — the top half of the app frame.

   The bottom nav has always sat dark teal in both themes (--nav-bg), while the
   top bar was just page ground with a wordmark on it. Bracketing the scroller
   between two teal bars is what makes the phone layout read as an app rather
   than a document with a title above it, and it is the same band the landing
   page wears on desktop, so the front door and the signed-in product agree.

   Phone only, and 768px is not an arbitrary number: it is exactly where the
   bottom nav is replaced by the sidebar rail. Above it there is no second bar
   for a header to pair with, and a teal strip running alongside a light rail
   would read as a mistake rather than a frame.

   Every .topbar is covered, not just the ones with nav — a member arriving from
   the landing page through login and onboarding should not watch the header
   change colour twice on the way in.
   ========================================================================== */
@media (max-width: 767.98px) {
    .topbar {
        background: var(--grad-hero);
        color: #fff;
        /* The bar is now a filled surface, so it has to own the status bar
           inset the way .bottom-nav already owns the home-indicator one —
           otherwise the notch shows --bg above a teal header. */
        padding: calc(16px + env(safe-area-inset-top)) 18px 14px;
    }
    /* .brand-teal colours the inner span, so the parent alone is not enough. */
    .topbar .brand, .topbar .brand .brand-teal { color: #fff; }
    .topbar .brand .tm { color: rgba(255,255,255,.55); }
    /* --gold is barely legible on the teal band; --gold-light is what the rest
       of the band already uses. */
    .topbar .brand .brand-mark { color: var(--gold-light); }
    .topbar .ob-step { color: rgba(255,255,255,.72); }

    /* Every control in a topbar — the theme toggle, the back chevron, logout —
       carries .theme-toggle, whose chip-grey fill and dark ink both vanish here. */
    .topbar .theme-toggle {
        background: rgba(255,255,255,.14);
        border-color: rgba(255,255,255,.22);
        color: #fff;
    }
    /* The dashboard's Admin chip is the one other thing that appears up here. */
    .topbar .chip {
        background: rgba(255,255,255,.14);
        border-color: rgba(255,255,255,.22);
        color: #fff;
    }
}

/* ==========================================================================
   Teal chrome (desktop) — the same frame, folded around the corner.

   On a phone the frame is a teal header over a teal footer. Above 768px there
   is no footer — the bottom nav is replaced by the sidebar rail — so the frame
   becomes an L: the rail down the left, the top bar across the content pane,
   and the warm scroller sitting inside it.

   Both surfaces paint --grad-hero with background-attachment: fixed, which is
   what makes the corner seamless. Painted normally, each element resolves the
   gradient against its own box — a tall narrow rail and a short wide bar land
   on completely different points of the ramp and meet in a visible seam.
   Fixed anchors both to the viewport, so they sample one gradient.

   The rail's ink is white at three opacities rather than the light-mode tokens
   it used to carry, for the same reason .bottom-nav hardcodes its own: the band
   is dark teal in both themes, so ink that flips with the theme would be wrong
   in one of them.
   ========================================================================== */
@media (min-width: 768px) {
    .app-shell.has-nav .side-nav,
    .app-shell.has-nav .topbar {
        background: var(--grad-hero);
        background-attachment: fixed;
        color: #fff;
    }
    /* The rail and the bar are now one surface; a rule between them would draw
       a line through the corner. --bg against the band is the separation. */
    .app-shell.has-nav .side-nav { border-right: none; }
    /* A filled bar needs even weight top and bottom — 6px underneath read as a
       gradient strip that had been cropped. */
    .app-shell.has-nav .topbar { padding: 16px 28px 16px; }

    .side-nav .side-brand, .side-nav .side-brand .brand-teal { color: #fff; }
    .side-nav .side-brand .tm { color: rgba(255,255,255,.5); }

    .side-nav .navmenu a, .side-nav .navmenu summary, .side-nav .navmenu button { color: rgba(255,255,255,.74); }
    .side-nav .navmenu a:hover, .side-nav .navmenu summary:hover, .side-nav .navmenu button:hover {
        background: rgba(255,255,255,.10); color: #fff;
    }
    /* --border against the teal band would draw a light line across the rail. */
    .side-nav .nav-foot { border-top-color: rgba(255,255,255,.18); }
    /* The dark-theme active colour is set at (0,4,1); these have to outrank it,
       hence the repeat under :root[data-theme="dark"]. */
    .side-nav .navmenu a.active, .side-nav .navmenu summary.active,
    :root[data-theme="dark"] .side-nav .navmenu a.active,
    :root[data-theme="dark"] .side-nav .navmenu summary.active {
        background: rgba(255,255,255,.16); color: #fff;
    }
    .side-nav .navmenu .nav-caret { color: rgba(255,255,255,.55); }

    .app-shell.has-nav .topbar .theme-toggle,
    .app-shell.has-nav .topbar .chip {
        background: rgba(255,255,255,.14);
        border-color: rgba(255,255,255,.22);
        color: #fff;
    }
}

/* ==========================================================================
   Print / PDF — the Progress screen has an explicit "export report" button,
   and the app frame is a fixed-height overflow:hidden column, so without this
   the printout is whatever fitted on one screen. Unwind the frame, drop the
   chrome, and force light tokens (dark theme prints white-on-white otherwise).
   ========================================================================== */
@media print {
    :root, :root[data-theme="dark"] {
        color-scheme: light;
        --bg: #fff; --bg-2: #fff; --surface: #fff; --surface-2: #fff;
        --text: #000; --text-muted: #444; --border: #ccc; --track: #ddd;
        --chip-bg: #f0f0f0; --card-shadow: none;
        /* The accent and status pairs swap for dark too, so they need unwinding
           here for the same reason the surfaces do — the dark ones are light inks. */
        --accent: #126d86; --teal-100: #eef4f6;
        /* The dark theme restates both gradients against its own ground, so they
           need unwinding here too or the hero card prints in its dark values. */
        --grad-hero: linear-gradient(160deg, #126d86 0%, #072530 100%);
        --grad-primary: linear-gradient(135deg, #147a9c 0%, #0f4a5a 100%);
        /* Flat, or every page prints a grey wash across its whole ground. */
        --grad-ground: #fff;
        --green-soft: #eaf7f0; --green-ink: #0b5c37;
        --warn-soft: #fbf0e2; --warn-ink: #7a4408;
    }
    html, body { background: #fff; }
    .app-shell, .app-shell.has-nav {
        display: block; height: auto; min-height: 0; max-width: none;
        overflow: visible; box-shadow: none; padding-bottom: 0;
    }
    .app-shell.has-nav .app-content { display: block; overflow: visible; }
    .app-shell.has-nav .app-main,
    .app-shell.has-nav .app-main:not(.flow-single) {
        overflow: visible; max-width: none; columns: auto; padding: 0;
    }
    .side-nav, .bottom-nav, .nav-drawer, .nav-drawer-overlay,
    .theme-toggle, .topbar button, .btn { display: none !important; }
    .card, .how-figure { break-inside: avoid; box-shadow: none; border: 1px solid #ccc; }
    a { color: #000; text-decoration: none; }

    /* Hero cards and the trophy paint white text onto a gradient. Browsers drop
       background graphics by default, so left alone they print white-on-white —
       and the text colors are inline, hence !important. */
    .card-hero, .trophy-badge { background: none !important; border: 1px solid #ccc; }
    .card-hero, .card-hero *, .trophy-badge, .trophy-badge * { color: #000 !important; }
    /* The landing band is the same trap at page scale — white type on a gradient
       the browser drops. No border: it is the page, not a card. */
    .landing-band, .landing-halo { background: none !important; border: none; }
    .landing-band, .landing-band * { color: #000 !important; }
    .pill-phase { background: #eee !important; }
    .progress { border: 1px solid #ccc; }
    .progress > span, .progress.gold > span { background: #777 !important; }
}

/* ==== Phase 1: care ==== */
/* Care team (CARE-04/05/06): the member's Care team pages, the Today card and the staff console.
   Everything else on those pages reuses .card, .chat-log/.bubble, .alert, .badge (admin.css) and
   .metric-grid/.stat; these rules only cover what those do not. */

/* Screen-reader-only text, for table captions and the "Open <name>" buttons in the queue. */
.care-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;
}

/* Skip link for the console: visible only when focused (WCAG 2.4.1). */
.care-skip { position: absolute; left: -9999px; top: 8px; z-index: 200; }
.care-skip:focus {
    left: 12px; background: var(--surface); color: var(--text); padding: 8px 12px;
    border-radius: 10px; border: 2px solid var(--teal-500);
}

/* Page title inside a .topbar — an <h1> for the document outline, sized like the existing title text. */
.care-title { font-size: 1.1rem; margin: 0; line-height: 1.2; }

/* The clinical-boundary line at the top of every console page. */
.care-boundary {
    display: flex; gap: 10px; align-items: flex-start; margin: 0 0 16px;
    padding: 10px 14px; border-radius: 12px; font-size: .84rem;
    background: var(--teal-100); color: var(--teal-700);
}
.care-boundary .icon { flex: 0 0 auto; margin-top: 2px; }
:root[data-theme="dark"] .care-boundary { color: var(--teal-300); }

/* Message and note bodies keep the author's line breaks and never overflow a narrow screen. */
.care-pre { white-space: pre-wrap; overflow-wrap: anywhere; }
.care-bubble { max-width: 88%; }
.care-meta { display: block; }
.bubble.ai .care-meta { color: var(--text-muted); }
.bubble.me .care-meta { color: #fff; }

/* Snapshot figures are sentences, not single numbers, so they run smaller than a .stat .val. */
.stat .val.care-val { font-size: 1rem; line-height: 1.3; margin: 2px 0; }

.care-suggest { border-left: 4px solid var(--teal-500); }

/* Plan summary on the member's Care team page. */
.care-plans { display: grid; grid-template-columns: max-content 1fr; gap: 6px 12px; margin: 0; }
.care-plans dt { font-weight: 700; }
.care-plans dd { margin: 0; }

/* Inline selects in the assignments table. */
.care-select-sm {
    padding: 7px 10px; border-radius: 10px; border: 1.5px solid var(--border);
    background: var(--surface-2); color: var(--text); font-size: .85rem; max-width: 220px;
}
.care-linkbtn { background: none; border: 0; padding: 0; cursor: pointer; text-decoration: underline; }

/* The Today card sits in the flow rather than overlapping the hero. */
.care-today { margin-top: 12px; }

@media (pointer: coarse) {
    .care-select-sm { font-size: 16px; min-height: 44px; }
    .care-linkbtn { min-height: 24px; }
}
/* ==== end care ==== */
/* ==== Phase 1: billing ==== */
/* Plans page, the member's plan page, the upgrade prompt, the Today payment notice and the
   Admin → Billing row form. Built on .card, .chip, .segment, .btn and .upnext; what is here is
   only the layout those do not already give. */

/* The monthly/yearly toggle. Two links, so it works before any script runs. */
.plans-toggle { margin: 4px 0 16px; }
.plans-save {
    display: inline-block; margin-left: 6px; font-size: .7rem; font-weight: 700;
    color: var(--green-ink); text-transform: none;
}

/* auto-fit rather than a fixed three: the same grid sits in a 460px phone column, beside the
   desktop sidebar and on the wide marketing page, and 210px is the narrowest a card's feature
   list stays readable at. */
.plan-grid {
    display: grid; gap: 16px; margin-bottom: 16px;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}
.plan-card {
    margin: 0; display: flex; flex-direction: column;
    border: 1.5px solid var(--border);
}
.plan-card.is-current { border-color: var(--teal-400); }
.plan-card.is-selected { border-color: var(--gold); box-shadow: 0 0 0 3px rgba(232,176,75,.22); }

.plan-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.plan-name { font-size: 1.3rem; font-weight: 800; letter-spacing: -.3px; margin: 0; }
.plan-tagline { margin: 4px 0 12px; }
.plan-price { display: flex; align-items: baseline; gap: 2px; }
.plan-amount { font-size: 2rem; font-weight: 800; letter-spacing: -1px; line-height: 1.1; }
.plan-per { font-size: .9rem; font-weight: 600; color: var(--text-muted); }
.plan-inherits { margin: 14px 0 6px; }

.plan-features { margin: 8px 0 0; }
.plan-features li { display: flex; gap: 8px; align-items: flex-start; font-size: .86rem; padding: 4px 0; }
.plan-tick { display: flex; flex: 0 0 auto; color: var(--green-ink); padding-top: 2px; }
.plan-tick .icon { width: 14px; height: 14px; stroke-width: 2.6; }

/* The button sits at the foot of every card so the three line up however long each list is. */
.plan-action { margin-top: auto; padding-top: 16px; }
.plan-register { margin: 8px 0 0; }

.plan-always .card-title { display: flex; align-items: center; gap: 8px; }
.plan-always .card-title .icon { color: var(--accent); }
.plans-terms { margin: 4px 0 16px; line-height: 1.5; }

/* The member's own plan page. */
.plan-current .plan-name { font-size: 1.6rem; }
.plan-buttons { display: grid; gap: 10px; margin-top: 18px; }
.plan-buttons form { margin: 0; }
.plan-success-mark { color: var(--green); margin: 4px 0 8px; }
.plan-success-mark .icon { width: 44px; height: 44px; }

/* On the public page the head band is 720px; the grid gets the same measure so the headline and
   the first card share a left edge, as .how-body does for the arc. */
@media (min-width: 768px) {
    .plans-body .plan-grid { gap: 18px; }
}

/* _UpgradePrompt — an invitation, not a wall: a quiet dashed card, never a modal. */
.upgrade-prompt { border: 1.5px dashed var(--teal-300); }
.upgrade-prompt-head { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.upgrade-prompt-ico {
    width: 32px; height: 32px; border-radius: 50%; background: var(--teal-100); color: var(--accent);
    display: grid; place-items: center; flex: 0 0 auto;
}
.upgrade-prompt-ico .icon { width: 16px; height: 16px; }
.upgrade-prompt-reason { margin: 0 0 12px; }

/* Today's payment notice: the Up next card's layout, with a warning-toned icon. */
.billing-notice { margin-top: 14px; }
.billing-notice-ico {
    width: 40px; height: 40px; border-radius: 50%; background: var(--warn-soft); color: var(--warn-ink);
    display: grid; place-items: center; flex: 0 0 auto;
}
.billing-notice-ico .icon { width: 18px; height: 18px; }

/* Admin → Billing: the per-row "Set tier" form lives in a <details>, so it needs no script. */
.billing-set summary { list-style: none; cursor: pointer; }
.billing-set summary::-webkit-details-marker { display: none; }
.billing-set[open] summary { margin-bottom: 4px; }
.billing-set .field select, .billing-set .field input { min-width: 200px; }
/* ==== end billing ==== */
/* ==== Phase 1: launch ==== */
/* Email preferences (COM-04), Admin → Outcomes (PLT-10), evidence labels (EDU-04). */

/* Visually hidden but announced — the chip's "Evidence level:" prefix and similar context
   that a sighted reader gets from layout. */
.launch-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;
}

/* EDU-04 evidence chips. Colour is never the only signal: the label is always written out.
   Inks are darkened from the stock .chip.green so small bold text clears 4.5:1 on its tint. */
.evidence-chip {
    display: inline-flex; align-items: center; gap: 5px;
    border-radius: 999px; padding: 2px 9px; border: 1px solid transparent;
    font-size: .7rem; font-weight: 700; letter-spacing: .2px; line-height: 1.5;
    vertical-align: middle; white-space: nowrap; text-decoration: none;
}
.evidence-chip::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }
a.evidence-chip:hover { text-decoration: underline; }
a.evidence-chip:focus-visible { outline: 2px solid var(--teal-400); outline-offset: 2px; }
.tiny .evidence-chip { margin-left: 4px; }
.evidence-chip.ev-established  { background: #d8f6e7; color: #0b6b3f; border-color: rgba(11,107,63,.25); }
.evidence-chip.ev-promising    { background: #e3f0f4; color: #0f4a5a; border-color: rgba(15,74,90,.2); }
.evidence-chip.ev-experimental { background: #fdf0e2; color: #8a4b06; border-color: rgba(138,75,6,.25); }
:root[data-theme="dark"] .evidence-chip.ev-established  { background: rgba(34,192,123,.16); color: #8ee8bb; border-color: rgba(142,232,187,.3); }
:root[data-theme="dark"] .evidence-chip.ev-promising    { background: rgba(17,143,189,.18); color: #9ad2d0; border-color: rgba(154,210,208,.3); }
:root[data-theme="dark"] .evidence-chip.ev-experimental { background: rgba(245,158,66,.16); color: #f5c27a; border-color: rgba(245,194,122,.3); }
.evidence-explainer { scroll-margin-top: 84px; }
.evidence-explainer:target { box-shadow: 0 0 0 2px var(--teal-400); }

/* COM-04 email preferences. */
.launch-list { margin: 0; padding-left: 18px; }
.launch-list li { margin-bottom: 8px; line-height: 1.5; }

/* PLT-10 Admin → Outcomes. Numbers right-aligned in tabular figures so columns compare. */
.outcome-table th[scope="row"] { text-align: left; font-weight: 600; }
.outcome-table .num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.outcome-suppressed, .outcome-pending { font-size: .78rem; font-style: italic; color: var(--text-muted); }
@media print {
    .evidence-chip { border-color: #999 !important; background: #fff !important; color: #000 !important; }
}
/* ==== end launch ==== */
/* ==== Phase 1: checkin ==== */
/* Daily check-in (APP-02/03/04) and the fiber/water target bars (NUT-06).
   Every colour is a token, so both themes are handled where the tokens are.
   Selected states use --teal-600 under white text in both themes (~7:1), not
   --grad-primary, whose dark-theme light end is under 4.5:1 for 13px text —
   and a selected chip is also bolder, so the state never rests on colour alone. */

.ci-visually-hidden {
    position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* --- The Today card --- */
.ci-card h2 { margin: 0; }
.ci-lede { margin: 2px 0 10px; font-size: 14.5px; font-weight: 800; }
.ci-hint { display: block; font-size: 12px; font-weight: 400; color: var(--text-muted); margin-top: 2px; }
.ci-q { margin-top: 12px; }
.ci-q-label { font-size: 12px; font-weight: 700; color: var(--text-muted); margin-bottom: 6px; padding: 0; }
.ci-note { font-size: .72rem; color: var(--text-muted); margin: 6px 0 0; }

/* minmax(0,…) for the reason .stat-grid gives: five chips on a 320px phone must
   shrink rather than push the card wide. */
.ci-chips { display: grid; gap: 6px; }
.ci-chips-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.ci-chips-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.ci-chip {
    min-height: 40px; padding: 6px 4px; border-radius: 12px;
    border: 1px solid var(--border); background: var(--surface-2); color: var(--text);
    font: inherit; font-size: .76rem; font-weight: 600; line-height: 1.15;
    cursor: pointer; overflow-wrap: anywhere; text-align: center;
    transition: background .15s ease, transform .06s ease;
}
.ci-chip:hover { border-color: var(--teal-400); }
.ci-chip:active { transform: scale(.97); }
.ci-chip[aria-pressed="true"] {
    background: var(--teal-600); border-color: var(--teal-600); color: #fff; font-weight: 800;
}
.ci-chip:focus-visible, .ci-step:focus-visible, .ci-clear:focus-visible,
.ci-day:focus-visible, .ci-table-scroll:focus-visible, .ci-details summary:focus-visible {
    outline: 2px solid var(--accent); outline-offset: 2px;
}
/* A tap in flight: dimmed, not hidden, so a slow network never looks like a lost tap. */
.ci-chip.is-saving, .ci-step.is-saving { opacity: .6; }
[data-ci-body][aria-busy="true"] { cursor: progress; }

.ci-stepper { display: flex; align-items: center; gap: 8px; }
.ci-step {
    width: 40px; height: 40px; flex: 0 0 auto; border-radius: 12px;
    border: 1px solid var(--border); background: var(--surface-2); color: var(--text);
    font: inherit; font-size: 1.15rem; font-weight: 700; line-height: 1; cursor: pointer;
}
.ci-step:disabled { opacity: .4; cursor: default; }
.ci-step-val { min-width: 4.5em; text-align: center; font-size: 1rem; font-weight: 800; }
.ci-stepper .ci-step-log { flex: 0 1 auto; min-width: 6em; padding: 6px 12px; }
.ci-clear {
    margin-left: auto; background: none; border: 0; padding: 8px 4px; cursor: pointer;
    font: inherit; font-size: .76rem; font-weight: 700; color: var(--accent);
}

/* --- /CheckIn: day picker --- */
.ci-days { display: flex; gap: 6px; overflow-x: auto; padding: 2px 2px 10px; margin-bottom: 6px; }
.ci-day {
    flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px;
    padding: 8px 12px; border-radius: 999px; border: 1px solid var(--border);
    background: var(--surface); color: var(--text); font-size: .78rem; font-weight: 600;
    text-decoration: none; white-space: nowrap;
}
.ci-day:hover { text-decoration: none; border-color: var(--teal-400); }
.ci-day.is-selected { background: var(--teal-600); border-color: var(--teal-600); color: #fff; font-weight: 800; }
/* Filled when answered, hollow when not: a shape difference as well as a colour one. */
.ci-day-mark { width: 7px; height: 7px; border-radius: 50%; border: 1.5px solid currentColor; opacity: .6; }
.ci-day-mark.is-answered { background: currentColor; opacity: 1; }

/* --- /CheckIn: the full form, as real radio inputs --- */
.ci-fieldset { border: 0; margin: 0 0 14px; padding: 0; min-width: 0; }
.ci-radios { display: grid; grid-template-columns: repeat(auto-fit, minmax(52px, 1fr)); gap: 6px; }
.ci-radio { position: relative; display: block; margin: 0; }
.ci-radio input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; }
.ci-radio span {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    min-height: 44px; padding: 6px 4px; border-radius: 12px; text-align: center;
    border: 1px solid var(--border); background: var(--surface-2); color: var(--text);
    font-size: .76rem; font-weight: 600; line-height: 1.15; cursor: pointer; overflow-wrap: anywhere;
}
.ci-radio small { font-size: .66rem; font-weight: 600; opacity: .75; }
.ci-radio-skip span { color: var(--text-muted); border-style: dashed; }
.ci-radio input:checked + span { background: var(--teal-600); border-color: var(--teal-600); color: #fff; font-weight: 800; }
.ci-radio input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }

/* --- /CheckIn: trends --- */
.ci-trend { padding: 10px 0 12px; border-bottom: 1px solid var(--border); }
.ci-trend:last-of-type { border-bottom: 0; }
.ci-trend-title { margin: 0; font-size: .86rem; font-weight: 700; }
.ci-spark-row { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 8px; margin-top: 6px; }
.ci-axis {
    display: flex; flex-direction: column; justify-content: space-between;
    min-width: 3.8em; text-align: right; font-size: .64rem; color: var(--text-muted); line-height: 1.1;
}
.ci-spark { display: block; width: 100%; height: auto; overflow: visible; }
.ci-spark-guide { stroke: var(--border); stroke-width: 1; stroke-dasharray: 3 3; vector-effect: non-scaling-stroke; }
.ci-spark-line {
    fill: none; stroke: var(--accent); stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke;
}
.ci-spark-dot { fill: var(--accent); }
.ci-spark-last { fill: var(--accent); stroke: var(--surface); stroke-width: 2; }
.ci-spark-dates { display: flex; justify-content: space-between; font-size: .64rem; color: var(--text-muted); margin: 2px 0 0 calc(3.8em + 8px); }

.ci-details { margin-top: 12px; }
.ci-details summary { cursor: pointer; font-size: .82rem; font-weight: 700; color: var(--accent); padding: 6px 0; }
.ci-table-scroll { overflow-x: auto; margin-top: 8px; border-radius: 10px; }
.ci-table { width: 100%; border-collapse: collapse; font-size: .74rem; }
.ci-table caption { text-align: left; font-size: .72rem; color: var(--text-muted); padding-bottom: 6px; }
.ci-table th, .ci-table td { padding: 6px 8px; border-bottom: 1px solid var(--border); text-align: left; white-space: nowrap; }
.ci-table thead th { color: var(--text-muted); font-weight: 700; }
.ci-table tbody th { font-weight: 700; }

/* --- Food page: fiber and water progress (NUT-06) ---
   .dim-bar's own track is --surface-2, which is also the .stat tile's ground, so
   inside a tile the track would vanish and only the fill would show. */
.dim-bar.ci-target-bar { background: var(--track); margin: 8px 0 0; }

@media (pointer: coarse) {
    .ci-chip, .ci-step { min-height: 44px; }
    .ci-step { width: 44px; height: 44px; }
    .ci-day { min-height: 44px; }
}
@media (prefers-reduced-motion: reduce) {
    .ci-chip { transition: none; }
    .ci-chip:active { transform: none; }
}
/* ==== end checkin ==== */
/* ==== Phase 1: insight ==== */
/* Grounded coach sources (CARE-02), the weekly review (CARE-03) and the recovery check-in
   (HAB-03). Built on the existing tokens only, so both themes follow without overrides. */

/* Coach: the lessons a reply cited, under the bubble it belongs to. */
.coach-sources { margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--border); font-size: .78rem; }
.coach-sources-head { font-weight: 700; color: var(--text-muted); margin-bottom: 4px; }
.coach-sources ol { margin: 0; padding-left: 1.4em; }
.coach-sources li { margin: 3px 0; }
.coach-sources a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
.coach-sources a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.coach-sources-lock { display: block; color: var(--text-muted); }
.coach-grounding ol { margin: 6px 0 0; padding-left: 1.4em; }
.coach-grounding li { margin-bottom: 6px; }
.coach-grounding summary { cursor: pointer; }

/* Headings that sit where plain text used to, so the page has a real outline without a
   different look. */
.insight-title { margin: 0; font-size: 1.1rem; }
.card-hero .insight-hero-title { color: #fff; margin: 8px 0 6px; font-size: 1.1rem; }
.insight-hero-text { color: rgba(255,255,255,.88); margin-top: 8px; }

/* Weekly review. */
.insight-focus { list-style: none; margin: 0 0 10px; padding: 0; }
.insight-focus li { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--border); }
.insight-focus li:last-child { border-bottom: none; }
.insight-row { margin-bottom: 12px; }
.insight-row .progress { height: 8px; margin-top: 6px; }
.insight-line { padding: 7px 0; border-bottom: 1px solid var(--border); gap: 12px; }
.insight-line:last-child { border-bottom: none; }
.escalate-card.insight-line { border-bottom: none; margin-bottom: 8px; padding-top: 4px; padding-bottom: 4px; }

/* Recovery check-in. */
.insight-fieldset { border: none; margin: 0 0 14px; padding: 0; min-width: 0; }
.insight-fieldset legend { padding: 0; }
.insight-opt-label { display: block; }
.insight-opt-hint { display: block; font-weight: 500; margin-top: 2px; }
.insight .opt:has(input:checked) { border-color: var(--teal-400); background: var(--teal-100); }
.insight .opt:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
.insight-field-label { display: block; font-size: .82rem; font-weight: 600; margin-bottom: 6px; color: var(--text-muted); }
.insight-chip { cursor: pointer; display: inline-flex; align-items: center; gap: 6px; min-height: 44px; }
.insight-chip input { accent-color: var(--teal-500); }
.insight-chip:has(input:checked) { background: var(--teal-100); color: var(--teal-700); }
:root[data-theme="dark"] .insight-chip:has(input:checked) { color: var(--teal-300); }
.insight-chip:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
.insight-quote { font-style: italic; border-left: 3px solid var(--border); padding-left: 10px; }
.insight-card .btn { flex-shrink: 0; }
/* ==== end insight ==== */
/* ==== Phase 1: med ==== */
/* MED-07..MED-10, SYM-03, TRN-07: the medication page additions, the dose timeline, the
   packet builder and the Today "Prepare for my appointment" card. Every colour below is an
   existing token; graphics use tokens that clear 3:1 on the card (WCAG 1.4.11), and text
   inside the chart wears text tokens, never a series colour. */

/* Visually hidden, still read: table captions and fieldset legends the layout already implies. */
.med-sr {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* A whole card as one link — the timeline entry on Medication, the packet link on the
   escalation page. Spans inside an <a> are made block-level where they need a line. */
.med-link-card { color: inherit; text-decoration: none; }
.med-link-card:hover { text-decoration: none; border-color: var(--accent); }
.med-link-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Prescriber, pharmacy and refill, one block per schedule. */
.med-care { padding: 12px 0; border-bottom: 1px solid var(--border); }
.card-title + .med-care { padding-top: 0; }
.med-care-row { display: flex; align-items: center; gap: 12px; padding: 6px 0; }
.med-care-row .win-ico { width: 32px; height: 32px; border-radius: 10px; font-size: .95rem; }
.med-care-row .chip { flex: 0 0 auto; white-space: nowrap; }

/* --- Dose timeline --- */
.med-tl-controls select { width: auto; }
.med-tl-overlays, .med-pk-sections { border: 0; margin: 10px 0 0; padding: 0; min-width: 0; }
.med-tl-overlays { display: flex; flex-wrap: wrap; gap: 6px 14px; }
.med-tl-overlays legend { margin-bottom: 6px; padding: 0; }
.med-tl-overlays label, .med-pk-sections label {
    display: inline-flex; align-items: center; gap: 6px; font-size: .84rem; cursor: pointer;
    min-height: 32px; /* a 24px target at minimum, with room to spare (WCAG 2.5.8) */
}
.med-pk-sections label { display: flex; align-items: flex-start; padding: 4px 0; }
.med-pk-sections input[type="checkbox"] { margin-top: 3px; flex: 0 0 auto; }

.med-tl { display: block; width: 100%; height: auto; max-width: 560px; margin: 0 auto; overflow: visible; }
.med-tl text { font-family: inherit; }
.med-tl-grid { stroke: var(--border); stroke-width: 1; }
.med-tl-base { stroke: var(--track); stroke-width: 1; }
.med-tl-axis, .med-tl-tick { fill: var(--text-muted); font-size: 9px; }
.med-tl-lane { fill: var(--text); font-size: 9.5px; font-weight: 700; }
.med-tl-dose { fill: var(--text); font-size: 9px; font-weight: 700; }
.med-tl-seg { fill: var(--accent); fill-opacity: .16; }
.med-tl-seg.is-oral { fill-opacity: .1; }
.med-tl-segtop { stroke: var(--accent); stroke-width: 2; stroke-linecap: round; }
.med-tl-taken { fill: var(--accent); }
/* A missed dose is a ring on the dose line: present in the record, absent from the body. */
.med-tl-missed { fill: var(--surface); stroke: var(--warn-ink); stroke-width: 2; }
.med-tl-change { stroke: var(--text-muted); stroke-width: 1; stroke-dasharray: 3 3; }
/* A treatment change the member recorded in the Transition Center — a clinician's direction with
   its pathway, the window opening, a restart — drawn through every lane like a dose change but
   solid and in the accent, so the two kinds of line read apart without colour alone. */
.med-tl-treatment { stroke: var(--accent); stroke-width: 1.5; }
.med-tl-treatment-flag { fill: var(--accent); }
.med-tl-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.med-tl-line.is-weight { stroke: var(--accent); }
.med-tl-line.is-appetite { stroke: var(--ring-habits-ink); }
.med-tl-pt { stroke: var(--surface); stroke-width: 1; }
.med-tl-pt.is-weight { fill: var(--accent); }
.med-tl-pt.is-appetite { fill: var(--ring-habits-ink); }
.med-tl-gi { fill: var(--orange); stroke: var(--warn-ink); stroke-width: 1; }
/* Flagged at "contact prescriber" or above: a heavier ring, so the level is readable without hue. */
.med-tl-gi.is-flagged { stroke: var(--red); stroke-width: 2.5; }
.med-tl-bar { fill: var(--ring-care-ink); }
.med-tl-target { stroke: var(--text-muted); stroke-width: 1; stroke-dasharray: 4 3; }
.med-tl-strength { fill: var(--ring-nutrition-c1); }

.med-tl-legend { list-style: none; padding: 0; margin: 10px 0 0; display: flex; flex-wrap: wrap; gap: 6px 14px; color: var(--text-muted); }
.med-tl-legend li { display: inline-flex; align-items: center; gap: 6px; }
.med-tl-legend .k { display: inline-block; width: 12px; height: 12px; flex: 0 0 auto; }
.med-tl-legend .k-seg { background: color-mix(in srgb, var(--accent) 16%, transparent); border-top: 2px solid var(--accent); height: 10px; }
.med-tl-legend .k-taken { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
.med-tl-legend .k-missed { width: 9px; height: 9px; border-radius: 50%; border: 2px solid var(--warn-ink); background: var(--surface); }
.med-tl-legend .k-change { width: 0; height: 12px; border-left: 1px dashed var(--text-muted); }
.med-tl-legend .k-treatment { width: 0; height: 12px; border-left: 2px solid var(--accent); }
/* The coverage-lapse card's collapsed row: a details summary that reads as a card row. */
.med-lapse > summary::-webkit-details-marker { display: none; }
.med-lapse[open] > summary .upnext-chev { transform: rotate(180deg); }
.med-tl-legend .k-flagged { width: 9px; height: 9px; border-radius: 50%; background: var(--orange); border: 2.5px solid var(--red); }

/* Tables that carry the same data as the chart. Scroll inside the card on a phone rather
   than pushing the page sideways. */
.med-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.med-table { width: 100%; border-collapse: collapse; font-size: .8rem; }
.med-table th, .med-table td { text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--border); vertical-align: top; }
.med-table thead th { font-weight: 600; color: var(--text-muted); font-size: .72rem; text-transform: uppercase; letter-spacing: .03em; white-space: nowrap; }
.med-table tbody th { font-weight: 600; white-space: nowrap; }

/* The two scope §9 statements, closing every packet. */
.packet-statement { margin-top: 22px; font-size: .8rem; font-weight: 600; color: var(--text-muted); }
.packet details { margin-top: 8px; }

/* --- Today: "Prepare for my appointment" --- */
.med-prep { display: flex; align-items: center; gap: 14px; color: inherit; text-decoration: none; }
.med-prep:hover { text-decoration: none; }
.med-prep:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.med-prep-ico {
    width: 40px; height: 40px; border-radius: 50%; background: var(--teal-100); color: var(--accent);
    display: grid; place-items: center; flex: 0 0 auto;
}
.med-prep-text { flex: 1; min-width: 0; }
/* Promoted for 14 days after a "contact prescriber" assessment: the escalation card's orange
   rule, so it reads as belonging to that assessment rather than as another nudge. */
.med-prep.is-promoted { border-left: 4px solid var(--orange); }
.med-prep.is-promoted .med-prep-ico { background: var(--warn-soft); color: var(--warn-ink); }

@media print {
    .med-tl-controls, .med-prep { display: none !important; }
    .med-tl-seg { fill-opacity: .25; }
}
/* ==== end med ==== */

/* ==== Journey timeline ====
   The dose timeline's classes for everything it shares; these are the lanes it doesn't have.
   Treatment stretches are shaded faintly behind every lane and drawn solid in their own row, so
   the shading places them and the row names them. */
.jr-shade.is-post { fill: var(--accent); fill-opacity: .07; }
.jr-shade.is-coverage { fill: var(--orange); fill-opacity: .09; }
.jr-span.is-post { fill: var(--accent); }
.jr-span.is-coverage { fill: var(--orange); }
.jr-span.is-recovery { fill: var(--ring-habits-ink); }
.jr-span.is-vacation { fill: var(--text-muted); fill-opacity: .55; }
.jr-mark { stroke: var(--surface); stroke-width: 1; }
.jr-mark.is-stage { fill: var(--accent); }
.jr-mark.is-credential { fill: var(--gold); }
.jr-lab { fill: var(--ring-care-ink); stroke: var(--surface); stroke-width: 1; }
.med-tl-line.is-waist { stroke: var(--ring-nutrition-ink); }
.med-tl-pt.is-waist { fill: var(--ring-nutrition-ink); }
.med-tl-line.is-strength { stroke: var(--green-ink); }
.med-tl-pt.is-strength { fill: var(--green-ink); }
.med-tl-line.is-function { stroke: var(--gold-ink); }
.med-tl-pt.is-function { fill: var(--gold-ink); }
.med-tl-line.is-energy { stroke: var(--ring-care-c1); stroke-width: 1.5; }
.med-tl-pt.is-energy { fill: var(--ring-care-c1); }
.med-tl-legend .k-jr-mark { width: 8px; height: 8px; background: var(--accent); transform: rotate(45deg); }
.med-tl-legend .k-jr-post { height: 7px; border-radius: 2px; background: var(--accent); }
.med-tl-legend .k-jr-coverage { height: 7px; border-radius: 2px; background: var(--orange); }
.med-tl-legend .k-jr-recovery { height: 7px; border-radius: 2px; background: var(--ring-habits-ink); }
.med-tl-legend .k-jr-vacation { height: 7px; border-radius: 2px; background: var(--text-muted); opacity: .55; }
/* ==== end journey ==== */
/* ==== Phase 1: account and trust ==== */
/* Sign-in, recovery, Settings › Security and › Your data (PLT-05, PLT-06, PLT-07, PLT-09), the
   email-confirmation reminder, and Admin › Audit log (PLT-04). Scoped to .acct / .verify-reminder /
   .audit-* so nothing here restyles an existing screen. */

/* A visible focus ring on every control in these flows (WCAG 2.4.7). Scoped rather than global:
   the site-wide pass belongs to the accessibility audit. */
.acct a:focus-visible, .acct button:focus-visible, .acct input:focus-visible, .acct select:focus-visible,
.verify-reminder a:focus-visible, .verify-reminder button:focus-visible,
.audit-filters a:focus-visible, .audit-filters button:focus-visible, .audit-filters input:focus-visible,
.audit-filters select:focus-visible, .audit-pager a:focus-visible {
    outline: 3px solid var(--teal-400); outline-offset: 2px;
}

.acct-topbar-title { font-size: 1.1rem; margin: 0; text-align: center; }

/* "or" rule between the password form and the provider buttons. */
.acct-or { display: flex; align-items: center; gap: 8px; margin: 16px 0 8px; }
.acct-or .divider { margin: 0; }
.acct-providers form { margin: 0 0 8px; }
.acct-providers form:last-child { margin-bottom: 0; }

/* Checkbox with its label to the right, at a 24px target. */
.acct-check { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; }
.acct-check input[type="checkbox"] { width: 20px; height: 20px; margin: 2px; accent-color: var(--teal-500); }

/* One-time codes: large, spaced, tabular so a digit misread is obvious. */
.field input.acct-code { font-size: 1.35rem; letter-spacing: .18em; font-variant-numeric: tabular-nums; text-align: center; }

.acct-glyph { font-size: 2.2rem; color: var(--accent); margin: 4px 0 6px; }
.acct-glyph-ok, .acct-ok { color: var(--green-ink); }
.acct-actions { display: flex; flex-wrap: wrap; gap: 8px; }

/* Authenticator setup. The QR code sits on white in both themes: scanners need the contrast. */
.acct-qr { display: grid; place-items: center; }
.acct-qr img { background: #fff; padding: 10px; border-radius: 12px; border: 1px solid var(--border); max-width: 100%; height: auto; }
.acct-key { margin: 0 0 6px; }
.acct-key code, .acct-codes code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 1rem;
    background: var(--surface-2); border: 1px solid var(--border); border-radius: 8px; padding: 6px 10px;
    display: inline-block; word-break: break-all;
}
.acct-codes {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px;
    margin: 0; padding: 0 0 0 1.4em; font-variant-numeric: tabular-nums;
}
.acct-codes li { padding-left: 2px; }
.acct-list { margin: 0; padding-left: 1.2em; }
.acct-list li { margin-bottom: 6px; }

/* Destructive actions. A darker red than --red so white text clears 4.5:1. */
.acct-danger { background: #b3261e; color: #fff; }
.acct-danger:hover { background: #8f1f18; }
.acct-danger-outline { border-color: #b3261e; color: #b3261e; }
:root[data-theme="dark"] .acct-danger-outline { border-color: #ff98a4; color: #ff98a4; }

/* The "confirm your email" reminder, on hero screens (.screen-card) and in settings (.card). */
.verify-reminder { border: 1px solid var(--border); }
.verify-reminder-head { display: flex; gap: 12px; align-items: flex-start; }
.verify-reminder-ico { color: var(--warn-ink); font-size: 1.25rem; line-height: 1; margin-top: 2px; }
.verify-reminder-title { font-size: .95rem; font-weight: 700; margin: 0 0 2px; }
.verify-reminder-body { margin: 0; }
.verify-reminder-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.verify-reminder-actions form { margin: 0; }

/* Admin › Audit log. */
.audit-filters {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 0 12px;
    align-items: end; margin-bottom: 12px;
}
.audit-filters .field { margin-bottom: 12px; }
.audit-filters .field input, .audit-filters .field select { padding: 9px 12px; font-size: .9rem; }
.audit-check { display: inline-flex; align-items: center; gap: 8px; margin-bottom: 12px; cursor: pointer; }
.audit-check input { width: 18px; height: 18px; accent-color: var(--teal-500); }
.audit-filter-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; grid-column: 1 / -1; }
.audit-caption {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.audit-action { font-size: .8rem; }
.audit-pager { display: flex; align-items: center; justify-content: center; gap: 12px; margin-top: 16px; }

@media print {
    /* The recovery-code page prints the codes and nothing else worth keeping. */
    .acct-actions, .acct .btn { display: none !important; }
}
/* ==== end account and trust ==== */

/* ==== help center ==== */
/* /Help and /Help/{slug}. Articles are Markdown rendered to plain elements, so the article body
   is styled by element here rather than by class in the content. Links take the ink colour and an
   underline like every other inline link (see the p a rule above). */
.help-search { display: flex; gap: 8px; margin-bottom: 14px; }
.help-search input { width: 100%; }
.help-list { list-style: none; margin: 0; padding: 0; }
.help-list li { padding: 9px 0; border-top: 1px solid var(--border); }
.help-list li:first-child { border-top: 0; padding-top: 2px; }
.help-list a { font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
.help-category > summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: 8px; }
.help-category > summary::-webkit-details-marker { display: none; }
.help-title { font-size: 1.3rem; line-height: 1.25; margin: 0 0 6px; }
.help-body { font-size: .92rem; line-height: 1.55; }
.help-body h2 { font-size: 1rem; margin: 18px 0 6px; }
.help-body ol, .help-body ul { padding-left: 1.3em; margin: 6px 0 10px; }
.help-body li { margin: 4px 0; }
.help-body a { text-decoration: underline; text-underline-offset: 2px; }
/* Coach replies keep their line breaks — a how-to answer is a numbered list of steps. */
.coach-text { white-space: pre-line; }
/* ==== end help center ==== */

/* ==== meal plan: why this plan fits you ==== */
/* The card MealPlanFitExplainer feeds on /MealPlan/Details. A <details> so it needs no script:
   closed, the summary shows the focus line and the step titles; open, every step with the lesson
   behind it. The UA hides everything but <summary> when closed, which is why the preview lives
   inside the summary and is hidden again by the [open] rule. */
.plan-fit > summary { list-style: none; cursor: pointer; }
.plan-fit > summary::-webkit-details-marker { display: none; }
.plan-fit > summary::marker { content: ""; }
.plan-fit-chev { display: inline-flex; color: var(--text-muted); transition: transform .15s ease; }
.plan-fit[open] .plan-fit-chev { transform: rotate(180deg); }
.plan-fit-preview { margin-top: 10px; line-height: 1.5; }
.plan-fit[open] .plan-fit-preview { display: none; }
.plan-fit-steps { list-style: none; margin: 12px 0 0; padding: 0; }
.plan-fit-step { padding: 12px 0; border-top: 1px solid var(--border); }
.plan-fit-why { margin-top: 4px; line-height: 1.5; }
/* Lesson chips are links; .chip already clears the 44px tap target on touch (see the
   a.chip rule in the touch block above). Locked weeks keep the chip shape in muted ink so the
   source of the reasoning is still named without reading as a dead link. */
.plan-fit-lesson { text-decoration: none; }
.plan-fit-lesson.locked { color: var(--text-muted); }
/* ==== end meal plan: why this plan fits you ==== */
