/* ============================================================================
   Sonic Arc — tokens
   v10.48 [Aayush, 2026-09-05]

   ONE FILE THAT DEFINES EVERY COLOUR. Before this there were six, and they did
   not agree:

       the blue        #1E90FF on marketing        #0A6CFF in the app
       the background  #000308 on the hero         #02060C on how-it-works
       muted text      #7F9CBD on the hero         #8AA6C6 on pricing
       the hairline    rgba(110,194,255,.16)       and .18 on the demo

   Two blues, both called "the Sonic Arc blue". Changing the brand meant editing
   six files and missing one.

   ---------------------------------------------------------------------------
   WHY THE NAMES ARE SEMANTIC AND NOT LITERAL

   A token called --navy tells you what it looks like. A token called --surface
   tells you what it is FOR. Only the second can change between a dark theme and
   a light one, which is the whole point: --surface is near-black on marketing
   and white in the app, and every rule that uses it follows without being
   rewritten.

   That is also why the light/dark switch Aayush wants in Settings is nearly free
   once this exists — it sets one attribute on <html> and every colour follows.

   ---------------------------------------------------------------------------
   ONE BLUE DOES NOT WORK ON BOTH GROUNDS, AND PRETENDING OTHERWISE IS THE
   MISTAKE THAT MAKES A PRODUCT LOOK CHEAP

   #1E90FF on white is glaring and fails contrast for small text. #0A6CFF on
   near-black is muddy and loses its lift. Both were correct choices for their own
   background; the error was calling them the same thing.

   So --accent resolves to #1E90FF in dark and #0A6CFF in light. Same role, same
   name, tuned to its ground. A designer would not ship one value for both, and
   the token system is what lets us stop trying.

   ---------------------------------------------------------------------------
   HOW TO USE IT

   Dark is the DEFAULT, because the marketing site is what a stranger sees first
   and it is the look Aayush approved. A page that wants light sets:

       <html data-theme="light">

   The compatibility block at the foot maps every OLD token name onto the new
   ones, so app.css, the marketing pages and admin.html keep working untouched
   while they are migrated one at a time. Nothing has to change in one go.
   ============================================================================ */

/* v10.54 [Aayush feedback 3] — THE TYPEFACE, LOADED ONCE FOR THE WHOLE PRODUCT.
   Only pricing.html was loading Inter. Every other page asked for it in --sans and
   fell back to the system font, which is why the sidebar read in a different
   typeface from the marketing pages — and why most of the site was not rendering in
   the face it was designed in at all.

   It belongs here because tokens.css is the one file every page already loads.
   Putting it in each page is how it came to be in only one of them.

   @import must precede every rule, so this sits above the theme blocks. */
/* v10.78 - THE FONT IMPORT MOVED OUT OF HERE.
   An @import is a SECOND round trip: the browser fetches tokens.css, parses it,
   finds this, and goes off to Google before the sheet is settled. Until it is,
   --wrap does not exist - and every max-width:var(--wrap) on the site resolves
   to nothing, which means no maximum at all. The page paints FULL WIDTH and then
   snaps in. That is the "wider design for a split second".
   The font is a <link rel="preconnect"> plus a <link rel="stylesheet"> in each
   page instead, which fetches in parallel and blocks nothing. */


/* ============================================================================
   v10.92 — THE TYPE SCALE, THE TRACKING AND THE SPACING.
   The approved layout, applied.

   NAMED --fs-, NOT --t-. This file already defines --t-base as a transition
   duration; a font size under that name would have made every transition in the
   product 15px long. Caught before it shipped, which is why the prefix differs
   from the mock-ups.

   THE SCALE is 1.200 from a 15px base, in ONE unit. What the app had was
   1.3rem, 1.02rem, 15px, 12.5px, 12px — mixed units with no ratio, and 1.02rem
   is not a step in anything.

   TRACKING MOVES WITH SIZE: large type wants negative, small wants positive. A
   single tracking value for every size is the commonest reason a scale looks
   amateur at both ends.

   SPACING is a 4px base, named by job. The app used 1rem–1.25rem almost
   everywhere, so nothing read as more important than anything else.

   None of these change between themes, so they sit outside the theme blocks.
   ============================================================================ */
:root {
  --fs-xs:11.5px; --fs-sm:12.5px; --fs-base:15px; --fs-md:17px;
  --fs-lg:20px;   --fs-xl:27px;   --fs-2xl:44px;

  --k-2xl:-.042em; --k-xl:-.026em; --k-lg:-.018em; --k-md:-.01em;
  --k-base:-.003em; --k-sm:.004em; --k-xs:.01em;

  --s-1:4px; --s-2:8px; --s-3:12px; --s-4:16px;
  --s-5:24px; --s-6:32px; --s-7:44px; --s-8:64px;
}

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

  /* v10.92 — the 1px top highlight that gives a dark surface depth. Light
     falls from above; this one line is how a costly dark interface reads as
     physical rather than flat. */
  --edge: rgba(160,205,255,.10);

  /* ---- ground ---- */
  --bg:            #02060C;   /* the page itself */
  --bg-raised:     #040B15;   /* a panel lifted off it */
  --surface:       #08121F;   /* a card */
  --surface-2:     rgba(8,20,36,.55);

  /* ---- text ---- */
  --text:          #FFFFFF;
  --text-2:        #8AA6C6;   /* body copy on dark; readable, not shouting */
  --text-3:        #4D6D92;   /* labels, captions, the quiet layer */
  /* A FOURTH LEVEL, AND IN DARK IT COLLAPSES INTO THE THIRD.
     Dark grounds have far less usable range at the quiet end than light ones: by
     the time a grey is quiet enough to read as tertiary it is too close to the
     background to read at all. Three distinct greys in light, two in dark, is the
     honest answer — and it is why this token exists rather than the app carrying a
     literal that could not flip. Left as a literal it was #A9B7C2, which on a dark
     card reads 9.17:1 against --text-2's 7.48:1: the quietest grey in the system
     becoming the loudest, and the hierarchy reading backwards. */
  --text-4:        #4D6D92;

  /* ---- the accent ---- */
  --accent:        #1E90FF;   /* text, links, borders — 6.28:1 on the ground */
  /* A SOLID FILL NEEDS A DEEPER BLUE THAN A LINE OF TEXT DOES.
     White on #1E90FF is 3.24:1 — fine for a border or an icon under WCAG's
     non-text rule, short of the 4.5:1 a button LABEL needs. #166FD9 takes it to
     4.87:1 and is all but indistinguishable beside it. The alternative was to
     darken every use of the accent, which would have cost the lift that makes
     the marketing pages work. One token, one place, look preserved. */
  --accent-fill:   #166FD9;
  --accent-hi:     #6EC2FF;   /* hover, and text on dark that must stay legible */
  --accent-soft:   #9FC9F2;
  --accent-wash:   rgba(30,144,255,.10);
  --on-accent:     #FFFFFF;   /* text ON an accent fill */
  --cyan:          #A8E8FF;   /* data highlights: SPL figures, live readouts */

  /* ---- lines ---- */
  --line:          rgba(110,194,255,.16);
  --line-2:        rgba(110,194,255,.08);

  /* ---- states ---- */
  --good:          #3FBFA8;   --good-wash: rgba(63,191,168,.12);
  --warn:          #E9C46A;   --warn-wash: rgba(233,196,106,.12);
  --bad:           #E76F51;   --bad-wash:  rgba(231,111,81,.12);

  /* ---- elevation. Softer on dark: a hard shadow on near-black reads as a
         smudge, so depth comes from a lighter surface plus a faint ring. ---- */
  --e1: 0 1px 2px rgba(0,0,0,.30);
  --e2: 0 4px 16px rgba(0,0,0,.36);
  --e3: 0 18px 50px rgba(0,0,0,.46);
}

[data-theme="light"] {
  /* v10.92 — no top highlight in light; the shadow already does that work. */
  --edge: transparent;
  color-scheme: light;

  --bg:            #F6F8FA;
  --bg-raised:     #FFFFFF;
  --surface:       #FFFFFF;
  --surface-2:     #F0F3F6;

  --text:          #0B1B2B;
  --text-2:        #4A5C6C;
  --text-3:        #7C8FA0;
  --text-4:        #A9B7C2;   /* the quiet layer light grounds can afford */

  --accent:        #0A6CFF;
  /* On light the accent already clears 4.56:1 against white, so the fill is the
     same colour. The token exists in both themes so a rule never has to ask
     which theme it is in. */
  --accent-fill:   #0A6CFF;
  --accent-hi:     #0055D4;   /* on light, hover goes DARKER, not lighter */
  --accent-soft:   #4FA3FF;
  --accent-wash:   #EDF4FF;
  --on-accent:     #FFFFFF;
  --cyan:          #0E7C8A;

  --line:          #E5EAEF;
  --line-2:        #F0F3F6;

  --good:          #0E7C5A;   --good-wash: #E7F5F0;
  --warn:          #9A6B10;   --warn-wash: #FDF5E4;
  --bad:           #B3382C;   --bad-wash:  #FBEDEB;

  --e1: 0 1px 2px rgba(11,27,43,.04), 0 1px 1px rgba(11,27,43,.03);
  --e2: 0 2px 8px rgba(11,27,43,.05), 0 1px 2px rgba(11,27,43,.04);
  --e3: 0 8px 28px rgba(11,27,43,.08), 0 2px 6px rgba(11,27,43,.05);
}

/* ---------------------------------------------------------------------------
   Type, spacing and motion — the same in both themes.
   --------------------------------------------------------------------------- */
:root {
  --sans: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  /* JetBrains Mono ahead of the system faces: SF Mono only exists on Apple
     machines, so a dealer on Windows was seeing Consolas where the design
     assumed something else. The stack keeps the system faces behind it. */
  --mono: "JetBrains Mono", "SF Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* The header is a fixed height everywhere so page content can allow for it
     without each page guessing. */
  --header-h: 66px;
  --wrap: 1240px;

  /* v11.19 [Aayush, 2026-09-20] — 18, not 14. app.css drew 18 on every app
     page and this file drew 14 on every marketing page; both were live at the
     same time under one name. Chosen from a render of the two side by side. */
  --r-card: 18px;
  --r-ctl:  9px;
  --r-chip: 6px;

  --ease:   cubic-bezier(.22,.61,.36,1);
  --t-fast: 140ms;
  --t-base: 240ms;
  --t-slow: 420ms;
}

/* ---------------------------------------------------------------------------
   COMPATIBILITY.

   Every old token name, mapped onto the new ones. This is what makes the change
   safe: app.css, the marketing pages and admin.html can be migrated one at a
   time instead of all at once, and nothing looks different until it is.

   These are deliberately NOT for new work. New rules use the semantic names
   above; this block exists to be deleted, one line at a time, as each file
   stops needing it.
   --------------------------------------------------------------------------- */
:root {
  /* marketing (sa-) */
  --sa-bg:        var(--bg);
  --sa-bg2:       var(--bg-raised);
  --sa-panel:     var(--surface-2);
  --sa-ink:       var(--text);
  --sa-muted:     var(--text-2);
  --sa-dim:       var(--text-3);
  --sa-blue:      var(--accent);
  --sa-blue-hi:   var(--accent-hi);
  --sa-blue-soft: var(--accent-soft);
  --sa-cyan:      var(--cyan);
  --sa-line:      var(--line);
  --sa-font:      var(--sans);
  --sa-mono:      var(--mono);
  --sa-wrap:      var(--wrap);

  /* the app (app.css) — NOTE these are the LIGHT values by name. app.css is a
     light-themed stylesheet, so pages using it set data-theme="light" and these
     resolve correctly. On a dark page they follow the dark theme, which is what
     lets the same components appear in both. */
  --paper:      var(--surface);
  --wash:       var(--bg);
  --navy:       #0B1B2B;      /* literal: the navy BRAND colour, not a surface.
                                 It stays navy on a light page and on a dark one,
                                 because it is the ink in the wordmark. */
  --navy-2:     #16293D;
  --navy-3:     #24394F;
  --blue:       var(--accent);
  --blue-dk:    var(--accent-hi);
  --blue-wash:  var(--accent-wash);
  --slate:      var(--text-2);
  --slate-2:    var(--text-3);
  --slate-3:    var(--text-4);
  --hairline:   var(--line);
  --hairline-2: var(--line-2);
  --ink:        var(--text);

  /* NOT ALIASED, AND THAT IS THE POINT: --good, --warn, --bad and their washes
     already carry the same names in both theme blocks above. Writing
     "--good: var(--good)" here would be a cycle — CSS discards the whole
     declaration and every chip on the site loses its colour. app.css can simply
     drop its literals and inherit these directly. */
}
