/* ============================================================
   tokens.css — Klarik "Signal & Thread" palette

   Was klarik.app's web/theme.css; moved here (klarik.ui, ADR 0008 in
   klarik.app/docs/adr/) so every producer across every sibling repo links
   ONE file instead of hand-copying its values. Served at /klarik-ui/tokens.css
   by any host that mounts klarik_ui.static_dir() (see klarik_ui/__init__.py).

   Keeps the same variable names every existing page already reads —
   only values change here. The brief: Domain Storytelling turns a
   conversation into a *numbered sequence* of actors, objects, and
   activities — a thread. --accent ("the signal") is spent on exactly
   that: the thread line, sequence numerals, and the one interactive
   colour. Deliberately not the teal-on-navy analytics-dashboard look
   this used to be — indigo ink + marigold signal reads as this
   product's own thing, not a generic SaaS panel. --thread is a new
   token: the dedicated structural-rule colour for the numbered-node
   device in doc_page.css (kept separate from --border so the thread
   itself, not every hairline, can be tuned independently later).

   Type (ADR 0008 phase 5): the Google Fonts <link> and the font-family
   stacks used to be hand-copied into every producer's <head> and
   stylesheet — the "one thing still synced by hand" the dst.css comment
   named. Now the faces are SELF-HOSTED here: the .woff2 files sit beside
   this file in klarik_ui/static/, the @font-face blocks below load them
   same-origin off /klarik-ui/, and --font-sans / --font-mono are the
   canonical stacks. A type change is one place: drop the .woff2 in
   klarik_ui/static/, edit the @font-face src + the token, add the
   filename to klarik_ui.ASSETS. No producer edit, ever — same as a
   colour.

   Two families, by design: DM Sans for everything on screen, IBM Plex
   Mono for code / paths / structural labels / numerals. There is no
   display serif — headings are DM Sans at a bold weight. (A third face,
   Fraunces, was carried here briefly and dropped; --font-serif is gone,
   every consumer that read it now reads --font-sans.)

   Why self-hosted, not a remote CSS @import: an @import nests one
   request behind this stylesheet (html -> tokens.css -> remote CSS
   -> woff2), so on a cold load text painted in the platform fallback
   and then reflowed when the real faces finally arrived — a visible
   jump mid-navigation. Same-origin woff2 off the host that already
   serves this file arrives fast enough to apply at first paint, and
   works with no network (the desktop/MSIX build, where a remote
   import silently fell back to system fonts).

   Subsets: latin + latin-ext only (Google's own split, unicode-range
   kept so latin-ext only downloads when an accented glyph needs it).
   No vietnamese/greek/cyrillic — those glyphs fall through the stack
   to the platform font. DM Sans is a variable face, one file per
   subset; the @font-face declares the full wght axis (100 1000), not
   just the weights in use, so any font-weight the CSS asks for renders
   a real interpolated instance rather than a synthesised faux-bold.
   IBM Plex Mono is static, one file per weight (500, 600). To re-pull
   or add a weight/subset, refetch from the css2 API with a browser UA
   and mirror the @font-face here.
   ============================================================ */

@font-face {
  font-family: 'DM Sans';
  font-style: normal;
  font-weight: 100 1000;
  font-display: swap;
  src: url("dm-sans-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'DM Sans';
  font-style: normal;
  font-weight: 100 1000;
  font-display: swap;
  src: url("dm-sans-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("ibm-plex-mono-500-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("ibm-plex-mono-500-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("ibm-plex-mono-600-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("ibm-plex-mono-600-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  color-scheme: light;

  /* Type — see the header note. Union of every stack these faces
     replaced across the repos; keep the web font first, then the
     platform fallbacks the old stacks named. Two families only:
     --font-sans everywhere on screen, --font-mono for code / paths /
     structural labels. Headings are --font-sans at a bold weight;
     there is no --font-serif. */
  --font-sans:  'DM Sans', Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-mono:  'IBM Plex Mono', 'SF Mono', 'Cascadia Code', Consolas, monospace;

  /* Core surfaces — cool paper grey, not the AI-cliché warm cream */
  --bg:           #eef0f4;
  --surface:      #ffffff;
  --elevated:     #e4e7ee;
  --surface-hover:#f5f6fa;
  --border:       rgba(27, 31, 59, 0.12);
  --border-strong:rgba(27, 31, 59, 0.20);

  /* Text — deep indigo ink, not flat black */
  --text:         #1b1f3b;
  --muted:        #5b5f82;
  --muted-strong: #40435f;

  /* Brand / interaction — the marigold "signal" */
  --accent:       #d98e04;
  --accent-hover: #c27e02;
  --accent-soft:  rgba(217, 142, 4, 0.12);
  --accent-ring:  rgba(217, 142, 4, 0.22);

  /* Semantic — each its own hue, none competing with the signal */
  --ok:           #0f7a5c;
  --ok-bg:        #dff4ec;
  --warn:         #c1521e;
  --warn-bg:      #fbeae0;
  --err:          #a6291d;
  --err-bg:       #fbe4e1;
  --info:         #4a4e9e;
  --info-bg:      #e9e9f7;

  /* Shape / depth */
  --radius:       10px;
  --radius-sm:    6px;
  --radius-lg:    14px;
  --shadow-sm:    0 1px 2px rgba(27, 31, 59, 0.05);
  --shadow-card:  0 8px 22px rgba(27, 31, 59, 0.08);
  --shadow-pop:   0 18px 42px rgba(27, 31, 59, 0.16);

  /* Button shape -- theme-independent, same as --radius above. Added for
     ADR 0008 phase 4: klarik.app's own .btn / .header-action-btn /
     klarik.ui's .k-header__btn had each hardcoded one of two IDENTICAL
     shapes (verified value-for-value before introducing these -- not
     assumed from the name). The point of pulling them out: "change a
     button size" -- the question that started this ADR -- becomes editing
     one of these two lines, everywhere they're used, instead of N hardcoded
     copies across repos. --btn-sm-* is currently used only within
     klarik.app; kept alongside the other two for the same reason.
     .sd-btn (klarik.app's save-dialog) is a genuinely different shape
     (no min-height, 4px radius, 500 weight) -- deliberately NOT unified
     into these, so as not to force a real visual change through a "shared
     token" edit. */
  --btn-h:            38px;
  --btn-radius:       9px;
  --btn-weight:       700;
  --btn-pad:          8px 16px;   /* .btn */
  --btn-font:         0.84rem;    /* .btn */
  --btn-compact-pad:  8px 13px;   /* .k-header__btn, .header-action-btn */
  --btn-compact-font: 0.76rem;    /* .k-header__btn, .header-action-btn */
  --btn-sm-h:         30px;
  --btn-sm-pad:       5px 11px;
  --btn-sm-radius:    7px;
  --btn-sm-font:      0.76rem;

  /* Type scale -- theme-independent, ADR 0008 phase 6c. klarik.app's
     web/style.css (app shell) and web/doc_page.css (rendered doc pages)
     carried two private, drifted copies of the same rungs; this session's
     repeated hand-copying of one file's numbers into the other is the
     evidence. Only the values that genuinely CLUSTER are pulled out here,
     and only EXACT-match literals are aliased onto them -- snapping a
     near-miss (0.85 -> 0.875, 0.82 -> 0.8, ...) would be a visual change
     disguised as a refactor (docs/ui-styling-guide.md). So a long tail of
     one-off sizes deliberately stays literal in the consumer sheets; this
     is a partial ladder by design, not an oversight. line-height is not
     tokenised yet -- a later pass if it proves worth it.

     2026-08-31: the whole ladder stepped up ~one notch so the section
     headings out-rank the table body again (--fs-table was the largest
     rung, reading bigger than the panel headings above it on family-view /
     the main-index dashboard). Ratios between rungs are unchanged; every
     consumer -- app shell, doc pages, the dashboard twin -- moves together. */
  --fs-eyebrow:    0.72rem;    /* micro-caps kicker (h3 / .report-heading / .report-aside__label) */
  --fs-badge:      0.74rem;    /* pills & status badges (.report-state, .status-card__badge, ...) */
  --fs-small:      0.82rem;    /* small secondary text */
  --fs-secondary:  0.9rem;     /* secondary / caption body (also .panel .subtitle) */
  --fs-body:       0.95rem;    /* card & panel body copy */
  --fs-table-head: 1rem;       /* thead th / .runs-table th */
  --fs-heading:    1.0625rem;  /* section heading (h2 / .panel h2 / .report-title) -- == --fs-table */
  --fs-table:      1.0625rem;  /* table cell / .runs-table td */
  --fs-card-title: 1.125rem;   /* card title (.status-card__title, .finding-card__title, .report-story .story-name) */

  /* Doc-page title card box model -- the navy .doc-header block at the top
     of a document page (h1 + subtitle / meta). klarik.app's web/doc_page.css
     and klarik.notebook's web/index.html each hand-carried these two values
     and had ALREADY drifted -- margin-bottom was 16px in one, 20px in the
     other -- the exact ADR 0008 failure mode. One value now; same rationale
     as --btn-* for button size. The rest of .doc-header (background, the h1
     ::after signature rule, the __row / __top / __lead subparts, the
     page--main-index / page--carded variants, the mobile / print overrides)
     is still per-repo -- a later .k-doc-header component migration folds
     those in, the way .k-header* replaced the app-shell header. */
  --doc-header-pad:    24px 28px 22px;
  --doc-header-margin: 16px;

  /* Layout -- the centered content column shared by the app-shell header
     (.k-header__inner in components.css), klarik.app's .main and every
     doc-page .page / .doc-banner, and klarik.notebook's .page. One value
     so all of them share a left/right edge and a width change is a single
     edit here -- same rationale as --btn-* for button size. Stepped to
     narrower gutters by the two @media blocks at the end of this file, so
     a consumer needs no media query of its own: `max-width:
     var(--app-content-max)` and nothing else. */
  --app-content-max: min(1440px, calc(100% - 48px));

  /* Primary-button colour -- theme-DEPENDENT, unlike the shapes above.
     Light: ink navy, because a marigold fill reads muddy on white and
     --accent already carries links + highlights. Dark (see :root[data-
     theme]): --accent itself, which pops on a dark surface. Consumed by
     every primary-button rule (.btn, .btn-running, ...) so the fill is a
     one-line change, not N copies. Buttons that sit on the always-navy
     header chrome are a separate role and do not read these. */
  --btn-primary-bg:       var(--navy);
  --btn-primary-fg:       #fff;
  --btn-primary-hover-bg: var(--navy-2);

  /* Header / special surfaces */
  --navy:         #1b1f3b;
  --navy-2:       #23274a;
  --teal-faint:   rgba(217, 142, 4, 0.08);
  --grid-line:    rgba(27, 31, 59, 0.05);
  --thread:       rgba(27, 31, 59, 0.16);

  /* Dashboard accents */
  --cyan:         #4a4e9e;
  --blue:         #4a4e9e;
  --amber:        #c1521e;
  --violet:       #6b4fa0;
}

/* ============================================================
   Dark — same system, ink deepens instead of flattening to black

   The `[data-klarik-dark]` selector alongside `:root[data-theme="dark"]`
   lets any SUBTREE opt into the full dark palette regardless of the page
   theme — for a data-viz surface (a graph canvas, a map) whose colours are
   authored against a dark ground and shouldn't follow a light chrome.
   Custom properties inherit, so `<div data-klarik-dark>` re-defines --bg /
   --surface / --text / … for itself and everything inside it, with no
   per-consumer hex copy. Chrome around it still follows the selection.
   (Accent stays the page's — add `data-accent="teal"` on the same element
   if a dark-teal scope is ever needed; not defined until something wants it.)
   ============================================================ */
:root[data-theme="dark"],
[data-klarik-dark] {
  color-scheme: dark;

  /* Three clearly separated dark surfaces */
  --bg:           #14141f;
  --surface:      #1c1d2e;
  --elevated:     #242540;
  --surface-hover:#2b2c48;
  --border:       rgba(185, 188, 224, 0.14);
  --border-strong:rgba(185, 188, 224, 0.24);

  /* Text */
  --text:         #edeef7;
  --muted:        #9a9dc4;
  --muted-strong: #c0c2e0;

  /* Brand / interaction — the marigold "signal", deepened from #f0a93d one
     step toward the light theme's #d98e04 so it sits back on the dashboard;
     still ~7:1 against --navy for the primary-button label. */
  --accent:       #e09a2e;
  --accent-hover: #eab255;
  --accent-soft:  rgba(224, 154, 46, 0.12);
  --accent-ring:  rgba(224, 154, 46, 0.22);

  /* Semantic — deepened one step from the original neon-on-black calibration
     toward the light theme's tone (the dashboard cards read hot otherwise);
     kept >4.5:1 on --surface for the pill / badge text that uses them. --ok
     stays lighter than a green --accent so success != signal under the Teal
     variant. --ok-bg / --warn-bg shed alpha too — the --action card wash and
     the status pills lean on them. */
  --ok:           #43c199;
  --ok-bg:        rgba(15, 122, 92, 0.16);
  --warn:         #d46b3c;
  --warn-bg:      rgba(193, 82, 30, 0.16);
  --err:          #e06b60;
  --err-bg:       rgba(166, 41, 29, 0.24);
  --info:         #7e80c8;
  --info-bg:      rgba(74, 78, 158, 0.28);

  /* Shape / depth */
  --shadow-sm:    0 1px 0 rgba(0, 0, 0, 0.35);
  --shadow-card:  0 12px 30px rgba(0, 0, 0, 0.40);
  --shadow-pop:   0 22px 56px rgba(0, 0, 0, 0.55);

  /* Header / special surfaces */
  --navy:         #0d0e1a;
  --navy-2:       #12132a;
  --teal-faint:   rgba(224, 154, 46, 0.10);
  --grid-line:    rgba(185, 188, 224, 0.05);
  --thread:       rgba(185, 188, 224, 0.20);

  /* Primary button -- see :root. Dark flips it to the accent fill, which
     stands out on a dark surface where an ink fill would sink. */
  --btn-primary-bg:       var(--accent);
  --btn-primary-fg:       var(--navy);
  --btn-primary-hover-bg: var(--accent-hover);

  /* Dashboard accents — mirror the semantic move above */
  --cyan:         #7e80c8;
  --blue:         #7e80c8;
  --amber:        #d46b3c;
  --violet:       #8a72c0;
}

/* ============================================================
   Teal — the DARK theme with its "signal" retinted from the marigold
   to a green-teal (klarik.chat's user-bubble green, #1a8a72). Not a
   separate surface set: applyTheme() / theme-init.js
   render it as data-theme="dark" + data-accent="teal", so every dark
   rule (this block above, and each consumer's own [data-theme="dark"]
   CSS) applies unchanged and only the accent tokens below move. Must
   sit AFTER the dark block — equal specificity, source order wins.

   Opt-in via Settings > Appearance (klarik.app). The choice is stored
   in the shared 'klarik-theme' key as 'teal'; the DDD Coach only knows
   'light'/'dark' and renders dark for it.
   ============================================================ */
:root[data-accent="teal"] {
  /* Brand / interaction — teal takes over the marigold "signal" role. Only
     the accent tokens move here; the surfaces and the deepened semantic /
     dashboard hues are inherited from the dark block unchanged. --btn-primary-*
     follow via var(--accent) / var(--accent-hover).

     Retinted from klarik.chat's user-bubble green (#1a8a72) to a lower-chroma
     teal — on the dashboard the pure green read hot next to the coral
     warn/amber hues. #31907d holds ~4.3:1 on --surface (better than #1a8a72's
     3.9). --accent-soft / --accent-ring carry the dark block's 0.12 / 0.22
     weight, restated only because the base colour differs. */
  --accent:       #31907d;
  --accent-hover: #3aa189;
  --accent-soft:  rgba(49, 144, 125, 0.12);
  --accent-ring:  rgba(49, 144, 125, 0.22);
  --teal-faint:   rgba(49, 144, 125, 0.10);
}

/* ============================================================
   Layout breakpoints for --app-content-max (defined in :root).
   Narrower side gutters as the viewport tightens; every consumer
   reads the token, so these two rules are the ONLY place the
   step-downs live. Theme-independent -- plain :root, no data-theme
   guard -- which is why they sit after the theme blocks. The widths
   match klarik.app's app-shell steps (web/style.css .main) so the
   header and every content column keep the same edge at all sizes.
   ============================================================ */
@media (max-width: 899px) {
  :root { --app-content-max: calc(100% - 32px); }
}
@media (max-width: 560px) {
  :root { --app-content-max: calc(100% - 24px); }
}
