/* Grainer Design System v1.1 — FOUNDATION TOKEN DISTRIBUTION
   Extracted verbatim from GRAINER-DESIGN-SYSTEM-v1.1.dc.html
   (118129 bytes · sha256 7ba585b2dd7d250eabd1bd6afe0b14157e256001cb354628a9bcccaf03cc9789).
   This is the single canonical declaration for product files: they LINK it, they never copy it.
   Shell-scope, documentation-chrome and reference-mode tokens are deliberately absent. */
:root{
    --green:#14332A; --green600:#1E4A3B; --lime:#C2F86C; --lime600:#A8E84A;
    --lime-ink:#1B2A08; --green-ink:#DCEFE6;

    --n0:#FFFFFF; --n50:#F7F7F4; --n100:#F0F0EC; --n150:#E9E9E3; --n200:#DEDED7;
    --n300:#C5C5BD; --n400:#A6A69E; --n500:#8A8A82; --n600:#6A6A63; --n700:#4A4A44; --n900:#141414;

    --pos:#1F9E78; --pos-bg:#E6F4EF;
    --warn:#C98708; --warn-bg:#FAF1DD;
    --neg:#DD4A44;  --neg-bg:#FBE9E8;
    --info:#3A6FB0; --info-bg:#EAF1F8;

    --ai:#6E56CF; --ai-bg:#ECEAFB; --ai-ink:#FFFFFF;

    --d-bg:#0E211B; --d-card:#16352B; --d-line:rgba(220,239,230,.14);
    --d-ink:#DCEFE6; --d-mut:rgba(220,239,230,.55);
    --pos-on-dark:#46D39E; --neg-on-dark:#F0726B;
    /* OWNER DECISION D4 (2026-09-04) — closes D-BLK-02. The Shell step .72 wins:
       measured 7.79:1 on --d-bg and 6.66:1 on --green, against 5.10 / 4.54 for .55
       (.55 sat on the AA edge on --green, the surface the product actually uses).
       Declared once here; the Shell scope override is withdrawn. */
    --ink-on-dark-mut:rgba(220,239,230,.72);
    --tk-sep:rgba(220,239,230,.18);

    /* Focus canon — SRC-1 css/base.css :focus-visible (width · offset · radius).
       OWNER DECISION D3 (2026-09-04) — closes D-BLK-01. The ring is solid --green:
       13.67:1 on --surface-card, 12.73 on --surface-page, 11.96 on --surface-sunken,
       11.02 on --surface-accent, against 2.04:1 for the former rgba(20,51,42,.35)
       and a 3:1 norm. On --surface-brand the forest ring measures 1.00, so the
       MANDATORY companion rule below re-colours it to --accent (11.02). */
    --focus-ring:var(--green);
    --focus-w:3px; --focus-offset:2px; --focus-r:4px;
    /* OWNER SCOPE GRANT R18-GRANT-01 (D1 / set A, 2026-09-04) — closes G04-ink.
       These four inks are the EXISTING Shell on-tint inks, granted to foundation
       scope and declared here ONCE (the Shell block no longer declares them).
       No value was created. Measured on their own tints:
       --pos-on-bg 6.20 · --warn-on-bg 5.07 · --neg-on-bg 6.42 · --tone-neutral-on-bg 8.46.
       --tone-neutral-on-bg carries info-bg: no --info-on-bg exists upstream. */
    --pos-on-bg:#12654C; --warn-on-bg:#8A5E07; --neg-on-bg:#9C2B28;
    --tone-neutral-on-bg:#2F4A42;

    /* OWNER SCOPE GRANT R18-GRANT-02 (D5 / G10, 2026-09-04) — the layer model of
       Shell v1.0 is granted to pre-Shell verbatim and declared here ONCE (the Shell
       block no longer declares it). No step was invented or renumbered.
       Pre-Shell mapping: page 0 · in-canvas state 6 · scrim 45 · skip link 46 ·
       tooltip 60 · modal 80. --z-rail/--z-panel/--z-capsule/--z-tip stay Shell-only in use. */
    --z-canvas-state:6; --z-rail:40; --z-panel:44; --z-capsule:44; --z-scrim:45;
    --z-topbar:46; --z-tooltip:60; --z-tip:70; --z-modal:80;


    --text-strong:var(--n900); --text-body:var(--n700); --text-muted:var(--n600); --text-faint:var(--n500);
    --text-on-brand:var(--green-ink); --text-on-accent:var(--lime-ink);
    --surface-page:var(--n50); --surface-card:var(--n0); --surface-sunken:var(--n100);
    --surface-brand:var(--green); --surface-accent:var(--lime);
    --surface-dark:var(--d-bg); --surface-dark-card:var(--d-card);
    --border-default:var(--n200); --border-strong:var(--n300); --border-hairline:var(--n150);
    --brand:var(--green); --brand-hover:var(--green600); --accent:var(--lime); --accent-hover:var(--lime600);

    --font:"Manrope",system-ui,-apple-system,"Segoe UI",sans-serif;
    --font-ar:"IBM Plex Sans Arabic","Manrope",sans-serif;
    --font-mono:ui-monospace,"SF Mono","Menlo",monospace;

    --t-display:56px; --t-display-w:300; --t-display-lh:1.05; --t-display-tracking:-.02em;
    --t-statL:40px;   --t-statL-w:500;   --t-statL-lh:1.1;
    --t-statM:28px;   --t-statM-w:500;   --t-statM-lh:1.15;
    --t-h1:32px;      --t-h1-w:300;      --t-h1-lh:1.2;
    --t-h2:20px;      --t-h2-w:700;      --t-h2-lh:1.3;
    --t-body:15px;    --t-body-w:400;    --t-body-lh:1.65;
    --t-caption:12px; --t-caption-w:500;
    --t-label:11px;   --t-label-w:700;   --t-label-tracking:.08em;
    --t-stat-tracking:-.01em; --t-table-tracking:.06em; --t-kpi-tracking:.07em; --t-lockup-tracking:.14em;

    --s-1:4px; --s-2:8px; --s-3:12px; --s-4:16px; --s-6:24px; --s-8:32px; --s-12:48px; --s-16:64px;
    --r-sm:8px; --r-md:14px; --r-lg:20px; --r-pill:999px;
    --sh1:0 1px 2px rgba(20,20,20,.04), 0 4px 14px rgba(20,20,20,.05);
    --sh2:0 2px 6px rgba(20,20,20,.05), 0 12px 34px rgba(20,20,20,.08);
    --ease:cubic-bezier(.2, .7, .2, 1); --dur:200ms;
    --ctl-lg:48px; --ctl-md:40px; --ctl-sm:32px;
    --bp-tablet:600px; --bp-laptop:900px; --bp-desktop:1280px; --bp-ultrawide:1920px;
    --rail-w:84px; --aside-w:312px; --topbar-h:58px; --canvas-gutter:16px;
  }


  /* ============================================================
     COMPONENT-LEVEL DECISIONS — DS-01R2
     Reusable decisions of three adopted components, declared once so no product
     file carries a raw measure, gradient or mask. They are component tokens, not
     per-literal aliases: each one is consumed by every instance of its component.
     Machine rule: ADHERENCE R23.
     ============================================================ */
  :root{
    /* shell.split-auth — the entry column may not fall below this measure before the
       grid wraps to one column. Replaces the raw 440px minimum. */
    --entry-col-min:440px;
    /* Button · Input · IconButton — the press displacement and the disabled wash,
       adopted from SRC-1 .btn:active and .btn:disabled. Consumed by every control. */
    --press-shift:1px;
    --disabled-opacity:.5;
    /* CONTROL LABEL TYPOGRAPHY — one shared single-line contract for every control
       label (component decision, machine rule R23). Closes DS GAP G17 (Button) and
       G18 (SegmentedControl), both found by the owner in GIC-053 AUDIT 01A/01B: the
       adopted SRC-1 .btn / .timerange declared neither line-height nor letter-spacing,
       so every instance inherited the engine default "normal" and the same size class
       rendered inconsistently. Resolved here, at the shared DS layer, with NO new
       number: the line-height is the single-line control convention already declared
       for the lockup (line-height:1 in css/components.css .lockup), the tracking is
       the structural keyword "normal" (machine rule R22 — not a literal), and every
       size maps onto an already declared type step.
       C02 Button, C03 IconButton, X02 radio card and action links share the family,
       line-height, weight and tracking; C08 SegmentedControl legitimately differs in
       one property only — its uppercase pill label keeps the declared label tracking —
       so it aliases the shared contract and overrides that single property. A
       button-named token is never used inside C08. Per-variant, per-status or
       per-instance label typography is forbidden. */
    --ctl-label-family:var(--font);
    --ctl-label-lh:1;
    --ctl-label-weight:var(--t-label-w);
    --ctl-label-tracking:normal;
    /* size map — control size class → declared type step.
       NOTE (owner decision, CORRECTION 01D): the size map governs CONTROL CONTAINERS
       and non-button control labels only. C02 Button no longer maps its label onto a
       per-size step: one canonical label size serves every text-button size and
       variant (see --btn-label-size below), so lg/md/sm differ in container height,
       inline padding, icon size and gap — never in label typography. */
    --ctl-label-lg:var(--t-body);
    --ctl-label-md:var(--t-caption);
    --ctl-label-sm:var(--t-label);
    /* C02 Button — THE canonical label size for every text button, all sizes and all
       variants (primary · secondary · ghost · busy · disabled). Alias of the already
       accepted body-label step --t-body 15px; no external value was introduced and
       the md → --t-caption mapping is withdrawn. */
    --btn-label-size:var(--ctl-label-lg);
    /* C08 SegmentedControl — aliases the contract, overrides tracking only */
    --seg-label-size:var(--ctl-label-md);
    --seg-label-lh:var(--ctl-label-lh);
    --seg-label-tracking:var(--t-label-tracking);
    /* action link — a control label, never body typography */
    --link-action-size:var(--ctl-label-md);
    --link-action-weight:var(--ctl-label-weight);
    /* a text link needs room for descenders, so it takes the tightest declared
       TEXT line-height step instead of the single-line control metric */
    --link-action-lh:var(--t-h2-lh);
    /* C07 Input — FIELD TYPOGRAPHY (component decision, machine rule R23).
       Same omission as G17/G18 in SRC-1 .field: no line-height and no letter-spacing
       were declared, so field labels and values inherited "normal". The field is a
       single-line control, so it consumes the shared control line-height; the value
       keeps the body weight (it is typed content, not a label) and the code variant
       keeps the declared mono family and lockup tracking. No new number. */
    --field-label-size:var(--t-caption);
    --field-label-weight:var(--t-label-w);
    --field-label-lh:var(--t-h2-lh);
    --field-value-family:var(--font);
    --field-value-size:var(--t-body);
    --field-value-weight:var(--t-body-w);
    --field-value-lh:var(--ctl-label-lh);
    --field-value-tracking:var(--ctl-label-tracking);
    --field-code-family:var(--font-mono);
    --field-code-tracking:var(--t-lockup-tracking);
    /* X02 Context choice (radio card) — ROW GEOMETRY (component decision, R23).
       DS GAP G20, proven by GIC-053 CORRECTION 01B/01C: the accepted row height of
       the radio card was produced by the engine default line-height, so once the
       label typography was governed (G19) the row shrank from the accepted 68px.
       No declared control height governs a two-line row (--ctl-lg/md/sm are 48/40/32
       and the spacing ladder has no 68 step), so ONE semantic minimum is declared
       here, at the shared DS layer, with its basis recorded: it preserves the
       accepted X02 geometry exactly. It is a minimum, not a fixed height — a wrapped
       two-line label grows the row instead of clipping. Instance-level literals and
       reverting the text line-height are both forbidden. */
    --x02-row-min-h:68px;
    /* Desktop-only blocker backdrop — THE blur of the D10 gate (component decision,
       R23). Closes DS GAP G02 for this one governed use only: the contract requires
       the start composition to stay recognisable behind the bilingual message while
       its copy becomes unreadable. 8 / 12 / 16px were compared in the real 767px
       composition (evidence: screenshots/01..03-g02-blur.png): at 8px the background
       words are still traceable, at 16px nothing is gained over 12px, so 12px is the
       minimal value that satisfies both halves of the contract. One token, one use;
       a general blur scale remains OUT of scope. */
    --entry-blocker-blur:12px;
    /* Lockup — the gap between mark and wordmark, font-relative like the mark box. */
    --lockup-gap:.6em;
    /* Lockup — protected boundary (clear space) around the complete lockup.
       Semantic alias, value taken from the existing spacing scale (--s-6 = 24px):
       it is the smallest existing step that every accepted placement already
       provides, so the standard costs no new number. Owner decision D-lockup-space. */
    --lockup-clear-space:var(--s-6);

    /* Brand watermark treatment — one opacity for every watermark instance, plus the
       bleed measure of the full-bleed variant used by the desktop-only notice. */
    --mark-watermark-opacity:.045;
    /* Brand watermark treatment — CORNER SIZE STANDARD (fixed): every corner
       watermark is exactly this size on every surface; a raw size fails R26. From the
       previous --s-16 step on 2026-09-04 by the owner; one token for every corner
       watermark instance. The full-bleed variant keeps --mark-watermark-bleed. */
    --mark-watermark-size:128px;

    --mark-watermark-bleed:min(150vw,720px);
    /* shell.split-auth — the access card measure. */
    --entry-card-max:520px;
    /* shell.editorial-panel — the entry headline size. Fluid between two declared
       type steps so the longest Cyrillic compound word fits the entry column at every
       desktop width; the fixed --t-display clipped it near --entry-col-min. */
    --entry-hero-size:clamp(var(--t-h1),4.4vw,var(--t-display));


    /* shell.editorial-panel — the signature lime vignette of the entry surface.
       One canonical geometry for every instance (was two near-identical variants). */
    --entry-vignette:radial-gradient(58% 58% at 88% 90%,rgba(194,248,108,.15),transparent 70%);
    /* shell.split-auth — the light wash behind the access column. */
    --entry-panel-wash:radial-gradient(135% 125% at 12% -10%,var(--surface-card) 0%,var(--surface-page) 50%,var(--surface-sunken) 100%);
    /* Lockup — HOUSE PROPORTION (standard): mark box = 1.39x the wordmark font-size.
       Every lockup references this token; a raw mark size fails R25. */
    --lockup-mark:1.39em;

    /* Table and status.spinner — semantic component geometry, ratified 2026-09-04.
       Originated in grainer-app PR #75 (head 3ca2a8de0da7965aa2baf9c7f86640a101e77a7a),
       where Code tokenised the already-approved specimen geometry so the product needs
       no literal. Designer RATIFIES the five names, values and scopes unchanged: the
       rendered geometry is byte-for-byte the approved specimen. Machine rule R23. */
    --ds-table-body-size:13.5px;
    --ds-table-cell-block:12px;
    --ds-table-cell-inline:14px;
    --ds-table-head-block:10px;
    --ds-spinner-size:1.2em;
    /* Ticker — the edge-fade mask of the marquee. */
    --tk-fade:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
  }

/* ============================================================
   a11y.visually-hidden — DS UTILITY (accessibility scope only)
   The one canonical way to remove content from view while keeping it in the
   accessibility tree. The geometry lives here so that no product file declares
   a 1px box or a clip path of its own. Never for layout, never for decoration.
   Machine rule: ADHERENCE R21.
   ============================================================ */
[data-ds-a11y="visually-hidden"]{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}

/* ============================================================
   GrainerLockup — ONE INDIVISIBLE GOVERNED COMPONENT (DS-05)
   Consumers mount the wrapper only:
     <span data-ds-component="grainer-lockup" data-ds-variant="…" role="img" aria-label="Grainer">
       <span data-ds-part="mark" aria-hidden="true"></span>
       <span data-ds-part="wordmark" aria-hidden="true">Grainer</span>
     </span>
   The two internals are NOT public placement primitives: their size, order,
   separation, colour and asset come from here, never from the consumer.
   Scale the whole lockup with font-size on the wrapper — the only public knob
   besides the variant. Machine rule: ADHERENCE R27.
   ============================================================ */
[data-ds-component="grainer-lockup"]{
  display:inline-flex;align-items:center;flex-direction:row;gap:var(--lockup-gap);
  line-height:1;white-space:nowrap;padding:var(--lockup-clear-space);
  text-decoration:none;
}
[data-ds-component="grainer-lockup"] [data-ds-part="mark"]{
  width:var(--lockup-mark);height:var(--lockup-mark);aspect-ratio:1/1;flex:none;
  pointer-events:none;
  background:url('../brandmark/grainer-mark-white.png') center/contain no-repeat;
}
[data-ds-component="grainer-lockup"] [data-ds-part="wordmark"]{
  font-weight:var(--t-label-w);font-size:1em;text-transform:uppercase;
  letter-spacing:var(--t-lockup-tracking);line-height:1;color:currentColor;
  pointer-events:none;
}
/* Variants — surface/colour only, each one an existing accepted usage. */
[data-ds-component="grainer-lockup"][data-ds-variant="reverse"]{color:var(--n0)}
[data-ds-component="grainer-lockup"][data-ds-variant="forest"]{color:var(--brand)}
[data-ds-component="grainer-lockup"][data-ds-variant="forest"] [data-ds-part="mark"]{background-image:url('../brandmark/grainer-mark-forest.png')}
[data-ds-component="grainer-lockup"][data-ds-variant="on-lime"]{color:var(--lime-ink)}
[data-ds-component="grainer-lockup"][data-ds-variant="on-lime"] [data-ds-part="mark"]{background-image:url('../brandmark/grainer-mark-forest.png')}
[data-ds-component="grainer-lockup"][data-ds-variant="accent-mask"]{color:var(--accent)}
[data-ds-component="grainer-lockup"][data-ds-variant="accent-mask"] [data-ds-part="mark"]{
  background:currentColor;
  -webkit-mask:url('../brandmark/grainer-mark-white.png') center/contain no-repeat;
          mask:url('../brandmark/grainer-mark-white.png') center/contain no-repeat;
}
/* Documentation-only clear-space overlay. Production instances never carry it. */
[data-ds-component="grainer-lockup"][data-ds-doc="clear-space"]{
  outline:1px dashed var(--accent);outline-offset:calc(-1 * var(--w-hair, 1px));
  background:color-mix(in srgb, currentColor 6%, transparent);
}


/* ============================================================
   ACCESSIBILITY LAYER — OWNER DECISION D2, policy 1 (2026-09-04)
   Closes G15 (motion) and G16 (forced colors). Component-level rules only:
   ZERO authored importance overrides, and no runtime/JS dependency — both media queries
   apply from the first frame because they are plain CSS.
   Machine rules: ADHERENCE R28 (motion) · R29 (forced colors) · R30 (focus canon)
   · R31 (live region).
   ============================================================ */

/* Focus canon — declared once for every focusable thing. Components never
   re-declare it and outline:none is forbidden (R30). */
:focus-visible{outline:var(--focus-w) solid var(--focus-ring);outline-offset:var(--focus-offset);border-radius:var(--focus-r)}
/* MANDATORY COMPANION (D3): on forest surfaces the forest ring is invisible (1.00),
   so the ring becomes --accent (11.02). Declared for the surface, not per control. */
[data-ds-surface="brand"] :focus-visible,
[data-ds-surface="dark"] :focus-visible,
[data-ds-on="brand"] :focus-visible{outline-color:var(--accent)}

/* Motion lives in rules, so it can be switched off without an importance override. */
@keyframes ds-spin{to{transform:rotate(360deg)}}
@keyframes ds-tk{to{transform:translateX(-50%)}}
[data-ds-anim="spin"]{animation:ds-spin 900ms linear infinite}
[data-ds-anim="tk"]{animation:ds-tk 46s linear infinite}
[data-ds-tk]:hover [data-ds-anim="tk"]{animation-play-state:paused}
[data-ds-motion="transition"]{transition:background var(--dur) var(--ease),color var(--dur) var(--ease),border-color var(--dur) var(--ease),transform var(--dur) var(--ease)}

@media (prefers-reduced-motion:reduce){
  [data-ds-anim]{animation:none}
  [data-ds-motion="transition"]{transition:none}
  /* STATIC ALTERNATIVE for status.spinner: the rotating ring becomes a static
     determinate-less bar-free disc — still a visible busy affordance, no motion. */
  [data-ds-anim="spin"]{border-radius:var(--r-pill);border-style:dashed}
  /* Ticker: no marquee, no mask, the content is readable by scroll instead. */
  [data-ds-tk]{-webkit-mask:none;mask:none;overflow-x:auto}
  [data-ds-tk] [data-ds-anim="tk"]{width:auto}
  [data-ds-tk] [data-ds-dup="tk"]{display:none}
}

/* D10 blocker backdrop — the effect and its accessible fallbacks are owned here, so
   the product marks the element and declares no filter of its own (G02 ownership).
   The backdrop is decorative and inert: it never receives pointer or focus. */
[data-ds-blocker-backdrop]{filter:blur(var(--entry-blocker-blur));pointer-events:none}
@media (prefers-reduced-transparency:reduce){
  /* Opaque fallback: no blur, no traceable background copy — the brand surface only. */
  [data-ds-blocker-backdrop]{filter:none;background:var(--brand)}
  [data-ds-blocker-backdrop] > *{display:none}
}

@media (forced-colors:active){
  /* The blocker backdrop cannot survive a forced palette: it becomes an opaque
     system surface instead of a blurred image. */
  [data-ds-blocker-backdrop]{filter:none;background:Canvas}
  [data-ds-blocker-backdrop] > *{display:none}
  /* Surfaces lose their fills, so structure must come from borders the OS keeps. */
  [data-ds-fc="surface"]{border:1px solid CanvasText}
  [data-ds-fc="selected"]{outline:2px solid Highlight;outline-offset:var(--focus-offset)}
  [data-ds-fc="ink"]{color:CanvasText}
  /* The brandmark is a background image: forced-colors keeps it, but the accent-mask
     variant paints with currentColor, so it follows CanvasText. */
  [data-ds-component="grainer-lockup"][data-ds-variant="accent-mask"]{color:CanvasText}
  :focus-visible{outline-color:Highlight}
}

/* Live region contract (R31): every screen carries exactly one polite announcer,
   visually hidden by the a11y utility, never a second one. */
[data-ds-live]{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
