/* TourKit design tokens — the single source for both themes.
 *
 * Lived in style.css AND app/style.css until now, which is two copies of the
 * same 25 values and exactly the drift this file exists to stop. Every page
 * links this FIRST, before its own stylesheet, so the marketing site, the
 * legal pages, the public route and stage pages and the app all resolve the
 * same tokens and all answer to the same data-theme.
 *
 * The theme is applied to <html data-theme> by an inline script in each page's
 * <head>, before this file is fetched, so nothing paints one theme and flips.
 * See app/core/theme.js.
 */
:root {
  /* Ground — blue-grey, hand-stepped. This is the family the app always had
     and the one Darren prefers; what had to go was the stock RAMP, not the
     hue. Tailwind slate sits at H215-222 with saturation swinging 16-47%
     between steps; this holds H210-217 on a saturation curve that falls
     smoothly 26% -> 10%, and no value here is a Tailwind step.
     Two earlier grounds are why the comment is this long: warm graphite read
     brown under an amber wash, and limestone fixed that but gave up the blue
     cast that made the app look like itself. (TKF-226) */
  --bg0:   #0f131a;
  --bg1:   #1a2028;
  --bg2:   #262c36;
  --bg3:   #343b46;
  --bdr:   #454d59;
  --bdr2:  #5a6472;

  /* Ink */
  --txt-hi:#f6f7f9;
  --txt:   #e4e8ec;
  --txt2:  #c2c9d1;
  --dim:   #99a2ad;
  --dim2:  #6c7684;
  --dim3:  #5a6472;

  /* Signal. DO NOT CHANGE — assets/logo.svg and the icons under
     assets/icons/ are this exact value, and it is the brand. 8.11:1 on
     --bg1, 8.65:1 on --bg0, so it needs no adjustment on this ground. */
  --amber: #f59e0b;

  /* Semantic. Held in a 44–58% chroma band so --amber, at 92%, is the only
     high-chroma value on screen and reads as the signal rather than as one
     more colour. Every one of these measures better against the new ground
     than the value it replaced did against the old one. */
  --green: #5c9c67;
  --blue:  #5589c4;
  --red:   #d9614f;
  --orange:#d98a3c;
  --pink:  #c98ab0;

  /* Hues that carry meaning of their own and are not interchangeable with
     --blue: HRV is purple where power is amber and heart rate is sky, and the
     comment at analysis.css .eftp-hrv-ok says so. They were hardcoded Tailwind
     (purple-500, sky-400, teal-400) until now, which is why they did not
     follow the theme. */
  --purple: #ab86dc;
  --sky:    #49a6e0;
  --teal:   #3fb98a;

  /* Ramp steps, and not semantics — nothing in the UI means "yellow". The VO2
     rating ramp runs orange · yellow · lime · green · teal and the set above
     carries neither hue, so half that ramp stayed on the dark-theme literals
     #eab308 and #84cc16 while the other half was already tokens: on paper the
     token steps inverted and the literal ones did not, at 1.54:1 and 1.58:1.
     Held in the same 44-58% chroma band as the semantics so the five steps
     read as one scale rather than two vivid ones and three muted.

     An ordered scale must not change HUE with the theme — the zone comment
     below says why — but it does have to change LIGHTNESS, or it is a fill
     pretending to be ink. That is the line between this pair and --z1..--z7:
     those are painted BEHIND a label, these are painted AS one.
     Used only by .vo2-band-* in analysis.css. (TKF-226) */
  --yellow: #c9a940;
  --lime:   #91bc49;

  /* ── The zone scale ──────────────────────────────────────────────────────
     Z1-Z7 plus Sweet Spot and Multi-Zone, mirroring ZONE_LIST in
     app/core/zones.js. Declared HERE and deliberately NOT redeclared in the
     light block: this is an ordered DATA scale, not chrome. A rider learns
     that VO₂ Max is that orange, and a ramp that changes hue with the theme
     stops being a scale.
     They live in CSS at all because the library's filter chips are static CSS
     keyed on [data-zone], so they cannot read the JS. Everything that CAN read
     zones.js still should — this is a mirror, and zones.js is the original.
     Anything sitting ON one of these fills takes --on-amber, never --bg0:
     --bg0 is near-black on the dark ground and cream on paper, so a label that
     reads at 6.6:1 in one theme drops to 2.4:1 in the other. (TKB-247) */
  --z1: #94a3b8;
  --z2: #3b82f6;
  --z3: #06b6d4;
  --z4: #f59e0b;
  --z5: #f97316;
  --z6: #ef4444;
  --z7: #a855f7;
  --z-ss: #10b981;
  --z-mx: #e2e8f0;

  /* Chart series — a SEPARATE slot from --amber, deliberately. amber-500
     sits at lightness 0.769, outside the 0.48–0.67 band a data mark needs on
     a dark surface, so using the brand colour for a line fails validation. */
  --s1:    #ad8735;
  --s2:    #4a84c9;
  /* Type. Mono set every string until TKF-226, which flattened the hierarchy —
     nothing had a distinct texture, so the uppercase letter-spaced label had to
     carry it instead, 188 times. Mono now keeps the job it is good at: numbers,
     tables and metrics, where tabular figures earn it. */
  --font-text: 'Instrument Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-data: 'JetBrains Mono', 'Fira Code', ui-monospace, monospace;

  /* ── The type scale ──────────────────────────────────────────────────────
     TKF-226 tokenised the colours and the two FACES and stopped there, which
     left size on literals: 864 `font-size` declarations across ~30 distinct
     values, none of them reading a token. A rider noticed and said the site
     has too many font sizes. It did (TKF-229).

     Ten steps, and the dense band is where the UI actually lives. Pick by the
     ROLE, not by eyeballing a number — picking the nearest number is what
     produced thirty sizes, and tokenising alone did not fix it: the first pass
     mapped every literal to its closest step and left 445 lowercase rules
     spread across 11/12/13, three sizes doing one job. That is what a rider
     meant by "font busy" (TKF-229, TKB-253).

       --fs-micro  UPPERCASE ONLY. Letter-spaced eyebrows, micro-labels, the
                   key above a value, badges. 11px of tracked caps sets about
                   as wide as 13px of lowercase, which is how it sits this low
                   and still reads. **Lowercase must never take it** — at 11px
                   it is the hardest text in the app to read, and there were
                   114 rules doing it. There are none now; a grep for
                   --fs-micro without text-transform:uppercase should stay empty.
       --fs-xs     The compact tier, and the only step that carries both cases:
                   dense data (values, units, ticks, tags, chips, table cells)
                   and compact controls (buttons, tabs). A control needs the
                   extra pixel more than a label does.
       --fs-sm     Prose the rider READS — card bodies, descriptions, help and
                   error text, hints. Also CAPS section headers, which sit a
                   step above an eyebrow because they head a panel rather than
                   label a number.
       --fs-base   Body, and card titles.
       --fs-md     Emphasis — metric values, an input's own value.

     So uppercase legitimately appears at three steps and they are not
     interchangeable: micro labels a value, xs is a control, sm heads a panel.
     Lowercase appears at two: xs is data, sm is prose.

     Above --fs-md the steps open out (~1.2 each) because headings are read at a
     glance and a 2px difference reads as a mistake rather than a level.

     TourKitPhoneApp/src/theme.ts mirrors these NAMES exactly and deliberately
     carries its own values above --fs-md: a phone is held at a third the
     distance, so the dense band matches to the pixel while the display tier
     runs smaller. Same system, two viewing distances. Re-transcribe there when
     a name is added here, and hold the same role rule — it has the same
     uppercase-only constraint on `micro`. */
  --fs-micro: 11px;
  --fs-xs:    12px;
  --fs-sm:    13px;
  --fs-base:  15px;
  --fs-md:    17px;
  --fs-lg:    20px;
  --fs-xl:    24px;
  --fs-xxl:   30px;
  --fs-hero:  38px;
  --fs-mega:  48px;
  /* Amber wash — the tint base for the 47 places amber is painted onto a
     surface rather than used as a signal. Raw amber cannot be that base: at
     18% over this ground it still composites to #443620, a blue channel of 32
     and visibly brown. This is amber mixed 55% toward --txt, which composites
     to #433e36 instead — a blue channel of 54, and a wash that stays a wash.
     One knob; every call site keeps its own alpha. (TKF-226) */
  --amber-wash: 240, 201, 134;
  /* Amber has two jobs and one ground cannot serve both once a light theme
     exists. On this ground they are the same value; the light block is where
     they diverge. --amber fills, --amber-ink writes and draws hairlines,
     --on-amber is the label sitting on top of a fill. (TKF-226)

     Being equal HERE is what makes the split easy to get wrong: on the dark
     ground the two are interchangeable, so a fill wearing the ink value looks
     right until someone opens the light theme. It has now been got wrong three
     times — favourite stars (TKB-231), chart markers (TKB-233), and every
     checkbox in the app (TKB-250). If you are asking which one to use, ask
     whether the colour is a SHAPE or a LETTER; only letters and hairlines take
     the ink. `accent-color` is a fill: it paints the box, and the browser picks
     the tick's own colour for contrast against it. */
  --amber-ink: #f59e0b;
  --on-amber:  #0f131a;
  /* The label on an ACCENTED row — selected or hovered — whose ground is an
     --amber-wash tint or a plain raised surface, never a solid --amber fill.
     A third case, and the two above cannot cover it: --on-amber assumes a gold
     ground underneath, and --amber-ink assumes writing the word in amber is
     available at all, which on paper means writing it in a colour that reads
     brown. So on the dark ground this IS the ink amber and nothing moves; on
     paper it steps out of amber entirely and the accent is carried by the
     shapes beside the word — the rail and the icon take --amber and stay gold
     on both grounds.

     Deliberately absent from TOKENS in core/palette.js: nothing in JS resolves
     it, and a var() follows the theme by itself, so listing it would only add
     another claimant to the value-keyed map TKB-251 had to disambiguate.
     (TKB-277) */
  --on-amber-wash: #f59e0b;
}

/* ── Light theme ──────────────────────────────────────────────────────────
   Map sheet: the ground is paper and elevation inverts — --bg1 sits BRIGHTER
   than --bg0, because on paper a card catches light rather than absorbing it.
   Set by core/theme.js on <html>; the inline script in the document head
   applies it before first paint so there is no flash of the other theme.

   --amber stays #f59e0b. It is the logo and it survives here as a fill:
   7.83:1 with --on-amber on top. What it cannot do is write — #f59e0b on
   this paper is 1.82:1 — so --amber-ink drops to the same hue and saturation
   at lightness 30%, which measures 4.58:1 on the ground and 5.32:1 on a card.
   ────────────────────────────────────────────────────────────────────────── */
:root[data-theme="light"] {
  --bg0:   #efece2;
  --bg1:   #f9f7f1;
  --bg2:   #e7e3d6;
  --bg3:   #dad5c5;
  --bdr:   #cbc5b3;
  --bdr2:  #aca596;

  --txt-hi:#100e0a;
  --txt:   #201d17;
  --txt2:  #3d3830;
  --dim:   #565043;
  --dim2:  #837d6c;
  --dim3:  #aca596;

  --amber:     #f59e0b;
  --amber-ink: #935f06;
  --on-amber:  #201d17;
  --on-amber-wash: #100e0a;

  --green: #45663d;
  --blue:  #2c6486;
  --red:   #a32b1e;
  --orange:#8a5210;
  --pink:  #8a3f66;

  --purple: #6b4a9c;
  --sky:    #1a6d97;
  --teal:   #1a7357;

  --yellow: #705910;
  --lime:   #4f6b1f;

  --s1:    #b06a10;
  --s2:    #15709f;

  /* The wash has to invert too: a pale tint is invisible on paper, so the
     tint base becomes the ink step and the same alphas read as parchment. */
  --amber-wash: 147, 95, 6;
}

/* Wordmark. Two files exist and only the one the theme needs is fetched: an
   <img> that is display:none still downloads, a background-image does not.
   Both PNGs are 1880x607, so aspect-ratio derives the width from the height
   and no call site has to hardcode one. (TKF-226) */
.tk-wordmark {
  display: block;
  aspect-ratio: 1880 / 607;
  background: url('/assets/wordmark-white.png') no-repeat center / contain;
}
:root[data-theme="light"] .tk-wordmark {
  background-image: url('/assets/wordmark-navy.png');
}

/* ── Theme toggle ────────────────────────────────────────────────────────────
   The control emitted by _includes/theme-toggle.php. Fixed rather than placed
   in a nav because these pages do not share one. The app's own toggle is a
   sidebar row and takes none of this — it only shares the icon swap below. */
.tk-theme-toggle {
  position: fixed;
  top: 14px;
  right: 14px;
  z-index: 200;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 1px solid var(--bdr);
  border-radius: 6px;
  background: var(--bg1);
  color: var(--dim);
  cursor: pointer;
  transition: color .15s, border-color .15s, background .15s;
}
/* Slotted: a page with a top bar declares [data-theme-toggle-slot] and
   core/theme.js moves the button into it, so it lays out as an ordinary item of
   that bar instead of floating over whatever the bar's right end holds — which
   on the public route and Stages pages was the Log Out link (TKB-304). The
   fixed corner stays the default: most pages carrying this toggle (legal,
   support, password reset) have no bar to put it in, which is why it was
   pinned to the corner in the first place (TKF-226). */
[data-theme-toggle-slot] > .tk-theme-toggle {
  position: static;
  top: auto;
  right: auto;
}
.tk-theme-toggle:hover { color: var(--amber-ink); border-color: var(--amber-ink); }
.tk-theme-toggle:focus-visible { outline: 2px solid var(--amber-ink); outline-offset: 2px; }
.tk-theme-toggle svg { width: 18px; height: 18px; }

/* Icon swap, shared with the app's sidebar row: show the theme you would GET. */
:root:not([data-theme="light"]) .tk-ico-moon,
:root:not([data-theme="light"]) .tk-when-light { display: none; }
:root[data-theme="light"] .tk-ico-sun,
:root[data-theme="light"] .tk-when-dark  { display: none; }
