/* ==========================================================================
   Saphirion Design Tokens
   Source of truth for colors, type, spacing, radii, shadows, motion.

   Color palette is the OFFICIAL Saphirion palette as documented in
   saphirion_colors.svg. Every value below uses the published Pantone-style
   name from the palette. Use the role variable (--sph-primary, --sph-text…)
   in components; the named variants (--sph-donkey-brown, --sph-amazon…) are
   provided for situations where you need the exact named brand color.
   ========================================================================== */

/* Fonts — Work Sans is the official Saphirion typeface, loaded from Google
   Fonts. See fonts.css / colors_and_type.css for the @import.                */

:root {
  /* ─────────────────────────────────────────────────────────────────────────
     Official palette — named values
     ───────────────────────────────────────────────────────────────────────── */

  /* Core 6 — from the top row of the palette */
  --sph-smoke:              #788176;  /* LIGHT — muted text, captions          */
  --sph-white:              #FFFFFF;  /* WHITE — content surfaces              */
  --sph-dark-jungle-green:  #1D2326;  /* DARK — body text, deepest contrast    */
  --sph-donkey-brown:       #A69276;  /* PRIMARY — brand identity color        */
  --sph-loafer:             #DDDCC5;  /* SECONDARY — branded page background   */
  --sph-lonestar:           #660000;  /* INFO — emphasis, "Störer"             */

  /* Accent row */
  --sph-korma:              #92450D;  /* ACCENT 1 — earth, price/cost          */
  --sph-san-juan:           #455662;  /* ACCENT 2 — slate, navigation, structure*/
  --sph-spanish-sky-blue:   #03A8E6;  /* ACCENT 3 — digital, data viz highlight */
  --sph-amazon:             #387754;  /* ACCENT 4 — brand emerald, links       */
  --sph-camel:              #C19A68;  /* ACCENT 5 — soft warm support          */
  --sph-burgundy:           #800020;  /* ACCENT 6 — premium emphasis, alerts   */
  --sph-navy:               #000080;  /* ACCENT 7 — premium contrast, footer   */

  /* Semantic / state row (used in NLPP product UI, not decks) */
  --sph-kelly-green:        #4BA900;  /* SUCCESS — value > 125% / "Realized"   */
  --sph-golden-taino:       #FFC14C;  /* WARNING — caution, pending             */
  --sph-folly:              #F4005D;  /* DANGER — destructive                   */

  /* Tints derived from named colors (not in original palette but needed) */
  --sph-donkey-brown-deep:  #7E6A4E;  /* darker brown — hovers, pressed         */
  --sph-donkey-brown-deeper:#66563F;  /* deepest brown — hover step on -deep    */
  --sph-donkey-brown-ink:   #6B5A43;  /* text-safe brown — ≥4.5:1 small text on
                                         white, cream and Loafer surfaces       */
  --sph-donkey-brown-soft:  #F1ECE1;  /* lighter brown — tints, backgrounds     */
  --sph-loafer-soft:        #F1EFE4;  /* lighter Loafer — page tint             */
  --sph-san-juan-deep:      #364653;  /* darker San Juan — cover surface depth  */

  /* ─────────────────────────────────────────────────────────────────────────
     Role variables — use these in components
     ───────────────────────────────────────────────────────────────────────── */

  /* Brand identity */
  --sph-primary:        var(--sph-donkey-brown);
  --sph-primary-deep:   var(--sph-donkey-brown-deep);
  --sph-primary-soft:   var(--sph-donkey-brown-soft);
  /* Contrast-safe brand-gold roles (a11y review, July 2026). Brand gold
     #A69276 carries only 3.0:1 against white — legal for display sizes,
     ILLEGAL (WCAG AA) for button labels and small caps. Filled CTAs use
     --sph-interactive (white label 5.2:1); small gold TEXT (eyebrows, link
     hovers) uses --sph-text-accent (≥4.5:1 on white…Loafer). Display-size
     gold headlines keep --sph-primary.                                     */
  --sph-interactive:       var(--sph-donkey-brown-deep);
  --sph-interactive-hover: var(--sph-donkey-brown-deeper);
  --sph-text-accent:       var(--sph-donkey-brown-ink);
  /* Focus indicator for interactive controls. Follows the PAGE theme (dark
     recipes lift it), and is deliberately NOT pinned back inside authored-
     palette islands: a focus ring sits visually on the page ground, not on
     the component's own surface. */
  --sph-focus:             var(--sph-donkey-brown-ink);
  /* Chevron glyph for .sph-select — a select can't carry a pseudo-element and
     background-image can't use currentColor, so the glyph is theme-keyed. */
  --sph-chevron-ink:   url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%231D2326' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --sph-chevron-paper: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%23F4F2E9' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --sph-chevron:       var(--sph-chevron-ink);
  --sph-secondary:      var(--sph-loafer);
  --sph-secondary-soft: var(--sph-loafer-soft);

  /* Neutrals */
  --sph-dark:           var(--sph-dark-jungle-green);
  --sph-light:          var(--sph-smoke);
  --sph-ink:            var(--sph-dark-jungle-green);

  /* Info / emphasis */
  --sph-info:           var(--sph-lonestar);

  /* Extended accents — map official palette names to UI roles */
  --sph-accent-earth:   var(--sph-korma);             /* deep earth tone        */
  --sph-accent-slate:   var(--sph-san-juan);          /* slate-blue for structure*/
  --sph-accent-sky:     var(--sph-spanish-sky-blue);  /* digital blue            */
  --sph-accent-emerald: var(--sph-amazon);            /* brand emerald           */
  --sph-accent-camel:   var(--sph-camel);             /* soft warm support       */
  --sph-accent-burgundy:var(--sph-burgundy);          /* premium accent          */
  --sph-accent-navy:    var(--sph-navy);              /* navigation / footer     */

  /* Semantic — UI state, not brand identity */
  --sph-success:        var(--sph-kelly-green);
  --sph-warning:        var(--sph-golden-taino);
  --sph-danger:         var(--sph-folly);

  /* ─────────────────────────────────────────────────────────────────────────
     Surfaces
     ───────────────────────────────────────────────────────────────────────── */
  --sph-bg:              var(--sph-white);
  --sph-bg-subtle:       var(--sph-loafer-soft); /* page tint — branded but airy */
  --sph-bg-muted:        var(--sph-loafer);      /* card / callout fill          */
  --sph-bg-callout:      #ECEAD6;                /* mid Loafer for callout bands */
  /* Primary surface for cover slides, section dividers, brand sign-off:
     San Juan slate. Switched from Donkey Brown in May 2026 — the slate
     reads as more serious and precise; Donkey-Brown is now reserved for
     accent-on-cream and the Saphirion identity colour only.                */
  --sph-bg-inverse:      var(--sph-san-juan);    /* deck cover / brand-led dark  */
  --sph-bg-inverse-2:    var(--sph-san-juan-deep);
  --sph-bg-charcoal:     var(--sph-dark-jungle-green); /* deepest contrast surface*/
  --sph-surface:         var(--sph-white);
  --sph-surface-2:       #FBFAF4;
  --sph-border:          #DBD9C9;
  --sph-border-strong:   var(--sph-donkey-brown);

  /* ─────────────────────────────────────────────────────────────────────────
     Text
     ───────────────────────────────────────────────────────────────────────── */
  --sph-text:            var(--sph-dark-jungle-green);
  --sph-text-muted:      var(--sph-smoke);
  --sph-text-soft:       #4A524C;
  --sph-text-on-dark:    var(--sph-white);
  --sph-text-on-primary: var(--sph-white);

  /* ─────────────────────────────────────────────────────────────────────────
     Typography
     ───────────────────────────────────────────────────────────────────────── */
  --sph-font-display: "Work Sans", "Helvetica Neue", "Arial", system-ui, sans-serif;
  --sph-font-body:    "Work Sans", "Helvetica Neue", "Arial", system-ui, sans-serif;
  --sph-font-ui:      "Work Sans", "Helvetica Neue", "Arial", system-ui, sans-serif;
  --sph-font-mono:    "JetBrains Mono", ui-monospace, monospace;

  /* Type scale (px) */
  --sph-fs-micro: 11px;
  --sph-fs-xs:    12px;
  --sph-fs-sm:    14px;
  --sph-fs-base:  16px;
  --sph-fs-md:    18px;
  --sph-fs-lg:    22px;
  --sph-fs-xl:    28px;
  --sph-fs-2xl:   36px;
  --sph-fs-3xl:   48px;
  --sph-fs-4xl:   64px;
  --sph-fs-5xl:   88px;
  --sph-fs-hero:  120px;

  --sph-lh-tight:   1.05;
  --sph-lh-snug:    1.2;
  --sph-lh-normal:  1.45;
  --sph-lh-loose:   1.6;

  --sph-tracking-tight:  -0.02em;
  --sph-tracking-normal:  0;
  --sph-tracking-wide:    0.08em;
  --sph-tracking-wider:   0.18em;

  --sph-weight-thin:       100;
  --sph-weight-extralight: 200;
  --sph-weight-light:      300;
  --sph-weight-regular:    400;
  --sph-weight-medium:     500;
  --sph-weight-semibold:   600;
  --sph-weight-bold:       700;
  --sph-weight-extrabold:  800;
  --sph-weight-black:      900;

  /* ─────────────────────────────────────────────────────────────────────────
     Spacing — 4 px base
     ───────────────────────────────────────────────────────────────────────── */
  --sph-space-0:  0;
  --sph-space-1:  4px;
  --sph-space-2:  8px;
  --sph-space-3:  12px;
  --sph-space-4:  16px;
  --sph-space-5:  20px;
  --sph-space-6:  24px;
  --sph-space-7:  32px;
  --sph-space-8:  40px;
  --sph-space-9:  56px;
  --sph-space-10: 72px;
  --sph-space-11: 96px;
  --sph-space-12: 128px;

  /* Radii — restrained */
  --sph-radius-none: 0;
  --sph-radius-xs:   2px;
  --sph-radius-sm:   4px;
  --sph-radius-md:   6px;
  --sph-radius-lg:   10px;
  --sph-radius-xl:   16px;
  --sph-radius-pill: 999px;

  /* Elevation — warm shadows, Donkey-Brown-tinted */
  --sph-shadow-xs: 0 1px 2px rgba(29,35,38,.06);
  --sph-shadow-sm: 0 1px 3px rgba(29,35,38,.08), 0 1px 2px rgba(29,35,38,.04);
  --sph-shadow-md: 0 4px 12px rgba(29,35,38,.08), 0 2px 4px rgba(29,35,38,.04);
  --sph-shadow-lg: 0 12px 28px rgba(29,35,38,.12), 0 4px 8px rgba(29,35,38,.06);
  --sph-shadow-xl: 0 24px 48px rgba(29,35,38,.18), 0 8px 16px rgba(29,35,38,.08);
  --sph-shadow-inset: inset 0 0 0 1px var(--sph-border);

  /* Motion */
  --sph-ease-standard:   cubic-bezier(.2,.6,.2,1);
  --sph-ease-emphasized: cubic-bezier(.16,1,.3,1);
  --sph-dur-fast: 140ms;
  --sph-dur-base: 220ms;
  --sph-dur-slow: 420ms;

  /* Layout */
  --sph-maxw-prose:  68ch;
  --sph-maxw-narrow: 960px;
  --sph-maxw-wide:   1280px;
  --sph-maxw-page:   1440px;

  /* ──────────────────────────────────────────────────────────────────────
     Deck template tokens — size & padding for 1920×1080 slides
     Authored once here so re-tuning the deck happens in one file.
     Used by .sph-slide / .sph-slide--cover / --divider / --closing in motifs.css.
     ───────────────────────────────────────────────────────────────────── */
  --sph-slide-w:                1920px;
  --sph-slide-h:                1080px;
  --sph-slide-pad-x:            96px;     /* content slide horizontal       */
  --sph-slide-pad-top:          120px;    /* content slide top (chrome)     */
  /* Bottom band is THREE explicit, non-overlapping zones — body must stop
     above the note, note must stop above the chrome footer.

       slide bottom (y = 1080)
       ┌──────────────────────── chrome-footer band  (12 px text @ bottom: 48 px)
       │   bottom 48 → top 60
       ├──────────────────────── breathing            (24 px)
       │   bottom 84
       ├──────────────────────── slide-note band      (up to 48 px = 2 lines)
       │   --sph-slide-note-bottom = 84 px
       │   1-line note: y 972 → 996
       │   2-line note: y 948 → 996
       ├──────────────────────── breathing            (12 px)
       │   bottom 144
       └──────────────────────── body content stops here  (y 936)
            pad-bottom = 144 px

     The note is `position: absolute` (slide chrome layer, not body flow),
     so the body's natural bottom and the note's reserved band can never
     overlap — that decoupling is what makes the layout stable across
     decks regardless of how tall the body content is.

     Don't change pad-bottom or --sph-slide-note-bottom without re-checking
     these arithmetic relationships — body must not collide with the note
     band, note must not collide with the chrome footer.                  */
  --sph-slide-pad-bottom:       144px;    /* body content stops here        */
  --sph-slide-note-bottom:      84px;     /* note band's bottom edge        */
  --sph-slide-pad-dark:         110px;    /* cover / divider / closing      */
  --sph-slide-h1-size:          56px;     /* content slide H1               */
  /* Cover & closing are the §8 bookend pair — same dark San-Juan surface,
     same vertical rhythm, same headline size. Tune both via these tokens;
     a deck may bump one down deck-locally (see deck.css) for a specific
     headline that needs to fit on one line — but the DS default keeps the
     pair matched so the deck opens and closes on the same note.            */
  --sph-slide-h1-cover-size:    112px;    /* cover H1 — matches closing     */
  --sph-slide-h1-divider-size:  96px;     /* divider H2                     */
  --sph-slide-h1-closing-size:  112px;    /* closing H2 — matches cover     */
  --sph-slide-lead-size:        28px;     /* content slide lead paragraph   */
  --sph-slide-body-size:        24px;     /* content body + bullets (12 pt) */
  --sph-slide-caption-size:     20px;     /* caption / source / note (10 pt) */

  /* Card axes (notes/card-axes-design-v1.md §5) */
  --sph-card-seal-size:   11px;
  --sph-card-seal-inset:  36px;   /* = card padding-x */
  --sph-card-frame-inset: 10px;
  --sph-card-rail-w:      48px;
  --sph-card-folio-fs:    var(--sph-fs-5xl);
}

/* Dark surface helper — flip a container to brand-led dark mode (San Juan slate).
   For deepest contrast (Charcoal/Dark Jungle Green surfaces), use .sph-on-charcoal. */
.sph-on-dark {
  background: var(--sph-bg-inverse);
  color: var(--sph-text-on-dark);
  --sph-text:       #FFFFFF;
  --sph-text-muted: var(--sph-loafer);
  --sph-text-soft:  #EFEADC;
  --sph-border:     rgba(221,220,197,.22);
  --sph-surface:    rgba(255,255,255,.06);
  --sph-surface-2:  rgba(255,255,255,.10);
}

.sph-on-charcoal {
  background: var(--sph-bg-charcoal);
  color: var(--sph-text-on-dark);
  --sph-text:       #FFFFFF;
  --sph-text-muted: var(--sph-loafer);
  --sph-text-soft:  #EFEADC;
  --sph-border:     rgba(221,220,197,.18);
  --sph-surface:    #2A2F32;
  --sph-surface-2:  #333A3D;
}

/* ==========================================================================
   Deck dark theme — `[data-sph-theme="dark"]`

   Presenter-driven: deck-stage.js toggles the attribute on its host (Dark/
   Light bar button, `D` key) for dark rooms — beamer sessions, evening
   reviews. Generalises `.sph-on-charcoal` to the LIGHT slide archetypes:
   content slides re-bind their role tokens to the charcoal palette, while
   the four dark bookends (cover / statement / divider / closing) are
   already the dark rendering of themselves and must not change. The
   `.sph-slide--hidden` editing surface keeps its loud pale-yellow warning.

   Selector notes:
   • Dual form — the plain attribute selector serves the live deck (slides
     are light-DOM descendants of <deck-stage>); the `:host([…])` form
     serves the rail thumbnails, whose shadow hosts mirror the attribute
     (deck-stage.js _syncThumbHostAttrs).
   • Print/PPTX always render authored-light: deck-stage strips the
     attribute on beforeprint, and the PPTX export host lives outside
     <deck-stage>, so neither ever matches these rules.

   Color policy (design review, June 2026): reuse the existing palette
   wherever it already passes WCAG on charcoal (loafer, camel, sky,
   donkey-brown); where an accent is used AS TEXT and fails, re-bind its
   ROLE token to a brightness-lifted variant of the same hue (named brand
   tokens stay untouched). Verified ≥4.5:1 for body text / ≥3:1 for
   display sizes against --sph-bg-charcoal.                                 */
[data-sph-theme="dark"] .sph-slide--content:not(.sph-slide--hidden),
[data-sph-theme="dark"] .sph-slide:not([class*="sph-slide--"]),
:host([data-sph-theme="dark"]) .sph-slide--content:not(.sph-slide--hidden),
:host([data-sph-theme="dark"]) .sph-slide:not([class*="sph-slide--"]) {
  /* The slide surface itself. Declared directly (not via --sph-white,
     which becomes the ELEVATED surface below) so cards and panels keep a
     visible step above the slide ground.                                  */
  background: var(--sph-bg-charcoal);

  /* Surfaces */
  --sph-white:      #2A2F32;                /* was card/panel white → elevated charcoal */
  --sph-surface:    #2A2F32;
  --sph-surface-2:  #333A3D;
  --sph-bg:         var(--sph-bg-charcoal);
  --sph-bg-subtle:  #272D30;
  --sph-bg-muted:   #333A3D;                /* was Loafer card fill                     */
  --sph-bg-callout: #2E3437;                /* zebra rows, callout bands                */
  --sph-border:     rgba(221,220,197,.18);  /* .sph-on-charcoal value                   */

  /* Ink */
  --sph-dark:       #F4F2E9;                /* warm white, Loafer-tinted                */
  --sph-ink:        #F4F2E9;
  --sph-text:       #F4F2E9;
  --sph-text-soft:  #EFEADC;                /* .sph-on-charcoal value                   */
  --sph-text-muted: var(--sph-loafer);

  /* Accents used as text — brightness-lifted, hue kept. Named brand
     tokens (--sph-lonestar, --sph-san-juan, …) are NOT changed; only the
     role aliases are re-bound, and only inside dark content slides.
     Sized for the WORST case: body-size text on the ELEVATED surface
     (#333A3D, i.e. emphasis inside a card) needs ≥4.5:1, which demands
     more lift than the charcoal slide ground alone would.                 */
  --sph-info:            #E8917C;           /* Lonestar lifted (was #660000, 1.2:1)     */
  --sph-accent-earth:    #E09B61;           /* Korma lifted                             */
  --sph-accent-slate:    #93A9BA;           /* San Juan lifted                          */
  --sph-accent-emerald:  #6BBC8F;           /* Amazon lifted                            */
  --sph-accent-burgundy: #E68FA6;           /* Burgundy lifted                          */
  --sph-accent-navy:     #9CA7E8;           /* Navy lifted                              */
  --sph-primary-deep:    var(--sph-camel);  /* hover goes LIGHTER on dark — existing    */
  --sph-text-accent:     #C7A272;           /* Donkey Brown lifted — ≥4.5:1 on #333A3D  */
  --sph-focus:           #C7A272;           /* focus ring follows the lifted gold        */
  --sph-chevron:         var(--sph-chevron-paper);

  /* Chart structural colors + chrome mark — consumed by always-on
     indirection rules in motifs.css (SVG fills/strokes are attributes,
     so plain token inheritance can't reach them).                         */
  --sph-chart-ink:   #F4F2E9;
  --sph-chart-muted: var(--sph-loafer);
  --sph-chart-grid:  rgba(221,220,197,.28);
  --sph-chart-band:  rgba(221,220,197,.14);
  --sph-mark-filter: invert(1);             /* black ensemble mark → white              */
}

/* Card-axes carriers — tint/line mixes get their charcoal recipes (spec
   §3.1). Declared on the card so they beat the slide-level flip via
   proximity; tones resolve through the role aliases already re-bound
   above, so every marker lifts automatically. */
[data-sph-theme="dark"] .sph-card-cream,
:host([data-sph-theme="dark"]) .sph-card-cream {
  --sph-card-tone-tint: color-mix(in srgb, var(--sph-card-tone) 16%, var(--sph-surface));
  --sph-card-tone-line: color-mix(in srgb, var(--sph-card-tone) 30%, var(--sph-surface));
}

/* Authored-palette islands — components that build their OWN dark or
   branded sub-surface inside a light slide (inverted cards, banded card
   heads, step numbers, pipeline stages, the metric-band störer, pills,
   buttons), plus the DATA2VALUE process chain — a brand GRAPHIC (cream
   ribbon, Dark-Jungle circles, Loafer icons, all via currentColor) whose
   internal contrast must read the same on any ground, like the logo.
   They already carry their contrast with them and must look identical in
   both themes, so every token the flip above re-binds is pinned back to
   its authored value. Custom properties INHERIT, so these element-level
   pins win over the slide-level flip regardless of specificity.
   Buttons: only the FILLED variants (--primary/--accent/--danger) are
   islands — they carry their own light-authored surface. The transparent
   variants (bare .sph-btn, --link, --ghost, --ghost-on-dark) sit directly
   on the page/slide ground and must keep the dark-lifted role tokens, or
   their text pins to light-theme ink/lonestar and vanishes on charcoal.  */
[data-sph-theme="dark"] :is(.sph-card-cream--invert, .sph-card--metric,
    .sph-card-banded__head, .sph-card-cream__tab, .sph-card-cream__rail,
    .sph-step__num, .sph-pipeline__stage, .sph-metric-band, .sph-pill,
    .sph-btn--primary, .sph-btn--accent, .sph-btn--danger, .sph-process-chain),
:host([data-sph-theme="dark"]) :is(.sph-card-cream--invert, .sph-card--metric,
    .sph-card-banded__head, .sph-card-cream__tab, .sph-card-cream__rail,
    .sph-step__num, .sph-pipeline__stage, .sph-metric-band, .sph-pill,
    .sph-btn--primary, .sph-btn--accent, .sph-btn--danger, .sph-process-chain) {
  --sph-white:      #FFFFFF;
  --sph-surface:    #FFFFFF;
  --sph-surface-2:  #FBFAF4;
  --sph-bg-callout: #ECEAD6;
  --sph-border:     #DBD9C9;
  --sph-dark:       var(--sph-dark-jungle-green);
  --sph-ink:        var(--sph-dark-jungle-green);
  --sph-text:       var(--sph-dark-jungle-green);
  --sph-text-soft:  #4A524C;
  --sph-text-muted: var(--sph-smoke);
  --sph-info:            var(--sph-lonestar);
  --sph-accent-earth:    var(--sph-korma);
  --sph-accent-slate:    var(--sph-san-juan);
  --sph-accent-emerald:  var(--sph-amazon);
  --sph-accent-burgundy: var(--sph-burgundy);
  --sph-accent-navy:     var(--sph-navy);
  --sph-primary-deep:    var(--sph-donkey-brown-deep);
  --sph-text-accent:     var(--sph-donkey-brown-ink);
  --sph-chevron:         var(--sph-chevron-ink);
}
