/* /tokens.css */
/* TrailGoat — design tokens: the one palette vocabulary (TG-281).
 *
 * Loaded FIRST on every page, before the page's own stylesheet, so every
 * colour on the site traces back here. Page stylesheets (fuel.css, home.css,
 * site_performance.css) no longer carry their own :root palette; the theme
 * files (emerald / alpenglow / aurora / firstlight) override exactly these
 * names under their html.theme-* class, values unchanged.
 *
 * "Forest" — the default dark "trail at dusk" palette — is the plain :root
 * block below. Every token here is either today's value under a new name, or
 * a new step nothing consumes yet: this file is a visual no-op by contract. */

:root {
    /* ---- Ground: four steps, well → page → panel → raised ---- */
    --bg-0: #07120f;          /* deepest pine — the page */
    --bg-1: #0a1a1c;          /* forest navy — panels */
    --bg-well: color-mix(in srgb, var(--bg-0) 80%, #000);   /* inset tracks & wells, below the page */
    --bg-2:    color-mix(in srgb, var(--bg-1) 93%, #fff);   /* raised — --glass-2 flattened over --bg-1 */

    /* ---- Ink: four steps, bright → text → muted → faint ---- */
    --ink: #eaf4ee;           /* near-white text */
    --muted: #8ea7a0;         /* muted sage */
    --ink-bright: color-mix(in srgb, var(--ink) 60%, #fff);          /* headline emphasis */
    --faint:      color-mix(in srgb, var(--muted) 70%, var(--bg-0)); /* hints, placeholders, disabled */

    /* ---- Accent: the one hue on duty for actions and "current" ---- */
    /* Moss (TG-282). Orange is retired from chrome — it survives only as the
       Fueling data tint below. Each theme sets its own green-family accent;
       --accent-ink is the text colour on a solid accent fill (dark ink here,
       ≥12:1 on the forest ground; First Light flips it to paper). */
    --accent: #9ae600;
    --accent-ink: var(--bg-well);
    --selection: color-mix(in srgb, var(--accent) 28%, transparent);

    /* ---- The neutral ladder: every interactive state that is not the accent ----
       Chrome (buttons, toggles, nav links, hovers, menus, toasts, inputs) uses
       ONLY --accent plus these steps of the ink. Fills: idle 4% → hover 8% →
       selected 18%. Edges: a defined border sits at 40%; hover/focus edges and
       focus rings at 25%. Never a feature tint, never a coloured glow. */
    --fill-idle: color-mix(in srgb, var(--ink) 4%, transparent);
    --fill-hover: color-mix(in srgb, var(--ink) 8%, transparent);
    --fill-selected: color-mix(in srgb, var(--ink) 18%, transparent);
    --edge: color-mix(in srgb, var(--ink) 40%, transparent);
    --edge-soft: color-mix(in srgb, var(--ink) 25%, transparent);
    --ring: color-mix(in srgb, var(--ink) 25%, transparent);

    /* ---- Lines & glass ---- */
    --line: rgba(255, 255, 255, 0.09);
    /* Half a hairline, for edges that should be felt rather than seen — the
       code chip below. Derived from --line on purpose: a theme that re-lights
       the line gets a matching faint for free (TG-299). */
    --line-faint: color-mix(in srgb, var(--line) 55%, transparent);
    --glass: rgba(255, 255, 255, 0.045);
    --glass-2: rgba(255, 255, 255, 0.07);

    /* ---- Feature palette: one hue per Run Planner section ----
       Nine sections, nine hues, spread around the wheel so no two cards read
       as the same colour (KRI-119). Every theme overrides all of them; add a
       token here and there. These belong to data-viz and section iconography
       — charts, elevation, map layers, section icons — never to chrome (TG-282):
       not buttons, not hovers, not active/selected states. */
    --c-fuel: #ff7a1a;        /* Fueling */
    --c-pace: #9ae600;        /* Pacing */
    --c-crew: #3ad17f;        /* Crew — meadow */
    --c-course: #19c3b1;      /* Course */
    --c-gear: #8b6cff;        /* Gear */
    --c-weather: #e070ee;     /* Weather — dusk sky */
    --c-climb: #ff5d73;       /* Climbs */
    --c-aid: #36c5f0;         /* Aid stations + descents */
    --gold: #ffd23f;          /* AI coach — matches Capra's wordmark gradient; brand hue, outside the feature set */

    /* ---- Status: the three semantic colours (one status vocabulary) ----
       "Saved", "needs a look", "failed" — the words every status chip, error
       line and toast dot mean. They were five different reds and a handful of
       greens across the stylesheets; now they are three names, set per theme
       like the feature hues. Semantic, not accent: --ok is never the button
       colour and --accent is never "success" (TG-282). Each theme overrides
       all three, and only the state's colour changes — the chip's shape, its
       mono caps and its 1px currentColor edge stay the same everywhere. */
    --ok: #3ad17f;            /* ready, saved, synced */
    --warn: #ffb020;          /* draft, stale, needs a look */
    --bad: #ff5d73;           /* failed, invalid, destructive */

    /* ---- Legacy names: aliases of the feature palette during transition ----
       Every existing stylesheet reads these. They resolve through the theme's
       override of the --c-* token, so a theme only sets the new names. */
    --orange: var(--c-fuel);
    --moss: var(--c-pace);
    --fern: var(--c-crew);
    --teal: var(--c-course);
    --violet: var(--c-gear);
    --plum: var(--c-weather);
    --coral: var(--c-climb);
    --aqua: var(--c-aid);

    /* ---- Corners: two radii for the whole chrome (TG-283) ----
       Depth comes from thin borders and ground steps, not from blur, so the
       corners come down to two steps: --r-ctl for anything you press (nav
       links, buttons, chips, unit toggles, inputs, menu rows) and --r-card for
       the surfaces they sit on (panels, cards, menus, modals, toasts, the
       command palette). Avatars and the theme swatch dots stay round — they
       are pictures, not controls — and so do meters, progress bars and slider
       tracks, which are data. */
    --r-ctl: 6px;
    --r-card: 10px;

    /* ---- Type: three cuts of one family (TG-288) ---- */
    /* The Red Hat superfamily, in three roles: Display for headlines and the
       wordmark, Text for body copy and the chrome, Mono for the topbar, the
       small-caps labels and every figure. TrailGoat is secretly a numbers
       product, so its figures stay set like instrument readings — tabular,
       units tracked out in caps (TG-284) — but the mono now visibly belongs to
       the same family as the prose beside it instead of being a fourth rented
       font. The system fallbacks are deliberate: block fonts.googleapis and the
       page still reads and the columns still line up. */
    --display: 'Red Hat Display', -apple-system, BlinkMacSystemFont, sans-serif;
    --body: 'Red Hat Text', -apple-system, BlinkMacSystemFont, sans-serif;
    --mono: 'Red Hat Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;

    /* ---- The floor under a mono-caps label (TG-301) ----
       Mono caps with letter-spacing is the product's label voice, and it is
       the voice that shrinks first: several of these had drifted to 0.6rem —
       9.6px of tracked-out uppercase, which is under what a label can be read
       at. This is a floor, not a size. A label already above it keeps its own
       size via max(); one below it comes up to meet this. It steps UP on a
       phone, where the screen is closer but smaller and the same type is
       harder, not easier. Decorative marks (the goat's bib, the `i` glyph)
       are not labels and are exempt. */
    --mono-cap: 0.6875rem;                 /* 11px */

    /* ---- Motion: announce the change, then stop (TG-285) ---- */
    /* One easing curve and two durations for the whole product. Motion here
       exists to say something arrived — a menu, a toast, the palette — and
       then it is over. Nothing in the chrome loops forever under a planning
       tool the runner is trying to read. */
    --ease-snap: cubic-bezier(0.23, 1, 0.32, 1);   /* easeOutQuint */
    --dur-ctl: 150ms;                              /* controls */
    --dur-layer: 250ms;                            /* layers that arrive */

    /* ---- You are here: the one two-colour mark (TG-287) ----
       Omarchy's single indulgence, ported: the active window's gradient border.
       Exactly ONE element per view wears it — the section chip in view on the
       planner and Training, the active view tab on /courses. The pair is the
       wordmark's (teal→moss), so each theme's own --teal/--accent makes it
       theirs. The fill is the raised ground: the padding-box layer must be
       opaque, or the ring would bleed through the middle. Never on cards,
       buttons, menus or the topbar — that keeps its flat underline. */
    --here-ring: linear-gradient(45deg, var(--teal), var(--accent));
    --here-fill: var(--bg-2);
    --here-bg: linear-gradient(var(--here-fill), var(--here-fill)) padding-box,
               var(--here-ring) border-box;

    /* ---- Shadow: one modest pop, for floating layers only ---- */
    /* Anything that leaves the page plane — dropdown menus, the command
       palette, toasts, tooltips, popovers — shares this one token. Resting
       surfaces get a 1px --line edge and a step up the ground instead of a
       shadow (TG-283), so nothing on the page floats.
       The rest of the depth system (--raise-*, --well, --ledge-orange) stays in
       fuel.css on purpose: home.css never defined it, and nav.css reads it
       without fallbacks, so hoisting it here would grow shadows on the home
       page's chrome — a visual change that refactor could not make. */
    --shadow-pop: 0 8px 24px rgba(0, 0, 0, 0.45);
}

/* The phone step-up for --mono-cap (TG-301). Overriding the token once beats
   restating a size in every consumer's own media query. */
@media (max-width: 860px) {
    :root { --mono-cap: 0.75rem; }         /* 12px */
}

/* ===== The body face (TG-288) =====
   The default for every page, declared once here because tokens.css loads
   before any page stylesheet. A page sheet that still sets its own body face
   (fuel.css, site_performance.css) loads later and keeps winning — which is
   exactly what holds the unswept tool pages on their old families until the
   sweep issue lands. */
body { font-family: var(--body); }

/* ===== The code voice (TG-299) =====
   `code`, `kbd` and `pre` are the third cut too. Without this rule they fall
   through to the UA's own monospace — a fourth family the type system never
   chose, and the one the `<iframe>` mention on /for-race-directors was still
   set in. The chip treatment is what three page stylesheets were each drawing
   for themselves; declared once here, a `<code>` reads the same wherever it
   appears. `.85em` rather than a fixed size, so it tracks the copy around it. */
code, kbd, pre {
    font-family: var(--mono);
    font-size: 0.85em;
    background: var(--bg-well);
    border: 1px solid var(--line-faint);
    border-radius: 4px;
    padding: 1px 5px;
}

/* ===== Body links (TG-299) =====
   info.css has carried the base `a` rule since TG-220 — but only the info
   pages load info.css, which is why the one prose link on the signed-out
   Creator still rendered in the UA's blue. The rule belongs here, where every
   page already loads it, and it carries the underline a body link should have.

   Scoped to classless anchors on purpose. Every anchor the chrome draws — the
   topbar, the footer, the tool cards, the anchor buttons below — wears a class
   and paints itself; a bare `a` rule would repaint all of them and drag an
   underline through the nav. `a:not([class])` is exactly the prose link this
   is for, and it is why the button classes need no exclusion list of their
   own to stay out of it. */
a:not([class]) {
    color: var(--accent);
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* An anchor that is a button never wears one. `.export-btn` (fuel.css) and
   `.btn` / `.btn-ghost` (home.css) are drawn for `<button>` first, and only
   `.btn` ever reset the UA underline — so the `<a>` form of the others showed
   one on /courses, /discover, /pricing, /404, /about, /crew-sheet and
   /dashboard, wherever a page loaded fuel.css without the local patch
   dashboard.css had been carrying. Reset here, in every state, for every
   page. */
a.export-btn, a.btn, a.btn-ghost,
a.export-btn:hover, a.btn:hover, a.btn-ghost:hover,
a.export-btn:focus, a.btn:focus, a.btn-ghost:focus,
a.export-btn:active, a.btn:active, a.btn-ghost:active {
    text-decoration: none;
}

/* ===== The instrument voice (TG-284) =====
   Two utilities, used site-wide. `.data` is any figure the product computes —
   a pace, a distance, a vert total, a cutoff, a fuel target, an ETA — and the
   tabular figures are what make a column of them line up digit for digit.
   `.data-label` is the small-caps voice that names one: eyebrows, section
   labels, table headers.

   Page stylesheets apply the same two declarations directly to their own value
   classes (`.metric-num`, `.cs-val`, `.plan-table td`, …) rather than every
   emitter growing a class — they read `var(--mono)` at the point of use, which
   is what the token is for. These utilities are for markup that has no class of
   its own to carry it. */
.data {
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
}
/* The unit rides with the figure but never competes with it: smaller, tracked
   out, in caps, and one weight down (TG-284 AC-5 — hierarchy by weight, not by
   another colour). */
.data-u,
.data .unit,
.data .u {
    font-size: 0.8em;
    font-weight: 500;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.data-label {
    font-family: var(--mono);
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

/* ===== You are here (TG-287) =====
   The double-background technique: a flat fill on the padding box over the
   gradient on the border box, with the border itself transparent so the
   gradient shows through a 1px ring. Static by design — no transition, and
   nothing here for prefers-reduced-motion to suppress. Components whose own
   base rule loads later (`.section-chip`, `.cp-chip`) restate these four
   declarations at the point of use, reading the same tokens. */
.tg-here {
    color: var(--accent);
    border: 1px solid transparent;
    background: var(--here-bg);
    transition: none;
}

/* ===== The one entrance (TG-285) =====
   Every floating layer arrives the same way: a fast fade up from 96%, on
   --ease-snap. Defined here rather than in nav.css so the pages that skip nav
   (the crew sheet, the embed) can use it too. Each consumer sets its own
   transform-origin so the layer grows out of the control that opened it. */
@keyframes tg-pop-in {
    from { opacity: 0; transform: scale(0.96); }
    to   { opacity: 1; transform: none; }
}

/* ===== Touch (2026-09-04) =====
   Two properties, applied once here because tokens.css loads first on every
   page, so every control on the site inherits the behaviour rather than each
   stylesheet remembering it.

   `touch-action: manipulation` tells the browser a tap on a control can never
   be the first half of a double-tap-to-zoom, so it dispatches the click
   immediately instead of waiting to find out. That wait is the "not very
   responsive" feeling on a phone: the control is fine, the browser is just
   holding the event. Only interactive elements are named — the page body keeps
   pinch-zoom, which is an accessibility affordance, not a bug.

   The tap highlight is turned off in favour of each control's own :active
   state: the default is a grey rectangle that ignores border-radius and paints
   over the themed press feedback the components already define. */
a, button, summary, label, select, input, textarea,
[role="button"], [role="tab"], [role="switch"], .tg-tab {
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
}

/* ===== Focus: one ring, every page (2026-09-24) =====
   A keyboard visitor needs to see where they are, and until now that depended
   on which stylesheet a control happened to live in — the topbar drew a ring,
   the Creator, the info pages and most of the dashboard drew nothing but the
   browser default, which is a blue that belongs to no theme. This is the site
   default: a 2px ring in the accent, 2px off the control. `outline` follows
   `border-radius` in every current engine, so a pill gets a pill-shaped ring
   and a card gets a card-shaped one without naming either.

   Wrapped in :where() so it carries ZERO specificity: any control that already
   draws its own focus treatment (an inset ring on a tab, a border-colour swap
   on a text field) keeps it, because any class selector outranks this. It only
   fills the gaps. The main landmark is the skip link's target and takes focus
   programmatically; a ring round the whole page body says nothing. */
:where(a[href], button, input, select, textarea, summary,
       [tabindex]:not([tabindex="-1"]), [contenteditable="true"]):focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
:where(main, [tabindex="-1"]):focus { outline: none; }

/* ===== Tokyo Night — the default palette, and why it lives HERE =====
   Every other theme is a scoped-override stylesheet that tg-store.js loads on
   demand, which is right for a palette most visitors never see. It is wrong
   for the DEFAULT one: tokens.css is parsed before anything paints, so the
   page comes up in the :root palette below (Forest) and only turns Tokyo Night
   when a second file arrives — a visible flash on every first visit, reported
   2026-09-05.

   A default that costs a request is a default that flashes. So Tokyo Night's
   palette and its handful of literal-colour spots ride in this file, which is
   already on the critical path, and tg-store.js loads no stylesheet for it.
   The class is still applied the same way, so nothing else changes; if Tokyo
   Night ever stops being the default, this block moves back out to its own
   file and the roster gets its `file` back. */
html.theme-tokyonight {
    --bg-0: #1a1b26;          /* tokyo midnight */
    --bg-1: #24283b;          /* storm panels */
    --ink: #c0caf5;           /* neon-sign periwinkle white */
    --muted: #9aa5ce;         /* streetlight slate */
    --accent: #7aa2f7;        /* signal blue — the one accent on duty (TG-282) */
    --c-fuel: #ff9e64;        /* Fueling — lantern orange */
    --gold: #e0af68;          /* AI coach — Capra gradient, brass */
    --c-pace: #7aa2f7;        /* Pacing — signal blue */
    --c-crew: #9ece6a;        /* Crew — vending-machine green */
    --c-course: #0db9d7;      /* Course — neon cyan */
    --c-gear: #bb9af7;        /* Gear — arcade violet */
    /* The scheme's two purples sit 1° apart (KRI-119 would call them the same
       card twice), so Weather takes a pink-shifted dusk neon instead — the
       same separation move Emerald made for --c-aid. */
    --c-weather: #d98ae0;     /* Weather — dusk neon */
    --c-climb: #f7768e;       /* Climbs — vermilion sign */
    --c-aid: #7dcfff;         /* Aid stations + descents — pale sky glass */
    --ok: #9ece6a;            /* Status — vending-machine green */
    --warn: #e0af68;          /* Status — brass */
    --bad: #f7768e;           /* Status — vermilion sign */
}

/* --- Literal-colour spots that don't read the tokens (home.css) --- */
/* .grad / .eyebrow / .btn-primary already read the tokens — signal-blue hero for free. */
/* Backdrop tints → neon cyan + arcade violet over the indigo ground */
html.theme-tokyonight .backdrop {
    background:
        radial-gradient(1200px 600px at 70% -10%, rgba(13, 185, 215, 0.10), transparent 60%),
        radial-gradient(900px 500px at 10% 10%, rgba(187, 154, 247, 0.08), transparent 55%),
        linear-gradient(180deg, var(--bg-0), var(--bg-1));
}
html.theme-tokyonight .aurora {
    background: conic-gradient(from 180deg at 50% 50%, transparent, rgba(122, 162, 247, 0.07), transparent 40%);
}
/* Goat glow → signal blue, and stop the LED colour-cycle (it hardcodes old brand hues) */
html.theme-tokyonight .goat {
    filter: drop-shadow(0 24px 36px rgba(0, 0, 0, 0.55)) drop-shadow(0 0 10px rgba(122, 162, 247, 0.45));
    animation: bob 3.2s ease-in-out infinite;
}
/* Closing CTA band glow → violet neon */
html.theme-tokyonight .cta-band {
    background-image: radial-gradient(600px 200px at 50% -20%, rgba(187, 154, 247, 0.12), transparent 70%);
}
/* Hero route SVG gradient stops → cyan → signal blue → arcade violet */
html.theme-tokyonight #hr-grad stop:nth-of-type(1) { stop-color: #0db9d7; }
html.theme-tokyonight #hr-grad stop:nth-of-type(2) { stop-color: #7aa2f7; }
html.theme-tokyonight #hr-grad stop:nth-of-type(3) { stop-color: #bb9af7; }

/* /print.css */
/* TrailGoat — the print engine's document styles (see print.js).
 *
 * #print-doc is a clean, light, data-first "roadbook" built at print time from
 * the live plan. On screen it stays hidden; during print it is the ONLY thing
 * shown. Pagination belongs to the browser: rows never split (break-inside),
 * table headers repeat per page (table-header-group), and each major part
 * starts on its own page. No screenshots, no dark ink slabs, no mid-row cuts.
 *
 * body.tg-print-preview shows the document on screen for debugging/QA. */

#print-doc { display: none; }

/* ---- The paper floor ----

   The palette this file reads is FETCHED now: print.js applies
   `theme-firstlight` and firstlight.css is lazy-loaded. `themeCssReady` caps
   its wait at 1500 ms so a stylesheet that never arrives cannot hold a print
   dialog open — which means a print CAN start with the class on the root and
   no rules behind it, and then every token falls through to tokens.css's dark
   `:root`. `--ink` there is #eaf4ee: white ink on the white ground below,
   printing blank.

   So the ground and the ink get a floor that owes nothing to any stylesheet.
   Only those — the accents stay the theme's to own, because a wrong accent is
   a blemish and wrong ink is a blank page. `html.theme-firstlight` is more
   specific than `:root`, so the real palette overrides this the instant it
   lands, whatever the load order.

   Scoped to `@media print` so it cannot touch a screen: on screen the reader's
   own theme is the whole point. The QA preview is the one screen surface that
   shows this document, and it goes through `TrailGoatPrint.preview()`, which
   applies paper mode properly and awaits it. ---- */
@media print {
    :root {
        --ink: #15201b;           /* First Light's ink, literally */
        --ink-bright: #000000;
        --muted: #5b6864;
        /* The grounds are plain white, not First Light's #f5f7f6: paper IS
           white, its near-white page tint is a screen nicety, and repeating a
           theme's ground hex in a page file is what the roster guard in
           test_theme_roster.py exists to catch. The INK is the theme's exactly,
           and a test holds it there. */
        --bg-0: #ffffff; --bg-1: #ffffff; --bg-2: #ffffff;
    }
}

/* ---- the document itself (shared by print and the on-screen preview) ---- */
#print-doc {
    background: #fff; color: var(--ink);
    font-family: var(--body);
    font-size: 10.5pt; line-height: 1.45;
}
#print-doc .pd-head { margin-bottom: 10pt; }
#print-doc h1 {
    font-family: var(--display); font-weight: 800;
    font-size: 20pt; margin: 0 0 2pt; color: var(--ink); letter-spacing: -0.01em;
}
#print-doc .pd-meta { color: var(--muted); font-size: 10pt; margin: 0; }
#print-doc .pd-meta strong { color: var(--ink); }
#print-doc .pd-brandline {
    display: flex; justify-content: space-between; align-items: baseline;
    border-bottom: 2.5pt solid var(--c-fuel); padding-bottom: 6pt; margin-bottom: 10pt;
}
#print-doc .pd-brand { font-family: var(--display); font-weight: 800; font-size: 10pt;
    color: var(--c-fuel); letter-spacing: 0.08em; }

#print-doc h2 {
    font-family: var(--display); font-weight: 700; font-size: 12.5pt;
    color: var(--accent); margin: 14pt 0 6pt; break-after: avoid;
}
#print-doc .pd-sub { color: var(--muted); font-size: 9pt; margin: -4pt 0 6pt; }

/* Metric strip: per-hour + totals as a compact row of boxes. */
#print-doc .pd-metrics { display: flex; gap: 8pt; margin: 6pt 0 2pt; break-inside: avoid; }
#print-doc .pd-metric {
    flex: 1; border: 1pt solid #d8ded9; border-radius: 6pt; padding: 5pt 8pt;
}
#print-doc .pd-metric .l { font-size: 7.5pt; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
#print-doc .pd-metric .v { font-family: var(--mono); font-weight: 700; font-size: 11pt; }
#print-doc .pd-metric .v small { font-weight: 400; font-size: 8pt; color: var(--muted); }

/* Tables — cloned from the live plan; restyle for paper. */
#print-doc table { width: 100%; border-collapse: collapse; font-size: 9.5pt; }
#print-doc thead { display: table-header-group; }   /* header repeats on every page */
#print-doc th {
    text-align: left; font-size: 7.5pt; text-transform: uppercase; letter-spacing: 0.06em;
    color: var(--muted); border-bottom: 1.5pt solid var(--ink); padding: 3pt 6pt;
}
#print-doc td { padding: 4pt 6pt; border-bottom: 0.75pt solid #dfe5e0; vertical-align: top; }
#print-doc tr { break-inside: avoid; }              /* a row never splits across pages */
#print-doc tbody tr:nth-child(even) td { background: #f4f6f4; }
/* Neutralise site colour classes that assume a dark ground. */
#print-doc .t-up, #print-doc .t-down, #print-doc .t-pace, #print-doc .t-sep, #print-doc .t-flat,
#print-doc .aid-badge { color: inherit !important; background: none !important; }

/* Elevation profile snapshot. */
#print-doc .pd-profile { width: 100%; border: 1pt solid #d8ded9; border-radius: 6pt; margin: 4pt 0; }

/* Checklists — the reason paper exists. */
#print-doc ul.pd-check { list-style: none; margin: 4pt 0; padding: 0;
    columns: 2; column-gap: 18pt; }
#print-doc ul.pd-check li { padding: 2pt 0 2pt 16pt; position: relative; break-inside: avoid; }
#print-doc ul.pd-check li::before {
    content: ''; position: absolute; left: 0; top: 3.5pt;
    width: 8pt; height: 8pt; border: 1.1pt solid var(--ink); border-radius: 1.5pt;
}
#print-doc .pd-note { color: var(--muted); font-size: 9pt; }

/* Major parts start on a fresh page. */
#print-doc .pd-page { break-before: page; }

/* Repeating footer: fixed repeats per printed page. */
#print-doc .pd-foot {
    position: fixed; bottom: 0; left: 0; right: 0;
    text-align: center; font-size: 7.5pt; color: #98a39c;
}

/* ---- switching ---- */
@page { margin: 14mm 12mm 18mm; }
@media print {
    body.tg-printing > *:not(#print-doc) { display: none !important; }
    body.tg-printing #print-doc { display: block; }
    body.tg-printing { background: #fff !important; height: auto !important;
        overflow: visible !important; display: block !important; }
}

/* On-screen preview for QA: same document, scrollable overlay. Screen only:
   a fixed, viewport-tall, overflow:auto box printed as ONE page — anything
   past the first sheet was clipped — whenever the preview was still on when
   the print dialog opened (the crew sheet hit the same pinning). */
@media screen {
    body.tg-print-preview #print-doc {
        display: block; position: fixed; inset: 0; z-index: 99999;
        overflow: auto; padding: 32px clamp(24px, 12vw, 220px);
    }
}

/* OSM surface legend under the printed elevation profile (KRI-38) */
.pd-surf-legend { font-size: 9px; color: #555; margin: 2px 0 0; }
.pd-surf-legend span { display: inline-block; width: 14px; height: 7px; border-radius: 2px; vertical-align: middle; }

/* ---- Accent design system (KRI-122), on First Light's palette (TG-347).

        This file used to carry its own `--p-*` copy of those hues, and it had
        already drifted from the theme it was copied from — orange #d95f10
        against #d9580d, aqua #0f7fbe against #1180bd. Now `print.js` applies
        `theme-firstlight` for the length of the print pass, so every token
        below resolves to the one palette the site already ships for a white
        ground, and there is nothing left to keep in step by hand.

        White ground stays (browsers strip full dark backgrounds when printing,
        and ink is finite). print-color-adjust keeping a background is not
        guaranteed with "background graphics" off, so colour lives in
        borders/text/small tiles wherever possible. ---- */
#print-doc h2.pd-h {
    display: flex; align-items: center; gap: 6pt;
    padding: 4pt 8pt 4pt 6pt; border-radius: 5pt;
    border-left: 3pt solid var(--acc, var(--accent));
    background: color-mix(in srgb, var(--acc, var(--accent)) 9%, #fff);
    color: var(--ink);
    print-color-adjust: exact; -webkit-print-color-adjust: exact;
}
#print-doc .pd-ico {
    flex: 0 0 auto; width: 15pt; height: 15pt; border-radius: 4pt;
    display: inline-grid; place-items: center; background: var(--acc, var(--accent));
    print-color-adjust: exact; -webkit-print-color-adjust: exact;
}
#print-doc .pd-ico svg { width: 9.5pt; height: 9.5pt; fill: none; stroke: #fff;
    stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* Aid rows: coloured badge + who & what waits there (bags, crew, pacers). */
#print-doc .pd-abadge {
    display: inline-grid; place-items: center; width: 11pt; height: 11pt; border-radius: 50%;
    margin-right: 4pt; font: 700 6.5pt var(--display); color: #fff;
    background: var(--pc, var(--c-aid)); vertical-align: -2pt;
    print-color-adjust: exact; -webkit-print-color-adjust: exact;
}
#print-doc .pd-bag { display: inline-flex; align-items: center; gap: 1.5pt; margin-left: 5pt;
    color: var(--gold); vertical-align: -1.5pt; }
#print-doc .pd-bag svg { width: 10pt; height: 10pt; fill: none; stroke: currentColor;
    stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
#print-doc .pd-bag i { font-style: normal; font-size: 7pt; font-weight: 700; }
#print-doc .pd-pp {
    display: inline-grid; place-items: center; min-width: 11pt; height: 11pt; border-radius: 99pt;
    padding: 0 3pt; margin-left: 4pt; font: 700 6.5pt var(--display); color: #fff;
    background: var(--pc, var(--c-crew)); vertical-align: -2pt;
    print-color-adjust: exact; -webkit-print-color-adjust: exact;
}
#print-doc .pd-io {
    display: inline-block; margin-left: 4pt; font-size: 7pt; font-weight: 700;
    color: var(--pc, var(--c-crew)); border: 0.9pt solid currentColor; border-radius: 99pt;
    padding: 0.5pt 4.5pt; white-space: nowrap;
    print-color-adjust: exact; -webkit-print-color-adjust: exact;
}
/* Driving hand-offs carry a van glyph inside the same pill (KRI-127). */
#print-doc .pd-van { width: 8pt; height: 8pt; fill: none; stroke: currentColor; stroke-width: 1.8;
    stroke-linecap: round; stroke-linejoin: round; vertical-align: -1pt; margin-right: 1.5pt; }
#print-doc td.pd-c-water { color: var(--c-course); font-weight: 600; }
#print-doc td.pd-c-carb { color: var(--gold); font-weight: 600; }

/* Metric tiles wear their planner accents. */
#print-doc .pd-metric { border-top: 2.5pt solid var(--macc, #d8ded9);
    print-color-adjust: exact; -webkit-print-color-adjust: exact; }
#print-doc .pd-m-water { --macc: var(--c-course); }
#print-doc .pd-m-sodium { --macc: var(--c-gear); }
#print-doc .pd-m-carbs { --macc: var(--gold); }
#print-doc .pd-m-cals { --macc: var(--c-fuel); }

/* Crew person cards — colour dot, role pill, contacts on one line. */
#print-doc .pd-person {
    border: 1pt solid #dfe5e0; border-left: 3pt solid var(--pc, var(--c-crew));
    border-radius: 6pt; padding: 5pt 8pt; margin: 4pt 0; break-inside: avoid;
    print-color-adjust: exact; -webkit-print-color-adjust: exact;
}
#print-doc .pd-person b { font-family: var(--display); }
#print-doc .pd-role {
    display: inline-block; margin-left: 4pt; font-size: 6.5pt; font-weight: 700;
    letter-spacing: 0.08em; text-transform: uppercase; color: var(--pc, var(--c-crew));
    border: 0.9pt solid currentColor; border-radius: 99pt; padding: 1pt 5pt;
    vertical-align: 1pt;
}
#print-doc .pd-person .pd-note { margin: 1pt 0 0; }

/* ---- Course map (KRI-116) ---- */
#print-doc .pd-map { width: 100%; border: 1pt solid #d8dfd8; border-radius: 6pt;
    margin: 10pt 0 3pt; break-inside: avoid; }
#print-doc .pd-map-legend { color: var(--muted); font-size: 8.5pt; margin: 0 0 10pt; }
#print-doc .pd-dot { display: inline-block; width: 8pt; height: 8pt; border-radius: 50%;
    border: 1pt solid var(--ink); vertical-align: -1pt; }

/* ---- Section-picker wizard (screen only — the print rules never see it,
        and .tg-printing hides everything but #print-doc anyway) ---- */
@media screen {
    .pw-box .pw-opts { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; margin-top: 4px; }
    .pw-opt { display: flex; gap: 10px; align-items: center; background: var(--glass);
        border: 1px solid var(--line); border-radius: 10px; padding: 11px 13px;
        cursor: pointer; color: var(--ink); font-size: 0.9rem;
        transition: border-color 0.18s ease; }
    .pw-opt:hover { border-color: var(--edge-soft); background: var(--fill-hover); }
    .pw-opt input { accent-color: var(--accent); width: 16px; height: 16px; flex-shrink: 0; }
    .pw-opt .pw-empty { display: none; margin-left: auto; color: var(--muted);
        font-size: 0.72rem; font-style: italic; }
    .pw-opt.off { opacity: 0.55; cursor: default; }
    .pw-opt.off:hover { border-color: var(--line); }
    .pw-opt.off .pw-empty { display: inline; }
    #pw-backdrop[hidden] { display: none; }
    @media (max-width: 560px) { .pw-box .pw-opts { grid-template-columns: 1fr; } }
}

/* ===== Pace band (wrist strip) — two copies side by side, scissors-ready ===== */
.pd-band-pair { display: flex; gap: 10mm; break-inside: avoid; page-break-inside: avoid; margin-top: 8mm; }
.pd-band { width: 62mm; border: 1.2px dashed #9aa7a0; border-radius: 2mm; padding: 3mm 3.5mm;
    font-size: 8.2pt; line-height: 1.25; color: var(--ink); }
.pd-band-head { font-weight: 700; font-size: 8.6pt; letter-spacing: 0.01em; margin-bottom: 1.6mm;
    display: flex; justify-content: space-between; gap: 2mm; align-items: baseline; }
.pd-band-head span { font-weight: 600; color: var(--muted); font-size: 7.6pt; white-space: nowrap; }
.pd-band table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.pd-band th { text-align: left; font-size: 6.8pt; text-transform: uppercase; letter-spacing: 0.06em;
    color: var(--muted); padding: 0 1mm 0.6mm 0; border-bottom: 0.6px solid #c9d2cc; }
.pd-band td { padding: 0.55mm 1mm 0.55mm 0; border-bottom: 0.4px solid #e2e8e4; white-space: nowrap; }
.pd-band-name { max-width: 24mm; overflow: hidden; text-overflow: ellipsis; }
.pd-band-foot { margin-top: 1.6mm; font-size: 6.6pt; color: #8a978f; text-align: right; }
.pd-band-note { margin-top: 3mm; }
/* The strip's own size has to be stated for the TABLE, not just the wrapper.
   `#print-doc table { font-size: 9.5pt }` above outranks `.pd-band` by an ID,
   so until TG-349 the band's rows printed at the roadbook's 9.5 pt and its
   declared 8.2 pt reached nothing — which is why a 62 mm strip overflowed. */
#print-doc .pd-band table { font-size: 8.2pt; }
#print-doc .pd-band-tight table { font-size: 7pt; }
/* 7 pt is the smaller of AC-5's two sizes. The strip drops to it for either
   reason it runs out of room: more than 24 rows, or a departure column, whose
   "9:30 AM +1d" values are the widest thing the band ever prints.
   Past 40 rows the band starts a second pair instead of shrinking further —
   7 pt is the floor at which a number is readable on a wrist in the dark.
   The widths this is answering are measured below, once, in one place. */
.pd-band-tight { font-size: 7pt; }
.pd-band-tight th { font-size: 6.2pt; }
.pd-band-tight td { padding: 0.4mm 1mm 0.4mm 0; }
.pd-band-tight .pd-band-head { font-size: 7.6pt; }
/* The 62 mm is a fixed measure, not a starting point: two strips and their
   gap must not be squeezed by a narrow screen in the QA preview. */
.pd-band { box-sizing: border-box; flex: 0 0 62mm; }
/* The one place this deviates from AC-5, and the measurement behind it.

   AC-5 asks for two copies SIDE BY SIDE in 62 mm strips. AC-3 adds a departure
   column beside arrive and cutoff. For a plan whose arrivals are clock times
   those cannot both hold.

   METHOD, because a bare number here is worth nothing to whoever reads this
   after the next font change. Each cell's NATURAL width is measured by copying
   its computed `font`, `letter-spacing` and `text-transform` onto an absolutely
   positioned `white-space: nowrap` probe span and reading that span's box. The
   obvious approach — `Range.getBoundingClientRect()` over the cell's contents —
   is wrong here and was wrong in an earlier revision of this comment: once a
   cell is narrower than its text, a Range reports the width the text was
   ALLOWED, not the width it wanted, so every column measures as fitting.

   Measured that way, at 7 pt, on the crew sheet's own five-column band:

       name    "Deep Canyon"    25.7 mm      at      "125.0"          10.0 mm
       arrive  "10:00 AM +3d"   26.7 mm      depart  "9:30 AM +1d"    23.6 mm
       cutoff  "10:00 AM"       18.2 mm

   plus 2.1 mm of cell padding each: 114.8 mm of table. A 62 mm strip offers
   55 mm inside its 3.5 mm padding, so one strip needs more than twice the room
   it has, and a side-by-side pair would need about 250 mm against the 190 mm
   the page gives it. Shrinking does not rescue it — the pair only fits under
   about 5 pt, which is not a size anybody reads off a wrist at 3 am.

   So a band carrying a departure column keeps both copies and gives up only
   their ARRANGEMENT: the pair stacks, each strip is 124 mm (clearing the
   114.8 mm above), and every time prints in full. You cut two strips off one
   sheet instead of side by side.

   The trigger is the DEPARTURE column, not five columns as such: a band with
   name · at · arrive · depart and no cutoffs stacks too. That is broader than
   the arithmetic above strictly demands and is deliberate — it errs toward the
   readable size rather than toward the boundary. Bands with no departure
   column are untouched: 62 mm, side by side, 8.2 pt. */
.pd-band-pair-stack { flex-direction: column; gap: 6mm; }
.pd-band-wide { flex-basis: auto; width: 124mm; max-width: 100%; }
/* The band printed on its own (AC-1): no roadbook header or footer above it,
   so the first pair should not sit under their absent margin. */
.pd-band-only .pd-band-pair:first-child { margin-top: 0; }
.pd-band-only .pd-band-pair + .pd-band-pair { margin-top: 10mm; }
@media screen { /* preview mode parity: the strips show on the QA preview too */
    body.tg-print-preview .pd-band { background: #fff; }
}

/* ===== The pace band preview (export previews, print.js openBandPreview) =====
   Lives beside the band's own rules: the same paper greys print.css draws the
   strip with. */
/* One copy of the strip exactly as print.js draws it, on a paper
   card. Paper is white in both themes — it is the sheet, not the page — so
   this is the one surface here that does not follow the theme's ground. */
.pb-paper { margin: 14px 0 4px; padding: 18px; background: #fff; color: #1a211d;
    display: flex; flex-direction: column; align-items: center; max-height: 58vh; overflow: auto;
    border: 1px solid var(--line); }
.pb-paper .pd-band { margin: 0; color: inherit; }
.pb-paper .pd-band * { color: inherit; }
.pb-paper .pd-band table { font-size: 8.2pt; }
.pb-paper .pd-band-tight table { font-size: 7pt; }
.pb-paper .pd-band-head span, .pb-paper .pd-band th, .pb-paper .pd-band-foot { color: #5b6860; }
.pb-more { margin: 8px 0 0; font-size: 0.78rem; color: #5b6860; }

/* /launch-beta.css */
/* The launch offer extends the shared shell, palette and typography. */
.tg-launch-note { font: 400 .88rem/1.55 var(--body); color: var(--ink); background: var(--bg-1); border: 1px solid var(--line); border-radius: var(--r-card); padding: 12px 16px; margin: 12px 0; }
.tg-launch-note a { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }
.tg-beta-label { display: none; }
html[data-launch-beta="true"] .tg-beta-label,
html[data-launch-beta="true"] .tg-plan-offline::after { display: inline-block; font: 500 var(--mono-cap)/1.3 var(--mono); text-transform: uppercase; letter-spacing: .05em; color: var(--muted); border: 1px solid var(--edge-soft); border-radius: var(--r-ctl); padding: 2px 5px; margin-left: 6px; }
html[data-launch-beta="true"] .tg-plan-offline::after { content: "Beta"; }
.tg-beta-pricing .pr-grid { margin-top: 24px; }
.tg-beta-pricing .pr-card { background: var(--bg-1); }
.tg-beta-pricing .export-btn { min-height: 44px; }
.tg-beta-pricing .info-tldr { margin: 24px 0; }
.tg-beta-pricing > .info-card { margin-top: 24px; padding: 22px; background: var(--bg-1); border: 1px solid var(--line); border-radius: var(--r-card); }
@media print { .tg-launch-note, .tg-beta-label { display: none !important; } }

html[data-launch-beta="true"] .wordmark .beta-pill { font: 500 var(--mono-cap)/1.3 var(--mono); text-transform: uppercase; letter-spacing: .04em; color: var(--muted); border: 1px solid var(--edge-soft); border-radius: var(--r-ctl); padding: 3px 5px; margin-left: 8px; }

/* Pricing during launch: every price shown, each paid card saying it's free
   until the launch window closes. The line is the accent — it is the offer —
   and sits under the price it qualifies, never in place of it. */
.tg-beta-pricing .pr-launch { font: 600 .84rem/1.4 var(--body); color: var(--accent); margin: -2px 0 12px; }
.tg-beta-pricing .pr-crew-note { color: var(--muted); font-size: .92rem; line-height: 1.5; margin: 14px 2px 0; }
.tg-beta-pricing .pr-dayblock .pr-day { margin-top: 14px; }

