/* ═══════════════════════════════════════════════════════════════════════════
   PRIMEBRIDGE DESIGN SYSTEM — LAYER 1: TOKENS
   ---------------------------------------------------------------------------
   This is the ONLY file in the project where a colour may be authored.
   Every other stylesheet, view and component consumes the variables below.

   ┌─────────────────────────────────────────────────────────────────────────┐
   │  TO REBRAND THE ENTIRE APPLICATION, EDIT THE THREE VALUES MARKED        │
   │  "THE ONE VARIABLE" BELOW. NOTHING ELSE.                                │
   │                                                                         │
   │  The brand is authored as three HSL channels rather than one hex so     │
   │  that every tint, shade, hover, ring and tinted surface can be derived  │
   │  arithmetically with calc() — no preprocessor, no build step.           │
   │                                                                         │
   │  ⚠ LIGHTNESS IS NOT INTERCHANGEABLE BETWEEN HUES.                       │
   │  Perceived luminance varies enormously by hue: green at 40% lightness   │
   │  is far brighter than indigo at 40%, so white button text that passes   │
   │  WCAG AA on indigo fails on green at the same value. Each preset below  │
   │  was solved for and verified at >= 4.5:1 for white-on-primary.          │
   │                                                                         │
   │  VERIFIED PRESETS      hue / sat / lightness      white-on-primary      │
   │    Indigo (current) →  226 /  76% / 54%              5.67:1             │
   │    Royal blue       →  212 /  84% / 46%              4.91:1             │
   │    Emerald          →  152 /  68% / 30%              4.92:1             │
   │    Teal             →  184 /  78% / 29%              4.96:1             │
   │    Violet           →  266 /  74% / 56%              5.65:1             │
   │    Crimson          →  348 /  72% / 50%              4.81:1             │
   │    Slate navy       →  220 /  40% / 50%              4.99:1             │
   │                                                                         │
   │  Choosing a hue that is not listed? Verify it before shipping — the      │
   │  simplest check is that white text on --color-primary reaches 4.5:1.    │
   └─────────────────────────────────────────────────────────────────────────┘
   ═══════════════════════════════════════════════════════════════════════════ */

:root {

  /* ══ THE ONE VARIABLE ═════════════════════════════════════════════════════
     Change these three values to rebrand the public site AND the admin panel.
     ════════════════════════════════════════════════════════════════════════ */

  --brand-h: 226;    /* hue        0–360                                     */
  --brand-s: 76%;    /* saturation 0–100%                                    */
  --brand-l: 54%;    /* lightness  0–100%  (drives all contrast maths)       */

  /* ── Accent ───────────────────────────────────────────────────────────────
     Used for the single highest-intent CTA ("Request a Quote") so it reads
     distinctly from ordinary primary actions.

     This is authored INDEPENDENTLY and deliberately does NOT rotate with the
     brand hue. Deriving it as a fixed rotation was tried and rejected: a
     complement that lands on warm orange against indigo lands on neon magenta
     against green, so the pairing broke at some brand hues.

     A warm amber-orange reads as a clear "act now" signal against cool brand
     colours (indigo, blue, teal, green, navy) without competing with them.
     If you move the brand into the warm half of the wheel — red, orange,
     crimson — pick a cool accent here instead, or set --accent-* equal to the
     brand values to drop the second colour entirely.                        */

  --accent-h: 26;
  --accent-s: 88%;
  --accent-l: 52%;


  /* ═══════════════════════════════════════════════════════════════════════
     DERIVED BRAND SCALE — do not hand-edit; these follow the values above
     ═══════════════════════════════════════════════════════════════════════ */

  --color-primary:          hsl(var(--brand-h) var(--brand-s) var(--brand-l));
  --color-primary-hover:    hsl(var(--brand-h) var(--brand-s) calc(var(--brand-l) - 8%));
  --color-primary-active:   hsl(var(--brand-h) var(--brand-s) calc(var(--brand-l) - 15%));
  --color-primary-light:    hsl(var(--brand-h) calc(var(--brand-s) - 10%) 96%);
  --color-primary-subtle:   hsl(var(--brand-h) calc(var(--brand-s) - 25%) 90%);
  --color-primary-muted:    hsl(var(--brand-h) calc(var(--brand-s) - 30%) 70%);
  --color-primary-dark:     hsl(var(--brand-h) calc(var(--brand-s) - 22%) 20%);
  --color-primary-darker:   hsl(var(--brand-h) calc(var(--brand-s) - 26%) 13%);
  --color-primary-contrast: #ffffff;

  /* Focus ring + translucent overlays, expressed with the modern slash-alpha
     syntax so a single hue change carries them too. */
  --color-primary-ring:     hsl(var(--brand-h) var(--brand-s) var(--brand-l) / .30);
  --color-primary-a08:      hsl(var(--brand-h) var(--brand-s) var(--brand-l) / .08);
  --color-primary-a12:      hsl(var(--brand-h) var(--brand-s) var(--brand-l) / .12);
  --color-primary-a20:      hsl(var(--brand-h) var(--brand-s) var(--brand-l) / .20);

  --color-accent:           hsl(var(--accent-h) var(--accent-s) var(--accent-l));
  --color-accent-hover:     hsl(var(--accent-h) var(--accent-s) calc(var(--accent-l) - 8%));
  --color-accent-active:    hsl(var(--accent-h) var(--accent-s) calc(var(--accent-l) - 14%));
  --color-accent-light:     hsl(var(--accent-h) calc(var(--accent-s) - 20%) 95%);
  /* Dark ink, not white: white on this orange is only 2.86:1, whereas the
     near-black brand ink scores 6.10:1 and keeps the CTA vivid. */
  --color-accent-contrast:  var(--color-primary-darker);
  --color-accent-ring:      hsl(var(--accent-h) var(--accent-s) var(--accent-l) / .32);


  /* ═══════════════════════════════════════════════════════════════════════
     NEUTRALS
     Tinted with the brand hue at very low saturation, so greys read as part
     of the palette rather than as dead slate. They rotate with the brand.
     ═══════════════════════════════════════════════════════════════════════ */

  --color-bg:               hsl(var(--brand-h) 30% 99%);
  --color-surface:          #ffffff;
  --color-surface-sunken:   hsl(var(--brand-h) 32% 97%);
  --color-surface-raised:   hsl(var(--brand-h) 30% 98.5%);
  --color-surface-inverse:  var(--color-primary-darker);

  --color-text-primary:     hsl(var(--brand-h) 26% 12%);
  --color-text-secondary:   hsl(var(--brand-h) 12% 36%);
  --color-text-muted:       hsl(var(--brand-h) 10% 42%);  /* 42% is the darkest-needed
                                                            value across all preset hues */
  --color-text-inverse:     #ffffff;
  --color-text-on-dark:     hsl(var(--brand-h) 30% 88%);
  --color-text-on-dark-dim: hsl(var(--brand-h) 20% 72%);

  --color-border:           hsl(var(--brand-h) 22% 91%);
  --color-border-strong:    hsl(var(--brand-h) 18% 82%);
  --color-divider:          hsl(var(--brand-h) 24% 94%);
  --color-border-inverse:   hsl(0 0% 100% / .16);

  /* Translucent whites for use on dark/brand surfaces (chips, glass buttons,
     hero tiles). Kept here so no other file authors a literal colour. */
  --color-glass-06:         hsl(0 0% 100% / .06);
  --color-glass-10:         hsl(0 0% 100% / .10);
  --color-glass-16:         hsl(0 0% 100% / .16);
  --color-scrim:            hsl(var(--brand-h) 40% 10% / .48);
  --color-veil:             hsl(0 0% 100% / .55);


  /* ═══════════════════════════════════════════════════════════════════════
     STATUS COLOURS
     Deliberately NOT derived from the brand: a success badge must stay green
     when the brand itself turns green. Each is authored independently.
     ═══════════════════════════════════════════════════════════════════════ */

  --success-h: 152; --success-s: 62%; --success-l: 34%;
  --warning-h:  38; --warning-s: 92%; --warning-l: 45%;
  --error-h:   356; --error-s:   72%; --error-l:   48%;
  --info-h:    205; --info-s:    82%; --info-l:    44%;

  --color-success:        hsl(var(--success-h) var(--success-s) var(--success-l));
  --color-success-bg:     hsl(var(--success-h) calc(var(--success-s) - 10%) 95%);
  --color-success-border: hsl(var(--success-h) calc(var(--success-s) - 20%) 82%);
  --color-success-text:   hsl(var(--success-h) var(--success-s) 26%);

  --color-warning:        hsl(var(--warning-h) var(--warning-s) var(--warning-l));
  --color-warning-bg:     hsl(var(--warning-h) calc(var(--warning-s) - 10%) 95%);
  --color-warning-border: hsl(var(--warning-h) calc(var(--warning-s) - 25%) 80%);
  --color-warning-text:   hsl(var(--warning-h) var(--warning-s) 30%);

  --color-error:          hsl(var(--error-h) var(--error-s) var(--error-l));
  --color-error-bg:       hsl(var(--error-h) calc(var(--error-s) - 10%) 96%);
  --color-error-border:   hsl(var(--error-h) calc(var(--error-s) - 20%) 86%);
  --color-error-text:     hsl(var(--error-h) var(--error-s) 38%);
  --color-error-ring:     hsl(var(--error-h) var(--error-s) var(--error-l) / .22);

  --color-info:           hsl(var(--info-h) var(--info-s) var(--info-l));
  --color-info-bg:        hsl(var(--info-h) calc(var(--info-s) - 10%) 96%);
  --color-info-border:    hsl(var(--info-h) calc(var(--info-s) - 20%) 85%);
  --color-info-text:      hsl(var(--info-h) var(--info-s) 32%);


  /* ═══════════════════════════════════════════════════════════════════════
     BRAND SURFACES — gradients and motifs used by heroes, bands and charts
     ═══════════════════════════════════════════════════════════════════════ */

  --gradient-brand: linear-gradient(
      135deg,
      var(--color-primary-darker) 0%,
      var(--color-primary-dark) 42%,
      hsl(var(--brand-h) var(--brand-s) calc(var(--brand-l) - 10%)) 100%);

  --gradient-brand-soft: linear-gradient(
      140deg,
      hsl(var(--brand-h) calc(var(--brand-s) - 15%) 95%) 0%,
      hsl(var(--brand-h) calc(var(--brand-s) - 25%) 99%) 100%);

  --gradient-accent: linear-gradient(
      135deg,
      var(--color-primary) 0%,
      var(--color-accent) 140%);

  /* Fine grid used behind dark bands. Two hairlines crossing at 32px. */
  --motif-grid:
      linear-gradient(hsl(0 0% 100% / .05) 1px, transparent 1px),
      linear-gradient(90deg, hsl(0 0% 100% / .05) 1px, transparent 1px);
  --motif-grid-size: 32px 32px;

  /* Radial glow used to lift the top-right of dark heroes. */
  --motif-glow: radial-gradient(
      circle at 78% 18%,
      hsl(var(--brand-h) var(--brand-s) 62% / .45) 0%,
      transparent 62%);


  /* ═══════════════════════════════════════════════════════════════════════
     EMBEDDED ICON ASSETS
     Form controls that need an icon painted as a background (native select,
     checkbox) cannot read a CSS variable from inside a data URI, so the two
     affected glyphs are authored here rather than in the component layer.
     That keeps 1-tokens.css the only file containing a literal colour.
     ═══════════════════════════════════════════════════════════════════════ */

  --icon-chevron-down: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");

  --icon-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6L9 17l-5-5'/%3E%3C/svg%3E");

  /* Opaque stop for mask-image gradients. Only its alpha channel is read —
     it is never painted — but it is declared here so no other file needs a
     colour literal. */
  --mask-ink: #000;


  /* ═══════════════════════════════════════════════════════════════════════
     TYPOGRAPHY
     Display = Sora (geometric, distinctive headline voice)
     Sans    = Inter (workhorse UI + body; chosen for admin table density)
     ═══════════════════════════════════════════════════════════════════════ */

  --font-display: 'Sora', 'Segoe UI', system-ui, -apple-system, sans-serif;
  --font-sans:    'Inter', 'Segoe UI', system-ui, -apple-system, Roboto, Helvetica, Arial, sans-serif;
  --font-mono:    ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;

  /* ── Type scale ───────────────────────────────────────────────────────────
     Every size in the app comes from here. No arbitrary values.

     Each step must stay visibly separated from its neighbours at BOTH ends of
     its clamp, or the hierarchy collapses on mid-size viewports. The previous
     scale failed that test twice: h4 rendered smaller than body-lg at every
     width (so an <h4> looked less important than the paragraph beside it), and
     h4's ceiling landed 1px under h3's floor (so the two were indistinguish-
     able around 900px). The middle of the scale below is re-solved; display
     and h1 are unchanged.

                    320px      1440px+
       display       44         72
       h1            34         52
       h2            28         40
       h3            21         26
       h4            18         20
       body-lg       17         18
       body          16         16
     ──────────────────────────────────────────────────────────────────────── */

  --text-display:  clamp(2.75rem,  1.9rem  + 3.60vw, 4.5rem);
  --text-h1:       clamp(2.1rem,   1.6rem  + 2.10vw, 3.25rem);
  --text-h2:       clamp(1.75rem,  1.45rem + 1.30vw, 2.5rem);
  --text-h3:       clamp(1.3rem,   1.18rem +  .50vw, 1.625rem);
  --text-h4:       clamp(1.125rem, 1.08rem +  .20vw, 1.25rem);
  --text-body-lg:  clamp(1.05rem,  1.01rem +  .18vw, 1.125rem);
  --text-body:     1rem;
  --text-body-sm:  .875rem;    /* 14px — was .9125rem (14.6px, sub-pixel)     */
  --text-caption:  .8125rem;   /* 13px                                        */
  --text-label:    .75rem;     /* 12px — was .78rem (12.48px, sub-pixel)      */

  /* Display sizes that are not headings. These exist because the wordmark and
     the KPI/stat numerals need their own sizes; without them the six values
     1.02 / 1.15 / 1.22 / 1.85 / 2.1 / .92rem get re-authored ad hoc, which is
     exactly how the scale drifted last time. */
  --text-stat:     clamp(1.75rem, 1.4rem + 1.40vw, 2.25rem);  /* 28 → 36      */
  --text-brand:    clamp(1.05rem, 1rem   +  .20vw, 1.2rem);   /* 17 → 19      */
  --text-micro:    .6875rem;   /* 11px — chart axis/peak labels only          */

  /* The 404/500 numeral. Deliberately larger than --text-display: it is a
     graphic, not a heading, and is the only element on the page. */
  --text-error-code: clamp(4.5rem, 14vw, 9rem);

  /* App-chrome titles. The admin panel needs headings a step smaller than the
     marketing site — a 52px <h1> over a data table is absurd. That was being
     achieved by pointing `.page-header h1` at --text-h2 and `.auth-aside h2`
     at --text-h1, which left the token names describing the opposite of what
     they did. These two say what they are for instead. */
  --text-page-title:  clamp(1.5rem, 1.35rem + .60vw, 1.875rem);  /* 24 → 30   */
  --text-panel-title: var(--text-h4);

  --leading-none:    1;
  --leading-flat:    1.2;
  --leading-tight:   1.12;
  --leading-snug:    1.28;
  --leading-normal:  1.5;
  --leading-relaxed: 1.68;

  --tracking-tight:  -.022em;
  --tracking-snug:   -.012em;
  --tracking-normal: 0;
  --tracking-wide:   .08em;

  --weight-normal:   400;
  --weight-medium:   500;
  --weight-semibold: 600;
  --weight-bold:     700;
  --weight-extra:    800;


  /* ═══════════════════════════════════════════════════════════════════════
     SPACING — 4px base scale
     ═══════════════════════════════════════════════════════════════════════ */

  --space-1:  4px;
  --space-2:  8px;
  --space-3:  12px;
  --space-4:  16px;
  --space-5:  20px;
  --space-6:  24px;
  --space-8:  32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;
  --space-20: 80px;
  --space-24: 96px;

  /* ── Vertical rhythm for full-width page sections ─────────────────────────
     Four bands, all on the SAME 4.5vw slope so they expand together as the
     viewport grows. Previously the hero (6vw), banner (4.5vw), cta-band (5vw)
     and .section (4.5vw) each carried their own inline clamp, so the gaps
     between sections drifted apart at intermediate widths. */
  --section-y:       clamp(56px, 4.5vw, 96px);
  --section-y-tight: clamp(40px, 3.2vw, 64px);
  --section-y-hero:  clamp(64px, 4.5vw, 104px);
  --section-y-band:  clamp(44px, 4.5vw, 76px);

  /* ── Grid gutters for the big two-column layouts ──────────────────────────
     Two steps, not five. `.hero-grid` and `.split` shared one value already;
     `.page-banner-media` (24px floor) and `.footer-grid` (28px floor) differed
     only by an unintentional 4px. */
  --gap-layout:      clamp(32px, 5vw, 72px);
  --gap-layout-sm:   clamp(24px, 4vw, 56px);

  /* ── Media aspect ratios ──────────────────────────────────────────────────
     Named so views never paste raw pixel dimensions. The value `1491 / 1055`
     had been copied into eight view files; it is ~1.413:1, close enough to
     3 / 2 that the difference was never intentional. */
  --ratio-band:      16 / 9;
  --ratio-side:      4 / 3;
  --ratio-hero:      3 / 2;


  /* ═══════════════════════════════════════════════════════════════════════
     RADIUS
     ═══════════════════════════════════════════════════════════════════════ */

  --radius-sm:   6px;
  --radius-md:   10px;
  --radius-lg:   14px;
  --radius-xl:   20px;
  --radius-2xl:  28px;
  --radius-full: 999px;


  /* ═══════════════════════════════════════════════════════════════════════
     ELEVATION — tinted with the brand hue so shadows belong to the palette
     ═══════════════════════════════════════════════════════════════════════ */

  --shadow-xs: 0 1px 2px  hsl(var(--brand-h) 30% 18% / .06);
  --shadow-sm: 0 1px 3px  hsl(var(--brand-h) 30% 18% / .07),
               0 1px 2px  hsl(var(--brand-h) 30% 18% / .04);
  --shadow-md: 0 4px 12px hsl(var(--brand-h) 30% 18% / .08),
               0 2px 4px  hsl(var(--brand-h) 30% 18% / .04);
  --shadow-lg: 0 12px 28px hsl(var(--brand-h) 30% 18% / .10),
               0 4px 10px  hsl(var(--brand-h) 30% 18% / .05);
  --shadow-xl: 0 24px 56px hsl(var(--brand-h) 30% 18% / .14),
               0 8px 20px  hsl(var(--brand-h) 30% 18% / .06);
  --shadow-brand: 0 10px 26px var(--color-primary-a20);


  /* ═══════════════════════════════════════════════════════════════════════
     LAYOUT
     ═══════════════════════════════════════════════════════════════════════ */

  --container-max:   1200px;
  --container-pad:   clamp(20px, 4vw, 32px);
  --prose-max:       68ch;
  --header-h:        76px;
  --header-h-shrunk: 64px;
  --topbar-h:        36px;
  --sidebar-w:       260px;
  --sidebar-w-rail:  76px;
  --admin-top-h:     64px;


  /* ═══════════════════════════════════════════════════════════════════════
     MOTION
     ═══════════════════════════════════════════════════════════════════════ */

  --duration-fast: 120ms;
  --duration-base: 200ms;
  --duration-slow: 320ms;
  --ease-out:      cubic-bezier(.22, .61, .36, 1);
  --ease-in-out:   cubic-bezier(.65, .05, .36, 1);
  --ease-spring:   cubic-bezier(.34, 1.4, .64, 1);


  /* ═══════════════════════════════════════════════════════════════════════
     Z-INDEX — a single ordered ladder; never write a raw z-index elsewhere
     ═══════════════════════════════════════════════════════════════════════ */

  --z-base:     1;
  --z-sticky:   100;
  --z-dropdown: 200;
  --z-overlay:  300;
  --z-drawer:   400;
  --z-modal:    500;
  --z-toast:    600;
}
