﻿/* ==========================================================================
   election.ltd design tokens
   Light-first (election.ltd). [data-theme="dark"] inverts roles for the
   datacenter.vote workbench surface. Same tokens, inverted roles.
   ========================================================================== */

:root {
  /* --- Surfaces ------------------------------------------------------- */
  --paper:          #FFFFFF;
  --paper-alt:      #F8FAFC;
  --paper-sunken:   #F1F5F9;
  --rule:           #E2E8F0;
  --rule-strong:    #CBD5E1;

  /* --- Ink ------------------------------------------------------------ */
  --ink-900:        #0B1220;
  --ink-700:        #1E293B;
  --ink-500:        #475569;
  --ink-400:        #64748B;

  /* --- Brand: deep institutional navy.
         Deliberately far from voters.contact's #6366F1/#A855F7 — the parent
         company must not read as one of its own products. ---------------- */
  --brand-800:      #0E2E56;
  --brand-700:      #1B3A6B;
  --brand-600:      #2563A8;
  --brand-050:      #EEF4FB;

  /* --- Semantic ------------------------------------------------------- */
  --verify:         #0F766E;   /* verified chips, primary CTA */
  --accent-600:     #9A3412;
  --accent-500:     #C2410C;
  --ok:             #15803D;
  --warn:           #B45309;
  --bad:            #B91C1C;

  /* --- Provenance status ---------------------------------------------- */
  /* Unknown is not a trust level - it is the absence of one. Neutral grey, never a
     status hue, so a figure whose provenance was never recorded cannot borrow the
     appearance of one that was. Pairs with VerificationStatus.Unknown = 0. */
  --status-unknown:     var(--ink-400);
  --status-verified:    var(--verify);
  --status-provisional: var(--warn);
  --status-ocr:         var(--accent-600);
  --status-error:       var(--bad);

  /* --- Categorical chart ramp (light ground) --------------------------- */
  --cat-1: #1B3A6B;  --cat-2: #3B9DFF;  --cat-3: #EC4899;  --cat-4: #F5A524;
  --cat-5: #22C55E;  --cat-6: #A855F7;  --cat-7: #14B8A6;  --cat-8: #EF4D63;

  /* --- Geo-tier wayfinding.
         Applied as a 3px left border, a dot in the tier chip, and the
         active-tier underline. NEVER as a fill. --------------------------- */
  --tier-state:         #FDE047;
  --tier-district:      #A855F7;
  --tier-parliamentary: #3B82F6;
  --tier-assembly:      #EF4444;
  --tier-sector:        #10B981;
  --tier-booth:         #F59E0B;

  /* --- Type -----------------------------------------------------------
     TODO: self-host IBM Plex woff2 into wwwroot/fonts and add @font-face.
     Until then these resolve through the fallback stacks below.
     No Google Fonts — India latency + DPDP optics.                        */
  --font-sans: "IBM Plex Sans", "Segoe UI", system-ui, -apple-system, sans-serif;
  --font-deva: "IBM Plex Sans Devanagari", "Nirmala UI", "Noto Sans Devanagari", var(--font-sans);
  --font-serif:"IBM Plex Serif", Georgia, "Times New Roman", serif;
  --font-mono: "IBM Plex Mono", "Cascadia Mono", Consolas, monospace;

  /* 16px base, 1.200 ratio */
  --fs-12: 0.75rem;   --fs-13: 0.8125rem; --fs-14: 0.875rem; --fs-16: 1rem;
  --fs-19: 1.1875rem; --fs-23: 1.4375rem; --fs-28: 1.75rem;  --fs-33: 2.0625rem;
  --fs-40: 2.5rem;    --fs-48: 3rem;

  --lh-body: 1.55;
  --lh-table: 1.35;

  /* --- Layout ---------------------------------------------------------- */
  --container-prose:     72ch;
  --container-marketing: 1280px;
  --container-app:       1440px;
  --gutter: 24px;
  --rail-left: 240px;

  --space-1: 4px;  --space-2: 8px;  --space-3: 12px; --space-4: 16px;
  --space-5: 24px; --space-6: 32px; --space-7: 48px; --space-8: 64px;

  --radius: 4px;
  --radius-lg: 6px;

  /* Elevation is border + inner highlight. Card drop-shadows are banned. */
  --elev-inner: inset 0 1px 0 rgba(255,255,255,0.6);
}

[data-theme="dark"] {
  --paper:        #0B0F1A;
  --paper-alt:    #111827;
  --paper-sunken: #0F1525;
  --rule:         #1E293B;
  --rule-strong:  #334155;

  --ink-900:      #F1F5F9;
  --ink-700:      #CBD5E1;
  --ink-500:      #94A3B8;
  --ink-400:      #64748B;

  --brand-600:    #5B93D6;
  --brand-050:    #111827;
  --accent-500:   #F97316;

  --elev-inner: inset 0 1px 0 rgba(255,255,255,0.04);
}

/* ==========================================================================
   FUTURISTIC LAYER
   Added on request: AI-forward visual treatment for the marketing surfaces.
   Document surfaces (Trust, Legal, Data) stay light and print-clean - they are
   read by procurement officers and lawyers, and a glowing gradient behind a
   retention schedule reads as unserious.
   ========================================================================== */

:root {
  /* --- Luminance accents. Electric cyan against the institutional navy:
         near-complementary, so the glow reads as signal, not decoration. ---- */
  --lum-cyan:    #22D3EE;
  --lum-blue:    #3B82F6;
  --lum-violet:  #8B5CF6;
  --lum-teal:    #2DD4BF;

  /* --- Deep surfaces for hero and workbench bands --------------------- */
  --deep-900:  #05070F;
  --deep-800:  #0A0F1E;
  --deep-700:  #111A31;
  --deep-600:  #1B2745;
  --deep-rule: #1E2B4A;

  /* Ink that sits on deep surfaces.

     MEASURE AGAINST THE COMPOSITE, NOT AGAINST A FLAT TOKEN. An earlier pass
     recorded a "worst case --deep-600 #1B2745". That was wrong twice over:
     --deep-600 is not painted as a background anywhere, and the ground text
     actually lands on is --grad-hero, whose two radial washes are ADDITIVE and
     land far lighter than any flat --deep-* value. On the pages that also stack
     a PlateLattice and a .glass panel the ground reaches about #353964 - lighter
     than --deep-600 - and every ink measured against the flat token was
     overstated by roughly 1.3x:

       ink       vs flat --deep-600   vs real composite ground   verdict then
       --on-deep-600 #94A6CC   6.03:1          3.76:1            FAILED AA body
       --on-deep-400 #818FB1   4.57:1          2.85:1            FAILED even 3:1

     Both were raised, and the two radial washes in --grad-hero were reduced
     from 0.28/0.22 to 0.18/0.14, until the worst composite the site can paint
     (mobile hero, both washes, mesh, plate and glass) clears 4.5:1:

       --on-deep-900 #F1F5FF  10.02:1
       --on-deep-600 #A4B3D5   5.20:1   body copy on a deep band
       --on-deep-400 #9BA9CC   4.66:1   labels and captions only

     The gap between 600 and 400 is deliberately small: on this ground there is
     no room for two well-separated inks that both clear AA, so the secondary
     tier is distinguished by size, weight and 0.08em tracking instead. Do not
     darken either back for aesthetics, and do not raise the wash alphas -
     both sides of that trade are already at the floor. Re-measure against the
     composite if you touch --grad-hero, PlateLattice's glow, or --glass-bg. */
  --on-deep-900: #F1F5FF;
  --on-deep-600: #A4B3D5;
  --on-deep-400: #9BA9CC;

  /* Status inks retuned for a deep ground. The light-ground semantics
     (--verify #0F766E, --warn #B45309, --accent-600, --bad) measure 1.0-2.3:1
     on a deep band; --brand-700 lands at 1.01:1, i.e. invisible. Worst-case
     composite ratios for these: teal 5.87, amber 6.55, orange 6.48, red 5.76,
     sky 6.56. Consumed by the .deep chip/tier/tbc rules in app.css. */
  --on-deep-ok:     #2DD4BF;
  --on-deep-warn:   #FBBF24;
  --on-deep-ocr:    #FDBA74;
  --on-deep-bad:    #FCA5A5;
  --on-deep-info:   #7DD3FC;

  /* Border for an outlined control sitting on a deep band. --glass-border
     measures 1.28:1 against its own ground, which is fine for a decorative
     panel edge but under the 3:1 SC 1.4.11 asks of a control boundary.
     This clears it at both ends of the band: 6.49:1 dark, 3.53:1 light. */
  --deep-control-border: #8492B7;

  /* --- Gradients ------------------------------------------------------- */
  /* Wash alphas were 0.28 / 0.22. Lowered to 0.18 / 0.14 for contrast: at the
     old values the composite ground reached #3F427B, which put body copy at
     3.76:1. The washes still read; they are simply no longer eating a stop and
     a half of contrast out of every deep band. */
  --grad-hero: radial-gradient(1200px 600px at 15% -10%, rgba(59,130,246,0.18), transparent 60%),
               radial-gradient(900px 500px at 85% 10%, rgba(139,92,246,0.14), transparent 55%),
               linear-gradient(160deg, var(--deep-900) 0%, var(--deep-800) 55%, var(--deep-700) 100%);
  /* Button FILL. Dark text rides on it, so the stops stay saturated:
     --deep-900 on cyan 11.13:1, on blue 5.47:1, on violet 4.75:1. */
  --grad-accent: linear-gradient(120deg, var(--lum-cyan), var(--lum-blue) 55%, var(--lum-violet));
  /* Text FILL for .grad-text. Must not reuse --grad-accent: its --lum-blue and
     --lum-violet stops measure 3.16:1 and 2.17:1 on the composite deep ground,
     so the tail of every hero line - the half a reader looks at last - fell
     under even the 3:1 large-text floor. These stops clear 4.5:1 as body text:
     cyan 6.05, sky 6.56, violet 5.92. */
  --grad-accent-text: linear-gradient(120deg, var(--lum-cyan), #7DD3FC 55%, #C4B5FD);
  --grad-rule:   linear-gradient(90deg, transparent, var(--lum-cyan), transparent);

  /* --- Glow. Used sparingly: on the primary CTA, active chips, and the
         hero mark. Never on body text or on a data table. ----------------- */
  --glow-cyan:   0 0 0 1px rgba(34,211,238,0.35), 0 0 24px -4px rgba(34,211,238,0.45);
  --glow-violet: 0 0 0 1px rgba(139,92,246,0.30), 0 0 28px -6px rgba(139,92,246,0.40);
  --glow-soft:   0 0 40px -12px rgba(59,130,246,0.55);

  /* --- Glass ----------------------------------------------------------- */
  --glass-bg:     rgba(255,255,255,0.04);
  --glass-border: rgba(255,255,255,0.10);
  --glass-blur:   blur(14px);

  /* --- Grid / mesh overlay, drawn in CSS so it costs no request -------- */
  --mesh-line:  rgba(148,166,204,0.10);
  --mesh-size:  44px;

  /* --- Icon sizing ------------------------------------------------------ */
  --icon-sm: 16px;
  --icon-md: 20px;
  --icon-lg: 28px;
  --icon-xl: 40px;
}
