/* ══════════════════════════════════════════════════════════════════
   CAIRN — the shared token layer.

   GENERATED FILE. Do not edit. Every value here is copied verbatim
   from the CAIRN:TOKENS region of index.html by scripts/prepush.js,
   which runs on every push. An edit made here is an edit that will
   be silently reverted.

   Linked by plus.html and landing.html. index.html keeps its own
   inline copy on purpose: a render-blocking stylesheet before first
   paint is exactly the green flash the theme boot script exists to
   prevent.
   ────────────────────────────────────────────────────────────────── */
/* ▼▼▼ CAIRN:TOKENS:START ▼▼▼ ─────────────────────────────────────────
   THE SHARED LAYER. Everything down to CAIRN:TOKENS:END is copied
   verbatim by scripts/prepush.js into:
       cairn.css       linked by plus.html and landing.html
       offline.html    inlined, because the page whose whole job is to
                       work with no network cannot depend on a request
   This is the only place any of it is edited. Nothing below the END
   marker is shared, and nothing above it belongs to a component.
   ──────────────────────────────────────────────────────────────────── */
:root {
  --g0: #0C1F15;
  --g1: #132B1C;
  --g2: #1E3D2A;
  --o:  #E8481C; --ot:  #F65E32;
  --w:  #FFFFFF;
  --w5: rgba(255,255,255,0.6);
  --w2: rgba(255,255,255,0.18);
  --w1: rgba(255,255,255,0.07);
  --line: rgba(232,72,28,0.55);
  /* Safe area insets for notch/home-indicator devices */
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bot: env(safe-area-inset-bottom, 0px);
  --top-pad: max(52px, calc(44px + var(--safe-top)));

  /* ══════════════════════════════════════════════════════════════════
     CAIRN — Campgrounder's design system.  Added Sept 2, 2026.
     Two layers. Primitives hold raw values; semantic tokens name a JOB.
     Components reference ONLY the semantic layer, so a new theme is
     ~24 overrides instead of 900 edits.
     Themes: NIGHTFALL (below, the default) and DAYLIGHT (data-theme).
     ────────────────────────────────────────────────────────────────── */

  /* ── L1 PRIMITIVES ── raw brand values. Rarely referenced directly. */
  --p-green-900:#0C1F15;  --p-green-800:#132B1C;  --p-green-700:#1E3D2A;
  --p-green-950:#0A1A12;  --p-green-975:#071309;
  --p-orange:#E8481C;     --p-orange-lift:#F65E32;
  --p-orange-press:#D03C12; --p-orange-deep:#C4380F;
  --p-white:#FFFFFF;      --p-ink:#141813;
  --p-dyneema:#EFEFEB;    --p-ripstop:#DBDFD8;    --p-hardware:#171A15;
  --p-ok:#5EC26A;         --p-warn:#E8C21C;       --p-star:#E8C21C;
  --p-danger:#B00000;     --p-info:#3FA9F5;

  /* ── L2 SEMANTIC ── what components reference. Themes override THESE. */

  /* ink — 46 drifted alphas collapsed to 5 steps */
  /* Native chrome: date pickers, caret, autofill, scrollbars. Inherits
     from :root, so it is declared once and never per control. */
  --color-scheme:dark;
  color-scheme: var(--color-scheme);   /* :root is html: define and apply in one place */
  --text-1:#FFFFFF;
  --text-2:rgba(255,255,255,0.75);
  --text-3:rgba(255,255,255,0.62);
  --text-4:rgba(255,255,255,0.525);
  --text-5:rgba(255,255,255,0.37);
  --text-strong:rgba(255,255,255,0.88);  /* heading that is deliberately not pure white */
  --text-ghost:rgba(255,255,255,0.20);   /* watermark and placeholder ink */
  --text-accent:#F65E32;
  --text-on-accent:#FFFFFF;
  /* ── ON-DARK ── the THIRD ink context, and the one Cairn named but
     never built. There are three grounds in this app: a themed surface,
     the orange accent, and something that does not flip at all — a
     photograph, a toast, a device mockup, a scrim, the Trail. The first
     two had a full ramp. The third had exactly two tokens, so anything
     needing a MUTED on-dark ink, a hairline or a veil reached into the
     THEMED ramp, which is correct right up until a second theme exists
     and then it is dark ink on a dark ground.
     These are the Nightfall rungs, frozen. Never overridden in Daylight.
     They are applied by scope, not by component: see THE ON-DARK SCOPE
     below. An invariant surface needs invariant ink, and ink inherits. */
  --text-on-dark:#FFFFFF;                     /* = --text-1 */
  --text-strong-on-dark:rgba(255,255,255,0.88);
  --text-2-on-dark:rgba(255,255,255,0.75);
  --text-3-on-dark:rgba(255,255,255,0.62);
  --text-4-on-dark:rgba(255,255,255,0.525);
  --text-5-on-dark:rgba(255,255,255,0.37);
  --text-ghost-on-dark:rgba(255,255,255,0.20);
  --text-accent-on-dark:#F65E32;              /* the lifted orange, which Daylight darkens to #A62D0B */
  --edge-on-dark:rgba(232,72,28,0.9);         /* the edge that goes WITH --text-on-dark */
  --edge-hair-on-dark:rgba(255,255,255,0.09);
  --edge-rule-on-dark:rgba(255,255,255,0.13);
  --edge-strong-on-dark:rgba(255,255,255,0.18);
  --edge-control-on-dark:rgba(255,255,255,0.37);
  --edge-heavy-on-dark:rgba(255,255,255,0.45);
  --edge-accent-on-dark:rgba(232,72,28,0.45);
  --edge-accent-soft-on-dark:rgba(232,72,28,0.20);
  --edge-accent-mid-on-dark:rgba(232,72,28,0.60);
  --edge-accent-strong-on-dark:rgba(232,72,28,0.70);
  --edge-control-accent-on-dark:rgba(232,72,28,0.99);
  --line-on-dark:rgba(232,72,28,0.55);
  --veil-on-dark:rgba(255,255,255,0.07);
  --veil-faint-on-dark:rgba(255,255,255,0.03);
  --scrim-on-dark:rgba(8,18,12,0.62);

  /* grounds */
  --surface-0:#0C1F15;
  --surface-1:#132B1C;
  --surface-2:#1E3D2A;
  --surface-sunken:#0A1A12;
  --surface-tint-faint:rgba(232,72,28,0.05);
  --surface-tint:rgba(232,72,28,0.07);
  --surface-tint-mid:rgba(232,72,28,0.10);
  --surface-tint-strong:rgba(232,72,28,0.14);
  --surface-tint-bold:rgba(232,72,28,0.18);
  --surface-veil:rgba(255,255,255,0.07);
  --surface-veil-faint:rgba(255,255,255,0.03);
  --wash-ambient:rgba(30,61,42,0.55);      /* the atmospheric bloom on the marketing pages */
  --surface-scrim:rgba(8,18,12,0.62);
  --surface-glass:rgba(0,0,0,0.45);
  --scrim-modal:rgba(0,0,0,0.68);
  --glass-on-media:rgba(0,0,0,0.45);     /* glass over a PHOTO. Invariant, like --text-on-dark. */
  --surface-media:#132B1C;               /* the ground a photo sits ON, and what shows for the second
                                            before it arrives. Invariant, because the ink over it is. */
  --surface-invert:rgba(12,31,21,0.92);  /* deliberately dark in both themes */
  --scrim-tile-0:rgba(12,31,21,0);       /* the tile gradient, fading to the ground */
  --scrim-tile-1:rgba(12,31,21,1);
  --photo-tile-opacity:1;                /* how much of the tile photo comes through */
  --photo-tile-filter:none;              /* and how much of its colour */

  /* edges — 22 neutral + 24 orange alphas collapsed to 3 + 3 */
  --edge-hair:rgba(255,255,255,0.09);
  --edge-rule:rgba(255,255,255,0.13);
  --edge-strong:rgba(255,255,255,0.18);
  --edge-control:rgba(255,255,255,0.37);        /* 3.42:1 — the outline of something you can press */
  --edge-control-accent:rgba(232,72,28,0.99);   /* 4.33:1 — the same, in orange */
  /* THE FOCUS RING. Not an edge: an edge is a boundary you may or may not
     notice, a ring is the answer to "where am I", and it has a hard 3:1
     floor. Named separately so it can never be tuned for looks. */
  --focus-ring:#E8481C;                  /* 4.40:1 on the ground, 3.87:1 on a panel */
  --focus-ring-on-dark:#E8481C;          /* the same orange, frozen, for invariant surfaces */
  --focus-ring-on-accent:#FFFFFF;        /* a ring drawn INSIDE an orange fill. Orange on orange
                                            is 1.55:1; white on --accent-fill is 4.51:1. */
  --bw-focus:2px;                        /* one weight. Three rings were 1.5px and thirteen were 2px. */
  --edge-heavy:rgba(255,255,255,0.45);   /* a border meant to be seen */
  --edge-accent-soft:rgba(232,72,28,0.2);
  --edge-accent-mid:rgba(232,72,28,0.60);
  --edge-accent:rgba(232,72,28,0.45);
  --edge-accent-strong:rgba(232,72,28,0.70);

  /* status — named at last, after living unnamed in 29 rules */
  --ok:#5EC26A;   --ok-edge:rgba(94,194,106,0.35);  --ok-wash:rgba(94,194,106,0.06);
  --warn:#E8C21C; --warn-edge:rgba(232,194,28,0.35); --warn-wash:rgba(232,194,28,0.06);
  --star:#E8C21C;
  --src-dyrt:rgba(42,160,100,0.9);   /* The Dyrt green   */
  --src-campendium:rgba(28,155,160,0.9); /* Campendium teal */
  --src-google:rgba(220,70,60,0.9);  /* Google red       */
  --src-recgov:rgba(110,150,240,0.9); /* Recreation.gov blue. 3.65:1 */

  /* ── WEATHER GLYPHS ── the little forecast icons. Data-driven, so they
     lived in a JS object and never saw the theme. */
  --wx-sun:#F5C842;    --wx-partly:#C8B458; --wx-cloud:rgba(255,255,255,0.55);
  --wx-rain:#6BB5E8;   --wx-snow:#A8D8EA;   --wx-storm:#C86BB5;
  /* ── AIR QUALITY ── six levels, and the two that matter most were the
     two that could not be read. */
  --aqi-good:#4CA96A;      --aqi-moderate:#C9A21A;  --aqi-sensitive:#E8731C;
  --aqi-unhealthy:#E8481C; --aqi-bad:#CA85DB;       --aqi-hazard:#D38D8D;
  /* ── THE SUN ARC ── the track is already tokenised; the sun was not. */
  --sun-progress:rgba(245,175,75,0.98); --sun-mark:rgba(255,218,100,1);
  /* ── SIGNAL ── the connectivity ramp: none, poor, fair, good, excellent. */
  --sig-none:rgba(255,255,255,0.5); --sig-poor:#F0562A; --sig-fair:#F6763A;
  --sig-good:#E8C21C;               --sig-best:#5EC26A;
  --danger:#F26359;
  --info:#3FA9F5;

  /* interaction */
  --accent:#E8481C;
  --accent-fill:#D8400F;  /* the accent as a FILL under white text. 4.51:1. Invariant. */
  --accent-hover:#D03C12;
  --accent-ring:rgba(232,72,28,0.35);

  /* ── TYPE ── 53 sizes collapsed to 12. Half-pixels were drift. */
  --fs-3xs:8px;  --fs-2xs:9px;  --fs-xs:10px;  --fs-sm:11px;
  --fs-base:12px; --fs-md:13px;  --fs-lg:14px;  --fs-xl:15px;
  --fs-2xl:16px; --fs-3xl:17px; --fs-4xl:18px; --fs-h4:19px;
  --fs-h3b:20px; --fs-h3:22px;  --fs-h2:28px;  --fs-h2b:30px;
  --fs-h1:34px;  --fs-h1b:46px;

  --fw-light:300; --fw-regular:400; --fw-medium:500; --fw-semi:600;
  --fw-bold:700;  --fw-heavy:800;  --fw-black:900;

  /* 47 letter-spacings collapsed to 7. Eight pairs were the same value
     written two ways (0.18em and .18em). */
  /* TRACKING. The previous scale had seven word-named rungs and zero
     uses: 0.18em is used 35 times and had no rung to land on, so nobody
     could pick a name. Rebuilt from what the app actually sets. The
     number is the meaning: --ls-18 is 0.18em. Negatives tighten display
     type; positives space uppercase labels.                            */
  --ls-neg-5:-0.05em; --ls-neg-4:-0.04em; --ls-neg-3:-0.03em;
  --ls-neg-2:-0.02em; --ls-neg-1:-0.01em; --ls-0:0;
  --ls-1:0.01em;  --ls-2:0.02em;  --ls-3:0.03em;  --ls-4:0.04em;
  --ls-5:0.05em;  --ls-6:0.06em;  --ls-7:0.07em;  --ls-8:0.08em;
  --ls-9:0.09em;  --ls-10:0.1em;  --ls-12:0.12em; --ls-13:0.13em;
  --ls-14:0.14em; --ls-16:0.16em; --ls-18:0.18em; --ls-20:0.2em;
  --ls-22:0.22em; --ls-24:0.24em; --ls-26:0.26em; --ls-28:0.28em;

  --lh-flat:1; --lh-tight:1.15; --lh-snug:1.35; --lh-base:1.5; --lh-loose:1.65;

  --font-ui:"Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-mark:'Montserrat', "Helvetica Neue", Helvetica, Arial, sans-serif;

  /* ── SPACE ── 53 values on a 2px base. Covers ~90% of uses. */
  --sp-1:2px;  --sp-2:4px;  --sp-3:6px;  --sp-4:8px;  --sp-5:10px;
  --sp-6:12px; --sp-7:14px; --sp-8:16px; --sp-9:18px; --sp-10:20px;
  --sp-12:24px; --sp-14:28px; --sp-16:32px; --sp-20:40px; --sp-24:48px;

  /* ── LINES & RADII ── the app is squared by design. */
  --bw-hair:1px; --bw-rule:1.5px; --bw-accent:2.5px;
  --r-none:0; --r-xs:3px; --r-sm:8px; --r-md:12px;
  --r-pill:999px; --r-circle:50%;

  /* ── ELEVATION ─────────────────────────────────────────────────
     The whole stacking order of the app, in one readable list. Every
     band is named for what actually lives there, read off the app
     rather than invented, and the numbers preserve the exact order
     the app already had while collapsing the range from 99999 to
     1000. Reading down this list tells you what is in front of what.

     Bare z-index 0 to 6 is still allowed and is NOT a layer: those
     order children INSIDE one component (a hero photo under its tint
     under its gradient). If a value needs to clear anything outside
     its own component, it belongs here instead.                     */
  --z-base:0;
  --z-raised:         10;   /* the active screen, flyover chrome */
  --z-chrome:         20;   /* screen chrome pinned over content */
  --z-tip:            40;   /* coach tips */
  --z-tip-top:        50;   /* a tip that must clear another tip */
  --z-search:         200;  /* the search overlay */
  --z-overlay:        300;  /* trip card overlay */
  --z-overlay-cal:    320;  /* the calendar overlay */
  --z-overlay-map:    350;  /* the sitemap overlay */
  --z-sheet-scrim:    400;  /* sheet backdrops */
  --z-sheet:          401;  /* the sheet itself */
  --z-sheet-top:      410;  /* a sheet stacked on a sheet */
  --z-sheet-over:     460;  /* results sheet, above the stack */
  --z-map-chrome:     500;  /* map topbar, drawer, compass */
  --z-map-top:        600;  /* map bottom nav, flyover */
  --z-sitemap:        800;  /* the sitemap bar */
  --z-pill:           900;  /* the offline pill */
  --z-toast:          910;  /* toasts */
  --z-reveal:         920;  /* the patch reveal */
  --z-sheet-urgent:   930;  /* plus and radar sheets. See the note below. */
  --z-welcome:        1000; /* first run welcome */

  /* ── MOTION ── 43 durations. 0.15/0.16/0.18 were one value drifting. */
  --dur-instant:0.12s;   --dur-fast:0.16s;      --dur-base:0.22s;
  --dur-moderate:0.30s;  --dur-slow:0.45s;      --dur-deliberate:0.62s;
  --dur-slowest:0.90s;
  /* Four curves, by job, replacing twelve bespoke beziers used once each. */
  --ease-out:      cubic-bezier(0.22,1,0.36,1);
  --ease-settle:   cubic-bezier(0.34,0.02,0.2,1);
  --ease-spring:   cubic-bezier(0.2,1.5,0.4,1);
  --ease-glide:    cubic-bezier(0.4,0,0.2,1);
  /* The rhythm a sequence is built from. Already the app's own step:
     the category tiles enter at 0.07s apart. */
  --stagger:0.07s;
  /* A long list is not a sequence. Twenty results at 0.07s apart takes
     a second and a half; the results cascade has always run at 26ms and
     should keep its own, tighter step. */
  --stagger-tight:0.026s;
  /* Drawing a line is not a transition. The hero ridge traces itself. */
  --dur-draw:1.5s;

  /* ── SHADOW ── */
  --shadow-sheet:0 -12px 40px rgba(0,0,0,0.55);
  --shadow-pop:0 10px 28px rgba(0,0,0,0.40);
  --shadow-inset-hair:inset 0 0 0 1px rgba(255,255,255,0.07);

  /* ── WEAVE ── Daylight's ripstop. Off in Nightfall. */
  --weave-body:none;
  --weave-panel:none;
  --weave-header:none;
}
/* ══════════════════════════════════════════════════════════════════
   DAYLIGHT — the Dyneema technical white theme.
   Proof the two-layer split works: a whole second visual world in
   24 overrides, none of which touch a component rule.
   Dormant until <html data-theme="daylight"> is set.
   ────────────────────────────────────────────────────────────────── */
:root[data-theme="daylight"] {
  --color-scheme:light;
  --text-1:#141813;
  --text-2:rgba(20,24,19,0.78);
  --text-3:rgba(20,24,19,0.64);
  --text-4:rgba(20,24,19,0.64);
  --text-5:rgba(20,24,19,0.49);
  --text-strong:rgba(20,24,19,0.90);
  --text-ghost:rgba(20,24,19,0.22);
  --text-accent:#A62D0B;              /* 5.18:1 on the tightest panel */
  /* --text-on-accent stays #FFFFFF: white on an orange fill in both themes */

  --surface-0:#EFEFEB;
  --surface-1:#DBDFD8;
  --surface-2:#D2D7CE;
  --surface-sunken:#E4E7E1;
  --surface-tint-faint:rgba(232,72,28,0.045);
  --surface-tint:rgba(232,72,28,0.065);
  --surface-tint-mid:rgba(232,72,28,0.093);
  --surface-tint-strong:rgba(232,72,28,0.13);
  --surface-tint-bold:rgba(232,72,28,0.167);
  --surface-veil:rgba(20,24,19,0.035);
  --surface-veil-faint:rgba(20,24,19,0.02);
  --wash-ambient:transparent;              /* the weave carries the depth here; a green wash reads as cloud */
  --surface-scrim:rgba(239,239,235,0.86);
  --surface-glass:rgba(239,239,235,0.90);
  --scrim-modal:rgba(18,22,17,0.46);

  /* black webbing does the structural work orange cannot carry alone */
  --edge-hair:rgba(20,24,19,0.15);
  --edge-rule:#171A15;
  --edge-strong:#171A15;
  --edge-control:rgba(20,24,19,0.49);           /* 3.02:1 */
  --edge-control-accent:rgba(166,45,11,0.95);   /* 4.90:1 */
  --edge-heavy:rgba(20,24,19,0.52);
  --scrim-tile-0:rgba(239,239,235,0);    /* no photo to scrim, so no scrim */
  --scrim-tile-1:rgba(239,239,235,0);
  --photo-tile-opacity:0;                /* no photo. The ripstop carries the tile. */
  --photo-tile-filter:none;
  --edge-accent-soft:rgba(166,45,11,0.80);  /* 3.60:1 — brand orange tops out at 2.67:1 here */
  --edge-accent-mid:rgba(166,45,11,0.85);   /* 4.05:1 */
  --edge-accent:rgba(166,45,11,0.90);       /* 4.49:1 */
  --edge-accent-strong:rgba(166,45,11,0.95);/* 4.90:1 — --accent itself is only 2.67:1 here */
  --focus-ring:#A62D0B;               /* 6.07:1 on Dyneema, 5.18:1 on a panel, 4.78:1 on the raised one.
                                         #E8481C was 3.39:1 and 2.89:1 here, under the 3:1 floor. */

  --ok:#1E5F27;                       /* #5EC26A is 2.1:1 on Dyneema; #2E8B3A was still 2.95 on the darkest panel */
  --ok-edge:rgba(30,95,39,0.40);   --ok-wash:rgba(30,95,39,0.07);
  --warn:#7A5309;                     /* gold is invisible on light. 4.68:1 on every panel. */
  --warn-edge:rgba(138,109,8,0.40); --warn-wash:rgba(138,109,8,0.07);
  --star:#7A5309;                     /* brass. #B57A0D was 2.49:1 on the darkest panel. */
  --danger:#A31010;
  --info:#1B6FB0;

  /* review source marks. Same hues, readable values. Daylight only. */
  --src-dyrt:#1E7449;
  --src-campendium:#146E72;
  --src-google:#A8322A;
  --src-recgov:#2A4EA8;

  /* same hue, darkened until each clears 4.5:1 on --surface-2 */
  --wx-sun:#745906;    --wx-partly:#685B22; --wx-cloud:#5C5C5C;
  --wx-rain:#176194;   --wx-snow:#1E637D;   --wx-storm:#953782;
  --aqi-good:#2F6841;      --aqi-moderate:#6F590E;  --aqi-sensitive:#92470F;
  --aqi-unhealthy:#A93211; --aqi-bad:#8F31A5;       --aqi-hazard:#A63535;
  --sun-progress:#8A5B00; --sun-mark:#6E4A00;
  --sig-none:#5C5C5C; --sig-poor:#AC300C; --sig-fair:#A33907;
  --sig-good:#6D5B0B; --sig-best:#286930;

  --shadow-sheet:0 -12px 40px rgba(20,24,19,0.18);
  --shadow-pop:0 10px 28px rgba(20,24,19,0.14);
  --shadow-inset-hair:inset 0 0 0 1px rgba(20,24,19,0.10);

  /* the ripstop weave. Pure CSS, no image. */
  --weave-body:
    repeating-linear-gradient(0deg, rgba(20,24,19,0.042) 0 1px, transparent 1px 15px),
    repeating-linear-gradient(90deg, rgba(20,24,19,0.042) 0 1px, transparent 1px 15px),
    repeating-linear-gradient(0deg, rgba(20,24,19,0.016) 0 1px, transparent 1px 4px),
    repeating-linear-gradient(90deg, rgba(20,24,19,0.016) 0 1px, transparent 1px 4px);
  --weave-panel:
    repeating-linear-gradient(0deg, rgba(20,24,19,0.065) 0 1px, transparent 1px 10px),
    repeating-linear-gradient(90deg, rgba(20,24,19,0.065) 0 1px, transparent 1px 10px);
  /* A header is where the fabric is DOUBLED OVER: a tighter, slightly firmer
     weave than the body, the way a reinforced band reads on a real pack. Same
     ink, 10px pitch instead of 15, and no sub-grid, so at a glance it is a
     texture change rather than a second pattern. */
  --weave-header:
    repeating-linear-gradient(0deg, rgba(20,24,19,0.07) 0 1px, transparent 1px 10px),
    repeating-linear-gradient(90deg, rgba(20,24,19,0.07) 0 1px, transparent 1px 10px);

  /* ── LEGACY ALIASES, THEMED ──────────────────────────────
     These eight short names predate Cairn and still carry 247
     declarations. We are not retiring them here: their :root
     values are untouched, so Nightfall renders byte for byte
     as before. We are only teaching them what they mean in
     Daylight. Retiring them is a separate, deliberate pass.
     --o and --ot are absent on purpose: orange is the one
     thing that does not change between the two themes.       */
  --g0:  var(--surface-0);      /* page ground        (26) */
  --g1:  var(--surface-1);      /* panel              (37) */
  --g2:  var(--surface-2);      /* raised panel        (8) */
  --w:   var(--text-1);         /* primary ink        (60) */
  --w5:  var(--text-3);         /* secondary ink      (16) */
  --w2:  rgba(20,24,19,0.49);   /* strong edge (33). 3.02:1 — the black webbing, as designed. */
  --w1:  var(--surface-veil);   /* faint fill          (6) */
  --line: var(--edge-accent);   /* the orange rule    (75) */
}

/* ══════════════════════════════════════════════════════════════════
   THE ON-DARK SCOPE
   Every ground in the app that does NOT flip with the theme, listed
   once. Inside any of these the themed ink names resolve to their
   invariant twins, so a component that already says
       color: var(--text-3)
   is right on a photo and right on a panel without ever knowing which
   one it is standing on. Ink inherits, so this is set on the GROUND
   and never on the children, and it composes: a control shared
   between a dark topbar and a themed sheet needs no variant.

   Building a new surface that stays dark? Give it .on-dark, or add
   its selector here. Prepush check 15 fails the push if a dark ground
   is carrying themed ink, so a missed one cannot ship.

   Grounds only — NOT --g0/--g1/--g2. A ground is the surface's own
   business: .d-hero-grad fades a photo into the themed page below it,
   and freezing --g0 there would paint a dark band across Daylight.
   ══════════════════════════════════════════════════════════════════ */
/* CAIRN:ONDARK:SCOPE — prepush check 15 reads this selector list */
.on-dark,
#trail,                                    /* #050a07, a whole screen */
#patch-reveal,
.tc-title, .tc-note, .tc-close, .tc-btn-save, .tc-btn-share,  /* the chrome on the scrim. NOT .tc-card-wrap: that is a themed card sitting on it. */
#flyover-overlay,
.phone-body,                               /* the device mockups, here and on the marketing pages */
.plus-phone,
.mich-header.mich-hero,                    /* photo + scrim */
.featured-card,
.d-hero,
.d-moment-slide,
.saved-sat-thumb,
.map-topbar,
.sitemap-head,
.flyover-topbar, .flyover-bottombar, .flyover-badge,
.smap-chip, .smap-hint, .smap-plustag,
.trail-pin,
.trail-entry,                              /* linear-gradient(#0e1c17 …), inside #trail */
.patch-disc,                               /* the enamel disc, dark on the profile too */
.sm-chip, .sitemap-legend,                 /* the sitemap overlay chrome */
.sitemap-thumb,                            /* a CSS drawing, with svg shapes drawn ON it */
.compass-btn, .compass-top-btn, .compass-global, .compass-tip,
.map-filters .fchip, .map-filters .fchip-type, .map-filters .fchip-ctl,   /* the applied-filters bar floating over the map tiles */
.topbar-btn, .xbtn.dark-bg,
.th-tip, .th-scrim,
.kit-light-exit,                           /* the one dark control on a deliberately light page */
.offline-pill {
  /* Redefining the tokens is only half of it. A child that INHERITS its
     ink rather than declaring it never reads a token at all, so the ground
     has to establish the ink as well as the vocabulary. This one line is
     what carries .smap-plustag, the svg glyphs that stroke currentColor,
     and every future child that simply does not mention colour. */
  color: var(--text-on-dark);

  --text-1:        var(--text-on-dark);
  --text-2:        var(--text-2-on-dark);
  --text-3:        var(--text-3-on-dark);
  --text-4:        var(--text-4-on-dark);
  --text-5:        var(--text-5-on-dark);
  --text-strong:   var(--text-strong-on-dark);
  --text-ghost:    var(--text-ghost-on-dark);
  --text-accent:   var(--text-accent-on-dark);
  --edge-hair:     var(--edge-hair-on-dark);
  --edge-rule:     var(--edge-rule-on-dark);
  --edge-strong:   var(--edge-strong-on-dark);
  --edge-control:  var(--edge-control-on-dark);
  --edge-heavy:    var(--edge-heavy-on-dark);
  --edge-accent:   var(--edge-accent-on-dark);
  --focus-ring:    var(--focus-ring-on-dark);
  --edge-accent-soft:   var(--edge-accent-soft-on-dark);
  --edge-accent-mid:    var(--edge-accent-mid-on-dark);
  --edge-accent-strong: var(--edge-accent-strong-on-dark);
  --edge-control-accent:var(--edge-control-accent-on-dark);
  --surface-veil:      var(--veil-on-dark);
  --surface-veil-faint:var(--veil-faint-on-dark);
  --surface-scrim:     var(--scrim-on-dark);
  --surface-glass:     var(--glass-on-media);
  --color-scheme:  dark;          /* caret, scrollbars and pickers inside a dark surface */
  /* the eight legacy aliases get the same treatment, because 247
     declarations still say var(--w) and they are on these grounds too */
  --w:    var(--text-on-dark);
  --w5:   var(--text-3-on-dark);
  --w2:   var(--edge-strong-on-dark);
  --w1:   var(--veil-on-dark);
  --line: var(--line-on-dark);
}
/* ▲▲▲ CAIRN:TOKENS:END ▲▲▲ */
