/* =============================================================================
   Tradenet design tokens — single source of truth.
   Direction: "Dossier". DARK IS THE CANONICAL THEME; light is the twin.
   Note the mechanism has not moved with the direction: `:root` still carries the
   light values and `.dark` still overrides them, because Tailwind's `darkMode:
   'class'` keys every one of the ~14k `dark:` variants in the templates off that
   class. Only the DEFAULT changed (see the init script in layouts/base.html).
   Inverting the file would have meant rewriting every variant.

   Colours are stored as space-separated RGB CHANNELS, not hex, so Tailwind's
   `<alpha-value>` placeholder works: `rgb(var(--tn-ink) / <alpha-value>)` then
   supports `text-ink/60` exactly like a built-in colour. Anything reading these
   directly in plain CSS must wrap them the same way: `rgb(var(--tn-ink))`.

   Every foreground/background pair below is measured, not estimated. The floor
   is WCAG AA: 4.5:1 for text, 3:1 for component boundaries and focus rings.
   The verification script lives in docs/ — rerun it after touching any value.
   ========================================================================== */

:root {
  /* Tells the browser which way its own chrome should go — form controls, scrollbars,
     the canvas behind the page, `input` spinners. Without it a dark page still gets a
     white autofill background and a light scrollbar. It follows the class, not the OS,
     so it stays consistent with what the page actually renders. */
  color-scheme: light;

  /* --- brand ramp --------------------------------------------------------
     Anchored on the existing CTA blue at step 600. That value is the brand and
     does not move; every other step is derived around it. */
  --tn-blue-50:   239 244 255;   /* #EFF4FF */
  --tn-blue-100:  219 231 254;   /* #DBE7FE */
  --tn-blue-200:  190 211 253;   /* #BED3FD */
  --tn-blue-300:  146 181 251;   /* #92B5FB */
  --tn-blue-400:   94 147 247;   /* #5E93F7 */
  --tn-blue-500:   59 120 240;   /* #3B78F0 */
  --tn-blue-600:   37  99 235;   /* #2563EB  ← brand, fixed */
  --tn-blue-700:   27  77 200;   /* #1B4DC8 */
  --tn-blue-800:   27  62 158;   /* #1B3E9E */
  --tn-blue-900:   28  55 126;   /* #1C377E */
  --tn-blue-950:   19  34  76;   /* #13224C */

  /* --- surfaces (light: the canonical theme) -----------------------------
     Two surfaces only, with a visible step between them. The old palette
     alternated #ffffff against #f8fafc — 1.4% luminance apart, i.e. invisible.

     The ground moved from #F1F3F7 to #E7ECF4 for the same reason one step down:
     measured in OKLab it was 0.036 of lightness below the sheet, and the panel
     another 0.034 below that. Three planes that close read as one cloudy plane,
     not as three surfaces. #E7ECF4 puts 0.062 between sheet and ground, which is
     a step you can see. Verified: ink 15.25:1, ink-2 8.30:1, muted 5.13:1,
     link 6.02:1, border 3.11:1 against it. */
  --tn-ground:    231 236 244;   /* #E7ECF4  page ground */
  --tn-surface:   255 255 255;   /* #FFFFFF  the sheet */
  --tn-panel:     228 232 239;   /* #E4E8EF  the recess */
  --tn-hairline:  199 207 220;   /* #C7CFDC  decorative rule — exempt from 3:1 */
  --tn-border:    121 134 155;   /* #79869B  component boundary — 3.00:1 min */


  /* --- the anchor register ------------------------------------------------
     The page had no third register: after the hero it never dropped below
     L 0.8 again for 5849px. This is that register — a blue FIELD, not a fourth
     grey. It is blue-950, already in the ramp above, so it adds no new hue.
     In light it goes DOWN from the sheet; in dark it goes UP from the ground
     (see .dark below). Same idea, mirrored — which is the same logic the panel
     already follows: a dent in paper, an opening in the dark. */
  --tn-anchor:     19  34  76;   /* #13224C  blue-950 · L 0.266 */

  /* --- text -------------------------------------------------------------- */
  --tn-ink:        16  22  35;   /* #101623  worst pair 14.72:1 */
  --tn-ink-2:      55  68  89;   /* #374459  worst pair  8.01:1 */
  --tn-muted:      85  99 122;   /* #55637A  worst pair  4.95:1 */

  /* --- links ------------------------------------------------------------- */
  --tn-link:       27  77 200;   /* blue-700, worst pair 5.81:1 */
  --tn-link-hover: 27  62 158;   /* blue-800 */

  /* --- the single action -------------------------------------------------
     These are FILLS, not text colours. They stay identical in both themes because
     a button carries its own surface. For coloured TEXT use --tn-link, which does
     follow the theme — using --tn-action as text fails AA on the dark ground. */
  /* Every state goes DARKER, never lighter, so the white label always clears
     AA. The old rule lightened on hover in dark mode and fell to 4.09:1. */
  --tn-action:        37  99 235;   /* blue-600 · white label 5.17:1 */
  --tn-action-hover:  27  77 200;   /* blue-700 · white label 7.14:1 */
  --tn-action-active: 27  62 158;   /* blue-800 · white label 9.42:1 */
  --tn-on-action:    255 255 255;

  /* --- focus ring, two layers -------------------------------------------
     A single ring fails on a same-hue button (blue on blue = 1.72:1). The inner
     layer separates the button from the outer layer, so both edges clear 3:1 on
     any surface. Consumers: box-shadow 0 0 0 2px inner, 0 0 0 4px outer. */
  --tn-focus-inner: 255 255 255;
  --tn-focus-outer:  27  77 200;

  /* --- semantic: state only, never decoration ---------------------------- */
  /* AMENDED. Colour in this system has TWO jobs, and no third:
       1. STATE — ok / warn / crit, below. Only in states.
       2. PLATFORM IDENTITY — the six hues further down. Only for the six things
          in the catalogue, and only on marks that identify: a rule down the side
          of a card, an icon, a pill. NEVER as a button fill, because that is the
          action's job and the action is always blue.
     Anything that is neither state nor platform identity does not get a hue. */
  --tn-ok:    14 120  71;   /* #0E7847  worst pair 4.50:1 */
  --tn-warn: 169  78   8;   /* #A94E08  worst pair 4.52:1 — also "content missing" */
  --tn-crit: 180  35  24;   /* #B42318  worst pair 5.35:1 */

  /* --- video veil --------------------------------------------------------
     Light: the hero text sits on an opaque sheet, so the veil only has to make
     the sheet detach from the footage. It is not load-bearing for contrast. */
  --tn-scrim:      8  12  20;
  --tn-scrim-alpha: 0.42;

  /* --- type -------------------------------------------------------------- */
  --tn-font-sans: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --tn-font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Modular scale, ratio 1.200 from a 17px base. The top step (61px) is where
     the figures in the catalogue descent land. */
  --tn-text-2xs:  12px;  --tn-leading-2xs: 1.45;
  --tn-text-xs:   14px;  --tn-leading-xs:  1.55;
  --tn-text-sm:   17px;  --tn-leading-sm:  1.65;   /* body */
  --tn-text-md:   20px;  --tn-leading-md:  1.50;   /* lede */
  --tn-text-lg:   24px;  --tn-leading-lg:  1.30;   /* h3 */
  --tn-text-xl:   29px;  --tn-leading-xl:  1.30;
  --tn-text-2xl:  35px;  --tn-leading-2xl: 1.20;   /* h2 · descent step 1 */
  --tn-text-3xl:  42px;  --tn-leading-3xl: 1.15;   /*      descent step 2 */
  --tn-text-4xl:  51px;  --tn-leading-4xl: 1.08;   /* h1 · descent step 3 */
  --tn-text-5xl:  61px;  --tn-leading-5xl: 1.00;   /*      descent step 4 */

  --tn-weight-regular: 400;
  --tn-weight-medium:  500;   /* marginal apparatus, labels */
  --tn-weight-semi:    600;   /* subheads */
  --tn-weight-bold:    700;   /* titles, wordmark */

  --tn-tracking-display: -0.022em;
  --tn-tracking-tight:   -0.012em;
  --tn-tracking-normal:  0;
  --tn-tracking-label:   0.10em;

  --tn-measure:        68ch;   /* running prose */
  --tn-measure-narrow: 42ch;   /* card copy */
  --tn-measure-rail:   34ch;   /* the marginal apparatus */

  /* --- spacing, 4px base -------------------------------------------------- */
  --tn-space-2xs:  4px;
  --tn-space-xs:   8px;
  --tn-space-sm:  12px;
  --tn-space-md:  16px;
  --tn-space-lg:  24px;
  --tn-space-xl:  32px;
  --tn-space-2xl: 48px;
  --tn-space-3xl: 64px;
  --tn-space-4xl: 96px;
  --tn-space-5xl: 144px;
  --tn-section-y: var(--tn-space-4xl);      /* vertical rhythm between sections */

  /* --- container and gutters ---------------------------------------------
     ONE container for navbar, sections and footer. The current page runs two —
     Tailwind's `container` (which snaps to breakpoints) in the navbar and footer,
     `max-w-7xl` in the sections — which is why the wordmark jumps 78px left when
     the viewport grows from 1000 to 1100px. */
  --tn-container: 1160px;
  --tn-gutter:      20px;

  /* --- radius ------------------------------------------------------------- */
  --tn-radius-sm:   3px;
  --tn-radius-md:   6px;
  --tn-radius-full: 9999px;

  /* --- elevation ----------------------------------------------------------
     Two shadows, no more. Paper casts a shadow; that is the whole logic. */
  --tn-shadow-sheet:   0 2px 4px rgb(11 18 32 / .10), 0 24px 60px -24px rgb(11 18 32 / .55);
  --tn-shadow-overlay: 0 4px 8px rgb(11 18 32 / .08), 0 32px 64px -20px rgb(11 18 32 / .35);

  /* --- motion -------------------------------------------------------------
     Three durations, two curves. Nothing longer than 320ms, no spring, no bounce. */
  --tn-dur-state:  120ms;   /* hover, active, colour changes */
  --tn-dur-enter:  200ms;   /* menus, disclosure */
  --tn-dur-reveal: 320ms;   /* scroll entrance */
  --tn-dur-count: 1200ms;   /* the one long duration: a figure counting up */
  --tn-stagger:     60ms;   /* max 3 items, then no further delay */
  --tn-marquee:      140s;  /* one full pass of the partner wall */
  --tn-marquee-slow:  0.22; /* playback rate while hovered or focused */
  --tn-ease-out:   cubic-bezier(.2, 0, 0, 1);
  --tn-ease-inout: cubic-bezier(.4, 0, .6, 1);

  /* --- z-index ------------------------------------------------------------ */
  --tn-z-base:      0;
  --tn-z-sticky:   10;
  --tn-z-dropdown: 20;
  --tn-z-backdrop: 30;
  --tn-z-modal:    40;
  --tn-z-toast:    50;
  --tn-z-skiplink: 60;
}

/* --- gutter steps ---------------------------------------------------------
   Breakpoints stay on Tailwind's defaults (640 / 768 / 1024 / 1280 / 1536) so
   nothing already written has to be rewritten. Only the gutter is new. */
@media (min-width: 640px)  { :root { --tn-gutter: 32px; } }
@media (min-width: 1024px) { :root { --tn-gutter: 48px; --tn-section-y: var(--tn-space-5xl); } }
@media (min-width: 1440px) { :root { --tn-gutter: 64px; } }

/* --- dark twin ------------------------------------------------------------
   Designed, not inverted. Note the recess goes DARKER than the sheet (#0C1017
   under #1A202A): in light the panel is a dent in paper, in dark it is an
   opening in the dark. Inverting mechanically would make the recess look raised. */
.dark {
  color-scheme: dark;

  --tn-ground:    18  22  30;   /* #12161E */
  --tn-surface:   26  32  42;   /* #1A202A */
  --tn-panel:     12  16  23;   /* #0C1017 */
  --tn-hairline:  43  51  64;   /* #2B3340 */
  --tn-border:    95 107 125;   /* #5F6B7D  3.03:1 min */

  /* Here the anchor cannot go down: the panel is already only 0.028 of lightness
     below the ground, and anything darker than that is not a register, it is the
     same plane again. Measured: with the band going down the page keeps 1.2% of
     its height on a different plane, in zero real bands. Going up to #172A5C it
     is 34.3% in 4 bands — the same rhythm the light theme gets. */
  --tn-anchor:    23  42  92;   /* #172A5C  L 0.301, +0.101 over the ground */

  --tn-ink:      236 239 244;   /* #ECEFF4  worst pair 14.19:1 */
  --tn-ink-2:    182 191 205;   /* #B6BFCD  worst pair  8.82:1 */
  --tn-muted:    129 142 159;   /* #818E9F  worst pair  4.91:1 */

  --tn-link:       94 147 247;  /* blue-400 — blue-600 only reaches 3.50:1 here */
  --tn-link-hover:146 181 251;  /* blue-300 */

  /* The action keeps the same fill in both themes: it is its own surface. */
  --tn-focus-inner: 18  22  30;
  --tn-focus-outer:236 239 244;

  --tn-ok:     74 222 128;   /* #4ADE80  worst pair 9.39:1 */
  --tn-warn:  240 163  44;   /* #F0A32C  worst pair 7.77:1 */
  --tn-crit:  255 139 128;   /* #FF8B80  worst pair 7.21:1 */

  --tn-scrim-alpha: 0.55;

  --tn-shadow-sheet:   0 2px 4px rgb(0 0 0 / .55), 0 24px 60px -24px rgb(0 0 0 / .80);
  --tn-shadow-overlay: 0 4px 8px rgb(0 0 0 / .45), 0 32px 64px -20px rgb(0 0 0 / .70);
}


/* --- platform identity ----------------------------------------------------
   Six platforms in the catalogue is a real taxonomy, so it is a legitimate reason
   for six hues. It is not a rainbow: one arc, equal lightness, chroma capped at
   0.185, so they read as siblings and not as six moods.

     nuclear 192°  ·  eREG 216°  ·  eGOV 240°  ||  eKYC 290°  ·  42.AI 314°  ·  zotsell 338°

   Note where the gap is. The steps are 24° apart except between eGOV and eKYC,
   where they are 50° — because the ACTION lives at 263°, right in the middle of
   that gap. No platform is ever within 23° of the colour of a button. The arc
   also stays at least 36° away from crit (29°), warn (49°) and ok (156°): a
   platform must never be mistakable for an error.

   Two sets, not one. On a light surface the tint has to be dark enough to read
   (L 0.515, worst pair 4.52:1); on a dark surface, or on an anchor band in EITHER
   theme, it has to be light enough (L 0.770, worst pair 4.55:1 across all seven
   dark surfaces the system has). The band overrides come with .tn-anchor below.

   A platform is tagged with `tn-pf--<slug>`, which sets --tn-pf; the utilities
   text-pf / bg-pf / border-pf read it. A platform with no rule here falls back
   to the muted ink, so a seventh platform added tomorrow looks plain, not broken. */
:root { --tn-pf: var(--tn-muted); }

.tn-pf--nuclear                                   { --tn-pf:  19 119 116; }  /* #137774 */
.tn-pf--ereg-fintech-distributed-registry         { --tn-pf:  18 116 135; }  /* #127487 */
.tn-pf--egov-qualified-electronic-distributed-ledger { --tn-pf: 17 110 161; }  /* #116EA1 */
.tn-pf--ekyc                                      { --tn-pf: 106  75 200; }  /* #6A4BC8 */
.tn-pf--quarantadue-ai                            { --tn-pf: 141  59 176; }  /* #8D3BB0 */
.tn-pf--zotsell-it                                { --tn-pf: 165  45 139; }  /* #A52D8B */

.dark .tn-pf--nuclear,                            .tn-anchor .tn-pf--nuclear                            { --tn-pf:  43 205 201; }  /* #2BCDC9 */
.dark .tn-pf--ereg-fintech-distributed-registry,  .tn-anchor .tn-pf--ereg-fintech-distributed-registry  { --tn-pf:  43 200 232; }  /* #2BC8E8 */
.dark .tn-pf--egov-qualified-electronic-distributed-ledger,
.tn-anchor .tn-pf--egov-qualified-electronic-distributed-ledger                                         { --tn-pf:  98 190 251; }  /* #62BEFB */
.dark .tn-pf--ekyc,                               .tn-anchor .tn-pf--ekyc                               { --tn-pf: 179 167 251; }  /* #B3A7FB */
.dark .tn-pf--quarantadue-ai,                     .tn-anchor .tn-pf--quarantadue-ai                     { --tn-pf: 217 147 251; }  /* #D993FB */
.dark .tn-pf--zotsell-it,                         .tn-anchor .tn-pf--zotsell-it                         { --tn-pf: 251 130 220; }  /* #FB82DC */

/* The pill a platform icon sits in: its own hue at 12% over the surface, so it
   belongs to the platform without competing with the icon drawn on top of it. */
.tn-pf-pill { background: rgb(var(--tn-pf) / .12); color: rgb(var(--tn-pf)); }

/* --- the anchor band ------------------------------------------------------
   One class. It does NOT paint its children: it redefines the tokens on itself,
   exactly the way .dark does, and every descendant that reads a token follows
   without being touched. That is the whole argument for the token system, and it
   is why the figures section changed register with no template edit at all.

   Anything still written as a `slate-*` literal inside one of these bands has no
   token to follow and stays the colour it was — which is why the literal
   migration ships in the same commit as this class, not after it.

   Values that DON'T depend on the theme live here; the three surfaces do depend
   on it and are set below, because the light band goes down from paper and the
   dark band goes up from near-black, so no single set works for both. */
.tn-anchor {
  --tn-ink:      236 239 244;   /* #ECEFF4  worst surface  9.60:1 light · 8.89:1 dark */
  --tn-ink-2:    190 203 228;   /* #BECBE4  worst surface  6.77:1 · 6.27:1 */
  --tn-muted:    155 173 206;   /* #9BADCE  worst surface  4.88:1 · 4.52:1 — this is
                                   #98AACC raised: on the raised card in the dark band
                                   it measured 4.37:1, just under AA */
  --tn-link:     146 181 251;   /* #92B5FB  worst surface  5.39:1 · 4.99:1 */
  --tn-link-hover: 190 211 253;
  --tn-hairline:  53  83 143;   /* #35538F  2.05:1 / 1.83:1 — decorative, exempt from
                                   3:1, but #2E467E at 1.69:1 made the descent's
                                   connecting rule vanish on the band */
  --tn-border:   120 142 190;   /* #788EBE  4.71:1 / 4.21:1 vs the band, and still
                                   3.38:1 / 3.13:1 vs a card's own fill, so the ring
                                   reads from both sides */

  /* Inside the band the action inverts. Not a preference: blue-600 measures 2.99:1
     on #13224C and 2.67:1 on #172A5C — under the 3:1 floor for a component boundary
     in both themes. White fill with a deep label is 15.43:1 and 13.80:1. */
  --tn-action:        255 255 255;
  --tn-action-hover:  219 231 254;   /* blue-100 */
  --tn-action-active: 190 211 253;   /* blue-200 */
  --tn-on-action: var(--tn-anchor);

  /* The focus ring flips too, or its outer layer is ink on ink. */
  --tn-focus-inner: var(--tn-anchor);
  --tn-focus-outer: 236 239 244;

  --tn-ground: var(--tn-anchor);
  background: rgb(var(--tn-anchor));
  color: rgb(var(--tn-ink-2));
}

/* The surfaces, per theme. A card inside the band takes its BOUNDARY from the
   border, not from its fill: the fill sits 1.39:1 (light) and 1.35:1 (dark) above
   the band, which is a lift you feel but cannot rely on. See the .card override in
   layouts/base.html.

   Getting this wrong is easy and silent: setting --tn-surface to the band colour
   makes the SECTION follow correctly and makes every CARD inside it disappear. */
.tn-anchor            { --tn-surface: 28 55 126; --tn-panel: 14 26  60; }  /* #1C377E on #13224C, recess #0E1A3C */
.dark .tn-anchor      { --tn-surface: 33 60 133; --tn-panel: 18 34  70; }  /* #213C85 on #172A5C, recess #122246 */

/* --- the one container ---------------------------------------------------- */
.tn-container {
  width: 100%;
  max-width: calc(var(--tn-container) + 2 * var(--tn-gutter));
  margin-inline: auto;
  padding-inline: var(--tn-gutter);
}

/* --- the one focus ring ---------------------------------------------------
   Applied through :focus-visible so a mouse click never paints it. */
.tn-focus:focus-visible,
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: none;
  /* No border-radius here on purpose: the ring must follow whatever radius the
     element already has, not impose one the moment it takes focus. */
  box-shadow: 0 0 0 2px rgb(var(--tn-focus-inner)),
              0 0 0 4px rgb(var(--tn-focus-outer));
}

/* --- reduced motion, once, for every consumer -----------------------------
   Consumers read the duration tokens, so neutralising them here disables motion
   everywhere without each component having to remember. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --tn-dur-state:  0.01ms;
    --tn-dur-enter:  0.01ms;
    --tn-dur-reveal: 0.01ms;
    --tn-dur-count:  0.01ms;
    --tn-stagger:    0.01ms;
  }
}
