/* FITCLUB design tokens — spec §1.

   No longer flat by mandate. v2 puts a coloured halo behind the figures that
   matter — the streak count, the live session clock, the progress rail — and
   the user chose that look on 8 August 2026 over the previous rule.

   The mandate is replaced by a narrower one, because "shadows are allowed now"
   would spread: glow is *emission*, not depth. It only ever comes from a
   saturated colour on a dark surface, and only on things that are live or
   record-breaking. Nothing gets a drop shadow to look raised — that is what
   the surface ramp is for.

   Theming: dark is the default and the design target (Hevy is dark-only).
   A light palette lives at the bottom of this file. Every colour a component
   uses must come from here — a literal hex in a component breaks light mode. */

:root {
  color-scheme: dark;

  /* ---- Surfaces ----

     v2 sits the app on true black with neutral greys above it — the iOS system
     ramp (#1c1c1e, #2c2c2e, #3a3a3c) rather than the blue-cast near-black we
     had. Black is what makes the huge unboxed numbers on the home screen read
     as floating rather than as content in a dark box, which is the whole
     device of that layout.

     Hairlines are white at low alpha, not a solid grey: on true black a solid
     divider reads as a seam, an alpha one recedes. */
  --bg: #000000;
  --surface: #1c1c1e;          /* cards, rows, raised panels */
  --surface-2: #2c2c2e;        /* controls on a card, chips, thumbs */
  --surface-3: #141414;        /* recessed: inputs, media wells, segmented track */
  --surface-press: #3a3a3c;
  --surface-bar: #000000;      /* nav floats on the page, not above it */
  --surface-band: #141414;
  --surface-unread: #1c1710;   /* tinted with the second accent, which is still red */
  --hairline: rgba(255, 255, 255, 0.09);
  --hairline-strong: rgba(255, 255, 255, 0.22);  /* input borders, dashed affordances */

  /* ---- Brand ----

     HANDOFF §3's rule outlived the colour it was written about: the accent
     marks one thing per screen — the value that is live, current, or just
     changed — and two of them means one is wrong. That still holds. Only the
     hue has moved, from red to orange to green to here. */
  /* Electric chartreuse, the OpenRouter look.
   *
     18:1 against black, which is the brightest thing this palette has ever
     carried and the reason it works on a near-black app: it does not need a
     glow to be found, it simply is the brightest object on the screen.

     Success used to be held apart from it at #30d158, so that "you finished
     this" and "press this" were different statements. That was sound in theory
     and wrong on screen: two greens read as two themes fighting. Success is now
     the accent, and --accent-2 carries anything that must not be confused
     with it.

     Channels as well as a hex, so tints and glows elsewhere read the token. */
  --accent-rgb: 208, 255, 0;
  --accent: #d0ff00;

  /* The old red, kept as a second accent for the things that want attention
     without being the main action — a live session, an unread marker. Same hue
     as --danger, which is a smaller problem than it looks: "look at this" and
     "this destroys something" are adjacent, where "confirm" and "destroy" were
     opposites. */
  --accent-2-rgb: 255, 59, 48;
  --accent-2: #ff3b30;
  --accent-2-soft: rgba(255, 59, 48, 0.16);
  /* --accent-text and --success-text already existed; this is the third of the
     set, and it was missing — which DESIGN.md's own rule needs: anything
     sitting on an --x-soft takes --x-text, never --x.
     Measured on the RIR chip, which is 11px and therefore owes 4.5:1:
     --accent-2 itself on that tint over a card is 4.16 and fails; this clears
     at 6.30 dark and 7.01 light. */
  --accent-2-text: #ff8a80;
  /* Its own halo. A red dot wearing the green glow reads as a mistake, and
     everything marked with the second accent is small enough that the halo is
     most of what you see. */
  --glow-accent-2: 0 0 22px rgba(255, 59, 48, 0.6), 0 0 44px rgba(255, 59, 48, 0.3);
  --glow-accent-2-sm: 0 0 16px rgba(255, 59, 48, 0.7);
  /* A shade down, never a different hue — a press state is the same colour
     under pressure. Chartreuse has almost nowhere to go lighter, so it reads by
     getting slightly deeper and denser instead. */
  --accent-press: #b3dd00;
  --accent-soft: rgba(208, 255, 0, 0.16);  /* tinted fills: badges, PR chips */
  --accent-text: #d0ff00;   /* 18:1 on black — bright enough to use as-is */

  /* Inactive chips and outline buttons — HANDOFF.md §3 "Border". */
  --border: rgba(255, 255, 255, 0.18);

  /* ---- Semantic ---- */
  /* Success is the accent, not a second green.
   *
   * It was #30d158 — iOS green — on the reasoning above that "you finished
   * this" and "press this" should not be the same colour. In practice the two
   * greens simply read as a mistake: a lime app with emerald tick marks looks
   * like two themes fighting, and it was reported as one twice. Meaning is
   * carried by --accent-2 and --danger, which are unmistakably not this.
   *
   * Everything downstream — done sets, streak dots, calendar keys, success
   * toasts — reads these tokens, so this is the only place it changes. */
  --success: #d0ff00;
  --success-text: #d0ff00;     /* 18:1 on black, same as the accent */
  --success-row: rgba(208, 255, 0, 0.10);   /* a completed set */

  /* The AI coach's own colours (owner's design, 29 Sep 2026). They appear
     nowhere else, so they mean "the AI coach" and nothing more: the comet
     round the thinking capsule, and the pulse round an official coach's photo. */
  --coach-comet-1: rgba(150, 0, 255, 0.4);
  --coach-comet-2: rgba(0, 102, 255, 0.8);
  --coach-comet-3: rgba(0, 255, 128, 1);
  --coach-comet-4: rgba(255, 255, 255, 1);
  --coach-pulse-1: rgba(150, 0, 255, 1);
  --coach-pulse-2: rgba(0, 102, 255, 1);
  --coach-pulse-3: rgba(0, 255, 128, 1);
  --coach-think-fill: #111114;  /* inside the capsule: a shade above the sample's #0a0a0c (owner) */
  --coach-wait-fill: #1c1c22;   /* the thinking capsule in the set table: the band row is #141414, so #111114 melted into it (owner, 3 Oct 2026) */
  --coach-fill: #18181b;        /* the coach's answer card */
  --coach-field: #26262a;       /* the message field on that card */
  --success-soft: rgba(208, 255, 0, 0.16);
  --on-success-fill: #14180a;  /* dark tick on the lime check */
  --live: #4cc4ff;             /* something counting right now */
  /* Was #ffd60a, 21° from the new accent and reading as the same family. A
     premium badge beside a primary button has to be plainly a different thing,
     and gold already carries "earned" here. */
  --pro: #e8b13b;
  /* One red.
   *
     This was #ff453a against the accent's #ff3b30 — six units apart, which no
     eye resolves as two colours. Two tokens for one visible red only bought the
     chance of them drifting apart. What separates destructive from primary is
     the treatment, not the hue: HANDOFF §3 already says destructive is outline
     or text and never filled, so shape carries the meaning and the colour does
     not have to. */
  --danger: #ff3b30;
  --danger-rgb: 255, 59, 48;   /* for tints: rgba(var(--danger-rgb), a) */
  --danger-soft: rgba(255, 59, 48, 0.14);

  /* How far a tappable surface sinks under a thumb. One number, so a tile, a
     button and a row all answer to the same degree. */
  --press-scale: 0.97;

  /* Data series — charts, muscle split, macro bars. */
  --data-blue: #4cc4ff;
  --data-violet: #b98cff;
  /* The AI comet (owner, 30 Sep 2026): the stops of his capsule sample,
     spinning behind the plan builder's and plan review's thinking box. */
  --comet-1: rgba(150, 0, 255, 0.4);
  --comet-2: rgba(0, 102, 255, 0.8);
  --comet-3: rgba(0, 255, 128, 1);
  --comet-4: rgba(255, 255, 255, 1);
  --comet-fill: #111114;
  --data-violet-rgb: 185, 140, 255;   /* the landing page's second hero blob */
  --data-grey: #3a4049;
  /* Addendum §2: macros are a data series, a sanctioned exception to §3.
     They appear only in bars and legend dots — never on a numeral, never with
     glow. That is what keeps §3 intact: accent still marks the one live thing. */
  --macro-protein: #e8734a;
  --macro-carb: #5b8dd9;
  --macro-fat: #d9c05b;

  /* Over target. Protein over is fine, not a failure; carbs, fat and total
     kcal over are a warning, never destructive red — addendum §3. */
  --over-ok: #d0ff00;   /* within target, on the accent like every other yes */
  --over-warn: #ffcc00;

  /* Water tracker. A muted blue that sits below macros in visual weight —
     water is a background habit, not a headline metric. */
  /* Not --live's colour. The two were byte-identical (#4cc4ff), so a habit
     you top up all day wore the badge that means "a session is running right
     now". They never share a screen, which is why it looked fine and was still
     wrong. Calmer than --live as well: this sits under the calorie ring all day
     and should not compete with it or with the accent. */
  --water: #3a9fd8;
  --water-soft: rgba(58, 159, 216, 0.16);

  /* The record family. `medal` and `trophy` are the only glyphs that do not
     take their colour from context — the designer's call, so that a record
     reads as a record wherever it appears. Her hex, from the pixel icon set. */
  --gold: #e8b13b;

  /* One colour per set type (owner, 24 Sep 2026), on the set number/letter in
     the workout and the routine editor. Built from existing tokens, so the
     light theme follows without restating them. */
  --set-normal: var(--text);
  --set-warmup: var(--gold);
  --set-failure: var(--danger);
  --set-drop: var(--data-violet);
  --set-restpause: var(--data-blue);
  --set-cluster: var(--macro-protein);
  /* RIR in three colours (owner, 30 Sep 2026, replacing the four of 28 Sep):
     0 and 1 red, 2 grey, 3+ lime. Four tokens still, so every band keeps its
     own name and a later change is a value here, not a code change. */
  --rir-0: #ff453a;
  --rir-1: #ff453a;
  --rir-2: #8e8e93;
  --rir-3: #d0ff00;

  /* Two more stops so gold can be a metal rather than a flat fill. A PRO badge
     is 18px square: at that size a single hex reads as a yellow chip, and the
     thing that says "metal" is a light edge over a dark one. Kept in the token
     file with the rest of the palette rather than written into the badge, so
     the light theme can restate them at its own contrast. */
  --gold-lit: #ffd97a;
  --gold-deep: #a9761d;

  /* ---- Text ----
     The v2 ramp: white, then the iOS greys. Four steps rather than five in
     practice — most of the design is white type or #8e8e93 labels, with the
     fainter two reserved for eyebrows and inactive marks. */
  --text: #ffffff;
  --text-mid: #c7c7cc;
  --text-dim: #8e8e93;
  /* Raised to clear 4.5:1 on black.
   *
     HANDOFF §2 asks for #5a5a5f on micro labels, and that measures 3.06:1 —
     under AA for anything below 19px, which is every single use of it: 9–11px
     eyebrows, the tab-bar labels on all five tabs, calendar weekday heads, the
     week strip, band titles. An audit across sixteen screens found 76 of them.
     It is the app's most-repeated text and it was its least readable.

     #78787e is 4.69:1 and still reads as the quiet tier against #8e8e93 above
     it. The design intent — three steps of grey, each quieter than the last —
     survives; only the bottom step moves up to where it can be read.

     But that 4.69:1 is against the *page*. On --surface (#1c1c1e) the same grey
     measures 3.88:1, and cards are where most of this app's text lives. An
     audit found three words-that-matter sitting on one — the weekday letters
     under the calorie chart, the water target, the monthly figure labels — all
     of them under AA and all of them moved to --text-dim.

     So: --text-faint is a page colour. **Text on a card takes --text-dim or
     above.** This is the same trap as --text-dim and --success on --x-soft,
     which the README has now recorded five times: a tone tuned against one
     ground tells you nothing about how it reads on another. */
  --text-faint: #78787e;
  /* Not for text. Inactive dots, hairline marks, disabled glyphs — anything
     that carries meaning in words uses --text-faint or above. */
  --text-fainter: #56565c;
  --on-accent: #000000;        /* HANDOFF: filled accent buttons take black */
  --accent-fill: var(--accent);       /* light mode splits fill (lime) from text (deep green) */
  --success-fill: var(--success);
  --on-solid: var(--on-accent);    /* ink on red / gold fills; light mode keeps its own */
  --switch-off: var(--surface-2);
  --switch-knob-off: var(--on-accent);
  --on-pro: #000000;
  /* Ink that has to hold over the promo spectrum — the check on a certified
     coach's badge, which sits on all four hues in turn as the wheel travels.
     The same value in both themes, like the photo scrim below: what is behind
     it is the gradient, not the page, so the theme has no say in it. */
  --on-spectrum: #ffffff;
  --on-success: var(--text);   /* a completed row is tinted, not filled */
  --control: #2b3038;
  --illustration-bg: #ffffff;  /* exercise thumbnails are always light discs */
  --illustration-fg: #111111;
  --scrim: rgba(0, 0, 0, 0.6);
  --scrim-strong: rgba(0, 0, 0, 0.78);  /* the guided tour's dimmer, both themes */
  --overlay-press: rgba(255, 255, 255, 0.05);

  /* Over a photograph, not over the page — so these are the same in both
     themes on purpose, and must not be swapped for --scrim. A photo is just as
     bright behind a light UI as a dark one, and thinning the scrim in light
     mode would leave white text sitting on whatever the picture happens to be.
     The one place a fixed colour is the correct answer. */
  --photo-scrim: rgba(0, 0, 0, 0.55);
  --on-photo: #ffffff;

  /* A soft highlight laid over a filled card. White works on the dark page;
     light mode gets a dark sheen instead, because white on white is nothing. */
  --sheen: rgba(255, 255, 255, 0.10);
  --tile-wash: rgba(255, 255, 255, 0.05);   /* a tile laid on a card (recap boards) */
  --cell-off: rgba(255, 255, 255, 0.07);    /* an empty day or week cell */

  /* The landing page's sticky nav, a translucent strip over whatever has
     scrolled beneath it — themed below, like --scrim. */
  --nav-glass: rgba(0, 0, 0, 0.6);

  /* A phone's own bezel and notch, on the landing page's device mockups.
     Plastic, not app UI — a real phone's case does not turn white in light
     mode, so like --photo-scrim this is the same in both themes on purpose. */
  --device-bezel: #0a0a0a;

  /* ---- Glow ----
     Two stops: a tight bright halo and a wide faint one. Written as text-shadow
     and box-shadow pairs so a component only ever names the token.

     Deliberately absent from the light theme, where a halo on white reads as a
     printing fault rather than as light. The overrides below blank them. */
  /* HANDOFF.md §3 — glow is only ever applied to accent-coloured elements.
     White and grey never glow. */
  --glow-accent: 0 0 22px rgba(208, 255, 0, 0.55), 0 0 44px rgba(208, 255, 0, 0.28);
  --glow-accent-sm: 0 0 16px rgba(208, 255, 0, 0.65);
  --glow-live: 0 0 20px rgba(76, 196, 255, 0.65), 0 0 40px rgba(76, 196, 255, 0.28);
  --glow-success: 0 0 18px rgba(208, 255, 0, 0.6);

  /* ---- Radii ---- */
  --r-xs: 6px;
  --r-sm: 10px;
  --r-md: 14px;
  --r-lg: 16px;              /* HANDOFF §4: panels are 16px */
  --r-xl: 24px;
  --r-pill: 999px;
  /* v2 abandons the pill: every button in the design is a rounded rectangle,
     13–16px depending on weight. One token, so the whole app follows. */
  --r-btn: 15px;
  --r-tile: 12px;              /* dark utility surfaces: search bar, filter tiles */

  /* ---- Spacing ---- */
  --s0: 2px;
  --s1: 4px;
  --s2: 8px;
  --s3: 12px;
  --s4: 16px;
  --s5: 20px;
  --s6: 24px;
  --s7: 32px;
  --s8: 40px;
  --page-x: 24px;            /* HANDOFF §5: screen padding */
  --log-x: 12px;             /* the live log's one inline inset: set rows, add set, footer */

  /* ---- Typography ----

     Sized in rem, not px, so the browser's and the OS's text-size settings
     actually move it. Someone who has turned their phone's font up has told
     us they need it; px ignores that and is an accessibility failure, not a
     styling preference.

     1rem is 16px by default, so these are the same sizes as before at default
     settings — 0.9375rem is the old 15px. Nothing looks different unless the
     reader has asked for it to. */
  --font: "Kalameh", "Vazirmatn", system-ui, "Segoe UI", Tahoma, sans-serif;

  /* HANDOFF §2: IBM Plex Mono for every numeral. Kalameh is the fallback
     until the Plex files are bundled — it keeps tabular figures, so columns
     still align, but the letterforms are not the design's. */
  --font-num: "IBM Plex Mono", ui-monospace, "Kalameh", monospace;
  --fs-display: 1.625rem;  /* 26px */
  --fs-title: 1.375rem;    /* 22px */
  --fs-h: 1.125rem;        /* 18px */
  --fs-body: 0.9375rem;    /* 15px */
  /* What a text field is set in — 15px like everything else on a desktop.
   *
     On a touch screen it becomes 16px, and that is not a design choice. iOS
     Safari zooms the whole page in whenever a field under 16px takes focus,
     and it does not zoom back out afterwards: tap a weight box mid-set and the
     app is left magnified until you pinch it back yourself. There is no way to
     refuse that from the viewport meta — Safari ignores `user-scalable` and
     `maximum-scale` deliberately, so the type size is the only lever. 16px is
     the threshold, so 16px it is. */
  --fs-field: var(--fs-body);
  --fs-sm: 0.8125rem;      /* 13px */
  --fs-xs: 0.6875rem;      /* 11px */
  --fs-stat: 1.25rem;      /* 20px */
  --fw-regular: 400;
  --fw-medium: 500;
  --fw-bold: 700;
  --lh-tight: 1.25;
  --lh-body: 1.7;

  /* ---- Safe areas ----
     The app runs viewport-fit=cover with a translucent iOS status bar, so
     content genuinely sits under the notch, Dynamic Island and home
     indicator. Named here so every fixed or sticky edge uses the same value
     and none get forgotten — the top one was, and the Finish button on the
     workout log ended up under the iPhone clock. */
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);

  /* ---- Layout ---- */
  --nav-h: 92px;             /* addendum §1: five tabs plus the scrim */
  --header-h: 54px;
  --content-max: 720px;
  --sidebar-w: 232px;
  --tap: 44px;                 /* minimum touch target */

  /* ---- Motion ---- */
  --dur-fast: 120ms;
  --dur: 200ms;
  --ease: cubic-bezier(0.2, 0, 0.2, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);

  /* The latch: what ticking a set feels like. Down to .86 and back, once.
     The design calls it a mechanical snap — no bounce-up, no confetti. It
     fires hundreds of times a session, so it has to be satisfying at the
     first tap and invisible by the hundredth. */
  --dur-latch: 320ms;
  --ease-latch: cubic-bezier(0.3, 1.6, 0.4, 1);
  --ease-spring: cubic-bezier(0.3, 1.6, 0.4, 1);

  /* Progress rails and bars filling. */
  --dur-progress: 350ms;
  --ease-progress: cubic-bezier(0.2, 0.8, 0.2, 1);

  --dur-tint: 180ms;           /* a row changing state under your thumb */
  --dur-reveal: 220ms;         /* a panel expanding */

  /* ---- Layers ---- */
  --z-nav: 40;
  /* ---- The house ad's travelling light -------------------------------
   *
     The one place in this app that carries more than one hue, and the
     exception is deliberate rather than a lapse. Everywhere else colour means
     something — accent is "the one live thing", accent-2 is "not that",
     success, danger. A spectrum inside that vocabulary would be a colour with
     no job.
   *
     This is an advertisement for a *different product*. It should read as
     slightly foreign to the app, and a sweep no other surface uses is exactly
     how a reader knows at a glance that it is an offer rather than a feature.
     It is confined to `.promo` and must stay there.
   *
     Anchored on the accent so it still reads as ours, then cyan, violet,
     magenta — spaced far enough apart to travel visibly, and kept off pure
     primaries so it reads as light rather than as a gaming keyboard. */
  --promo-1: #d0ff00;
  --promo-2: #00e0ff;
  --promo-3: #8b5cff;
  --promo-4: #ff3ea5;

  --z-dock: 50;                /* floating rest-timer bar */
  /* Above the dock, below sheets. The pad is what your thumb is on, so it takes
     the bottom edge and the rest timer moves up over it — but a sheet opened
     from anywhere still covers both. */
  --z-numpad: 55;
  --z-sheet: 60;
  --z-modal: 70;
  --z-toast: 80;
}

/* Touch screens get 16px fields. See --fs-field above: below that, iOS Safari
   zooms the page on focus and leaves it zoomed.

   Keyed on the pointer rather than on iOS, because the rule is harmless
   anywhere — a 16px field on a phone is the right size regardless — and
   sniffing for Safari would leave every future browser that copies the
   behaviour broken. */
@media (pointer: coarse) {
  :root {
    --fs-field: 1rem;          /* 16px — the threshold, not a preference */
  }
}

/* ---------------------------------------------------------------- Light theme

   Applied when the user picks "روشن", or picks "سیستم" on a device set to
   light. Only colour tokens are overridden - every size, radius and timing
   is shared, so the two themes cannot drift apart structurally.

   Redrawn twice on 3 Oct 2026 (owner: no high contrast, no washed-out colours,
   and "not fun, no character" for the first, sage-and-olive try). Now:
   - a cool grey page (#e6e9ec) and light grey cards (#f5f7f8): no white, no
     black, and none of the green-grey that read as dull;
   - the brand lime (#d0ff00) is back as the fill of every button, chip, check
     and switch, with a deep green-black ink (#1f2b08, 12.8:1) on it;
   - a live grass green (#267300, 5:1 on the cards) for everything that is text,
     an icon, a line or a bar, because lime itself cannot be read on grey;
   - ink is slate (#2e3741, 10:1; the old #14161a on white was 18:1) and every
     grey tone is at least 4.5:1 on the page;
   - reds, gold and blues deepened to stay readable on grey. */

:root[data-theme="light"] {
  color-scheme: light;

  --bg: #e6e9ec;
  --surface: #f5f7f8;
  --surface-2: #d4d9dd;
  --surface-3: #dbe0e3;
  --surface-press: #c6ccd1;
  --surface-bar: #f5f7f8;
  --surface-band: #dce0e4;
  --surface-unread: #eef6c8;
  --hairline: rgba(36, 48, 60, 0.14);
  --hairline-strong: rgba(36, 48, 60, 0.24);

  /* Light mode needs its own accent: #ff3b30 carries white text at only 3.3:1,
     and button labels are 15px bold, which is not "large text" — so it fails.
     #d70015 clears 4.5:1 with white and still reads as the same red.

     This was left on the old orange when the dark accent became red on
     8 August 2026, so anyone on a light device saw an entirely orange app. */
  /* Darker than the dark theme's green, because light flips the ink: filled
     buttons take white here, and #30d158 carries white at only 3.5:1. */
  /* Far darker than the dark theme's chartreuse, because light flips the ink:
     filled buttons take white here and #d0ff00 carries white at 1.17:1, which
     is not a contrast so much as a rumour. */
  --accent-rgb: 38, 115, 0;
  --accent: #267300;        /* white ink 6.1:1 */
  --accent-2-rgb: 189, 37, 23;
  --accent-2: #bd2517;
  --accent-2-soft: #f7dcd8;

  /* The promo sweep, deepened for a white page. The dark set is tuned to glow
     against black and washes out to pastel on light, which reads as cheap
     rather than premium — the one thing this element must not do. */
  --promo-1: #267300;
  --promo-2: #0b7a94;
  --promo-3: #5b3fb0;
  --promo-4: #b0286a;
  /* Light flips the ink: the page is white, so this darkens rather than
     lightens. */
  --accent-2-text: #9a1d10;
  --accent-press: #1e5f00;
  --accent-soft: #e3f7a0;
  --accent-text: #1f6a00;   /* 8.1:1 on the light page */

  /* Success follows the light accent for the same reason it does in dark: one
     affirmative colour, not two. Chartreuse itself is unusable here — it carries
     white at 1.17:1 — so this is the same darkened olive the accent uses, and
     the ink on it flips to white to match. */
  --success: #267300;          /* white ink 6.1:1 */
  --success-text: #1f6a00;     /* 8.1:1 on the light page */
  --success-row: rgba(38, 115, 0, 0.12);

  /* Coach colours: same hues; the capsule and card stay light here, because
     dark boxes would put the dark label and text on dark. */
  --coach-comet-1: rgba(150, 0, 255, 0.4);
  --coach-comet-2: rgba(0, 102, 255, 0.8);
  --coach-comet-3: rgba(0, 200, 110, 1);
  --coach-comet-4: rgba(255, 255, 255, 1);
  --coach-pulse-1: rgba(150, 0, 255, 1);
  --coach-pulse-2: rgba(0, 102, 255, 1);
  --coach-pulse-3: rgba(0, 200, 110, 1);
  --coach-think-fill: #262d34;
  --coach-wait-fill: #313a43;
  --coach-fill: #2d353d;
  --coach-field: #3b454f;
  --success-soft: #e3f7a0;
  --on-success-fill: #1f2b08;
  --live: #0a68a4;
  --pro: #835400;   /* the light gold, for the same reason */
  --danger: #a82013;
  --danger-rgb: 168, 32, 19;
  --danger-soft: rgba(196, 38, 20, 0.12);

  /* Her gold is drawn for true black and scores 1.79:1 on this ground — the
     medal would be a pale smudge. Darkened to clear 5:1 while staying
     recognisably the same metal. */
  --gold: #835400;
  /* The same metal on a white ground: the lit edge has to stay dark enough to
     read as gold rather than as a pale wash, so the pair is tighter than the
     dark theme's and both sit below the ink they carry. */
  --gold-lit: #b8862a;
  --gold-deep: #5e3d00;

  --data-blue: #0a68a4;
  --rir-0: #bd2517;
  --rir-1: #bd2517;
  --rir-2: #4d5a66;
  --rir-3: #1f6a00;
  --data-violet: #7d4fc4;
  --comet-1: rgba(150, 0, 255, 0.4);
  --comet-2: rgba(0, 102, 255, 0.8);
  --comet-3: rgba(0, 200, 110, 1);
  --comet-4: rgba(255, 255, 255, 1);
  --comet-fill: #f5f7f8;
  --data-violet-rgb: 125, 79, 196;
  --data-grey: #b4bcc4;
  --macro-protein: #a84400;
  --macro-carb: #8a6a00;
  --macro-fat: #0a68a4;

  /* Light water: darker than dark theme because light flips ink. White on
     #4cc4ff is only 2.2:1, so the fill needs its own contrast treatment. */
  --water: #0a6a9f;   /* light: darker still, white ink 4.9:1 */
  --water-soft: rgba(10, 106, 159, 0.12);

  /* A halo on white reads as a printing fault, not as light. */
  --glow-accent: none;
  --glow-accent-sm: none;
  --glow-accent-2: none;
  --glow-accent-2-sm: none;
  --glow-live: none;
  --glow-success: none;

  --text: #2e3741;
  --text-mid: #414c57;
  --text-dim: #4d5a66;
  /* Same correction on light, where #6e747e measured 3.99:1 against #f4f5f7. */
  --text-faint: #53606c;
  --text-fainter: #58656f;
  --on-accent: #1f2b08;        /* the darkened orange takes white, not black */
  --accent-fill: #d0ff00;      /* the brand lime, for buttons and other filled controls */
  --success-fill: #d0ff00;
  --on-solid: #fbfcfd;       /* soft white on the red and gold fills */
  --switch-off: #a7b0b8;
  --switch-knob-off: #f5f7f8;
  --on-pro: #000000;
  --on-success: var(--text);
  --control: #b4bcc4;
  --scrim: rgba(30, 38, 48, 0.34);
  --overlay-press: rgba(36, 48, 60, 0.07);
  --nav-glass: rgba(230, 233, 236, 0.78);

  /* Deliberately identical to dark: these sit on a photograph, not on the page.
     See the note beside them in the dark block. */
  --photo-scrim: rgba(0, 0, 0, 0.55);
  --on-photo: #ffffff;

  --sheen: rgba(36, 48, 60, 0.05);
  --tile-wash: rgba(36, 48, 60, 0.05);
  --cell-off: rgba(36, 48, 60, 0.09);
}


/* Charcoal panels on the grey page (owner, 3 Oct 2026: "add that dark charcoal
   thing"): the bottom bar and everything that is the AI coach (the switch, the
   thinking capsule, the answer card, the planner and review box) are dark, the way
   they are in the dark theme, so the light page has something with weight and the
   lime has a dark ground to glow on. Inside them the colour roles go back to the
   dark theme's values, so the text, lime and lines in them need no light-mode
   special case. */
:root[data-theme="light"] :is(.nav, .coachmaster, .coachthink, .coachcard, .aithink) {
  color: var(--text);
  --text: #ffffff;
  --text-mid: #c7c7cc;
  --text-dim: #a4adb5;
  --text-faint: #98a1a9;
  --text-fainter: #8a939b;
  --hairline: rgba(255, 255, 255, 0.1);
  --hairline-strong: rgba(255, 255, 255, 0.22);
  --accent: #d0ff00;
  --accent-rgb: 208, 255, 0;
  --accent-text: #d0ff00;
  --accent-press: #b3dd00;
  --success: #d0ff00;
  --success-text: #d0ff00;
  --surface-press: #3d4750;
  --switch-off: #56606a;
  --switch-knob-off: #e8edf0;
  --danger: #ff6b60;
}

:root[data-theme="light"] .nav { background: #262d34; border-block-start-color: transparent; }

@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-fast: 0ms;
    --dur: 0ms;
  }
}
