/* ============================================================================
   CrewBase design tokens
   ----------------------------------------------------------------------------
   SCOPE: site chrome only — this file owns every colour on the marketing pages
   under site/. It does NOT move into the app: the app's own source is the
   three-tier src/styles/design-tokens.css, and ADR-0017 rules out a third token
   file. Identity is shared with the app; chrome may differ (T3, 2026-08-30).
   Within this scope: do not hardcode a hex anywhere else.

   Derived from brand/BRAND.md. The five rules that must not break:
     1. Violet #6D28D9 never changes between light and dark. Violet used as
        SMALL TEXT on a dark ground lifts to #B29BFF for readability.
     2. Hi-vis #F5A524 is a SURFACE, never ink. Chip with #16181D text on it.
        Live status and warnings only. #B45309 is explicitly rejected.
     3. Purple is the badge, not the paint. Under 10% of any screen.
     4. Straight white #FFFFFF in light mode. Not off-white.
     5. Graphite #16181D is the structural dark in BOTH modes.

   The marketing site runs LIGHT, broken up by two or three full-width GRAPHITE
   BANDS. That restores brand/BRAND.md line 57 and reverses the 2026-08-15
   "marketing site runs dark" call. The app still follows the user's own theme.
   Both sets are defined here, once each.

   HOW THE BANDS WORK. There is no second stylesheet and no duplicated palette.
   LIGHT is the default on :root. The DARK set below is re-declared on a handful
   of scopes, and .band is one of them — so a graphite band re-points
   ground/surface/line/ink/violet-ink/shadow at their dark values for everything
   inside it, and site.css (which reads every colour through var(--cb-*)) inverts
   itself. Change a dark value once here and the bands follow.
   ========================================================================== */

/* ============================================================================
   THE TYPEFACE — self-hosted, 2026-08-16. Was two connections to Google.
   ----------------------------------------------------------------------------
   Plus Jakarta Sans, SIL Open Font License 1.1, so self-hosting is permitted.
   The licence is at assets/fonts/OFL.txt. Keep it with the files.

   WHY IT MOVED OFF GOOGLE. The old markup did preconnect to two hosts, then
   waited on a stylesheet from one of them before it could even ask for a font
   file. Three round trips to somebody else's server before a headline paints.
   Self-hosted, the font comes off the same connection as the page.

   ONE FILE, ALL FOUR WEIGHTS. This is the VARIABLE font, hence
   `font-weight: 400 800` rather than four separate @font-face blocks. 400, 600,
   700 and 800 are all instances of the one 27KB file, and any weight between
   them is available for free if a design ever wants it.

   TWO SUBSETS, matching what Google served: latin covers everything this site
   writes, latin-ext is there so a name with an unusual accent does not fall
   back to a system font mid-word. The browser downloads latin-ext ONLY if a
   character in its range actually appears, which is what unicode-range is for.
   Do not delete the unicode-range lines to "simplify" it — that makes the
   browser fetch both files on every visit.

   font-display: swap — text paints immediately in the fallback and re-renders
   when the font lands. On a phone on site data, never make a crew wait on a
   font to read a page.
   ========================================================================== */
@font-face {
  font-family: 'Plus Jakarta Sans';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('../fonts/plus-jakarta-sans-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Plus Jakarta Sans';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('../fonts/plus-jakarta-sans-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  /* ---- Brand constants. Identical in every mode. ---- */
  --cb-violet:        #6D28D9;
  --cb-violet-hover:  #5B21B6;
  --cb-violet-lift:   #B29BFF;  /* violet as small text on dark ONLY */
  --cb-hivis:         #F5A524;  /* surface only, never ink */
  --cb-hivis-ink:     #16181D;  /* the only text colour allowed on hi-vis */

  /* Hi-vis has the same problem --cb-ink-3 had before 2026-08-15: ONE value that
     only works on one of the two grounds. #F5A524 was picked against graphite.
     Measured on the live page:

         #F5A524 on graphite #16181D        8.70:1  reads as a mark
         #F5A524 on the white card #F7F8FA  1.92:1  does not register at all

     So a warning mark on the LIGHT page needs a deeper value or it is decoration.
     This is that value, and it is derived from the two tokens above rather than
     invented, so it can never drift away from the brand amber:

         color-mix(70% --cb-hivis, --cb-graphite) = #B27B22
         #B27B22 on the white card #F7F8FA  3.44:1  clears the 3:1 a non-text
                                                    mark needs, with headroom

     ⛔ This is NOT #B45309, which BRAND.md rejects. That one is a red-brown
        (180,83,9). This is (178,123,34) — still the brand amber, just taken down
        against our own graphite.
     ⛔ Do NOT merge this with --cb-hivis, and do NOT use it inside a band. On
        graphite it measures 4.85:1 against the plain token's 8.70:1, so in a
        band it is strictly the worse mark. Each value belongs to one ground.
        Same rule, and the same reason, as the two values of --cb-ink-3 further
        down this file.
     ⛔ Still a SURFACE, never ink. Rule 2 above is unchanged. */
  --cb-hivis-deep:    color-mix(in srgb, var(--cb-hivis) 70%, var(--cb-graphite));
  --cb-graphite:      #16181D;  /* structural dark, both modes */
  --cb-white:         #FFFFFF;

  /* ---- Semantic status. Not brand colours. Use sparingly. ---- */
  --cb-good:          #34D399;
  --cb-bad:           #F87171;

  /* ---- Type ---- */
  --cb-font: 'Plus Jakarta Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;

  /* ---- Motion. In-app motion is 180-320ms, explains a change, never decorates. ---- */
  --cb-fast:   180ms;
  --cb-mid:    320ms;
  --cb-slow:   620ms;
  --cb-ease:   cubic-bezier(.22, .61, .36, 1);

  /* ---- Radius ---- */
  --cb-r-sm:  8px;
  --cb-r-md:  14px;
  --cb-r-lg:  22px;
  --cb-r-pill: 999px;

  /* ---- Spine. One vertical rhythm, used everywhere. ---- */
  --cb-gap-1: 8px;
  --cb-gap-2: 16px;
  --cb-gap-3: 24px;
  --cb-gap-4: 40px;
  --cb-gap-5: 64px;
  --cb-gap-6: 96px;
  --cb-gap-7: 140px;   /* the air above a headline. bar.md mechanism 7. */

  --cb-wrap: 1180px;   /* max content width */

  /* ---- The tap floor. design-system.md: "used with gloves on." ----
     One number, so the other 19 pages cannot drift off it. Anything a finger
     presses gets `min-height: var(--cb-tap)`. The ONE documented exception is a
     link inside a running sentence, where the words set the box and padding
     would steal taps from the line above. That exception is named in
     design-system.md and enforced by checks/prestart.py. */
  --cb-tap: 44px;
}

/* ============================================================================
   LIGHT — the marketing site's default ground, and the app's light mode.
   Only the GROUND changes. Violet, hi-vis, graphite, type and shapes all hold.
   ========================================================================== */
:root,
[data-theme="light"] {
  --cb-ground:      #FFFFFF;  /* straight white. rule 4. do not soften. */
  --cb-surface:     #F7F8FA;  /* raised card */
  --cb-surface-2:   #FFFFFF;  /* raised twice, for overlap layers */
  --cb-line:        #E3E6EC;  /* hairline borders */
  --cb-line-soft:   #EFF1F5;

  --cb-ink:         #16181D;  /* primary text */
  --cb-ink-2:       #4A5160;  /* secondary text */
  --cb-ink-3:       #6B7284;  /* muted, captions, labels */

  --cb-violet-ink:  var(--cb-violet);  /* on light, violet text stays violet */

  /* The faintest possible tint of the ink over the ground. Column headers,
     table gutters — anywhere a surface needs to read as "one step in" without
     becoming a second background colour. */
  --cb-wash:        rgba(16,18,22,.030);

  --cb-shadow-1: 0 1px 2px rgba(16,18,22,.06);
  --cb-shadow-2: 0 8px 24px -6px rgba(16,18,22,.10);
  --cb-shadow-3: 0 30px 70px -20px rgba(16,18,22,.16);
  --cb-glow:     0 0 0 1px rgba(109,40,217,.12), 0 20px 60px -22px rgba(109,40,217,.22);
}

/* ============================================================================
   DARK — the marketing site's graphite bands, and the app's dark mode.

   The three selectors, and why each is here:
     [data-theme="dark"]  the app in dark mode, and the whole marketing site if
                          anyone ever sets it on <html> again.
     .band                a full-width graphite band on the marketing site.
                          THIS is the inversion. Everything inside a band reads
                          these values instead of the light ones above.
     .nav.is-dark         the sticky nav while a band is passing behind it.

   The last two are marketing-site class names living in the app's token file on
   purpose: it is the only way to keep ONE definition of the dark palette. The
   app uses neither class, so they cost it nothing.
   ========================================================================== */
[data-theme="dark"],
.band,
.nav.is-dark {
  --cb-ground:      #0F1115;  /* the one ground tone. bar.md mechanism 1. */
  --cb-surface:     #161920;  /* raised card */
  --cb-surface-2:   #1D212B;  /* raised twice, for overlap layers */
  --cb-line:        #262B36;  /* hairline borders */
  --cb-line-soft:   #1C212B;

  --cb-ink:         #F2F4F8;  /* primary text */
  --cb-ink-2:       #9AA1B2;  /* secondary text */
  /* Muted was #6B7284 in BOTH modes until 2026-08-15. That value was chosen when
     the marketing site was all dark, and it never got a second value when the
     page went white. Measured on the live page:

         #6B7284 on the white page   4.81:1  passes
         #6B7284 on graphite         3.69:1  FAILS
         #6B7284 on a raised surface 3.35:1  FAILS

     Every other text token already had a value per ground. This was the only one
     declared identical for both, so muted captions and labels inside every band
     on every page were unreadable to anyone with less than perfect sight.

         #80889E on graphite         5.02:1  passes
         #80889E on a raised surface 4.55:1  passes

     The light value above is untouched. Do not "tidy" these two back into one. */
  --cb-ink-3:       #80889E;  /* muted, captions, labels — LIGHTER on dark */

  --cb-violet-ink:  var(--cb-violet-lift);  /* violet TEXT on dark lifts */

  --cb-wash:        rgba(255,255,255,.022);

  --cb-shadow-1: 0 1px 2px rgba(0,0,0,.5);
  --cb-shadow-2: 0 8px 24px -6px rgba(0,0,0,.65);
  --cb-shadow-3: 0 30px 70px -20px rgba(0,0,0,.8);
  --cb-glow:     0 0 0 1px rgba(178,155,255,.14), 0 20px 60px -22px rgba(109,40,217,.55);
}
