/* KPress design tokens -- the source of truth for the KPress design system.
 *
 * Defines the --kpress-* token tree: typography, color + the shared surface family, the
 * corner-radius scale, spacing/measure, motion (one easing + transition speeds), and
 * scrollbars. Design RULES are kept here as comments next to each group, close to the code
 * (kpress-design.md is the map, not a duplicate ledger). The public subset is pinned by
 * contract.py::PUBLIC_CSS_VARIABLES. Core doc tokens read var(--kpress-host-*, <default>)
 * so an embedding host app can theme them; static pages and static-site builds override
 * via the same variables. */
.kpress,
.kpress-page-main,
.kpress-tooltip {
  /* Adapted from Kash base_styles.css.jinja and base_webpage.html.jinja.
     This block holds the theme-independent tokens (type, spacing, radii, motion)
     and the --color-* ⇒ --kpress-doc-* alias map. The actual COLOR VALUES are set
     per theme×palette in the Palette options section below; an embedding host
     re-themes by overriding those --kpress-doc-* tokens directly. */
  --kpress-font-body: var(
    --kpress-host-font-body,
    "Source Sans 3 Variable",
    system-ui,
    -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    sans-serif
  );
  --kpress-font-prose: var(
    --kpress-host-font-prose,
    "LocalPunct",
    "PT Serif",
    Georgia,
    "Times New Roman",
    serif
  );
  --kpress-font-sans: var(
    --kpress-host-font-sans,
    "Source Sans 3 Variable",
    system-ui,
    -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    sans-serif
  );
  --kpress-font-mono: var(
    --kpress-host-font-mono,
    ui-monospace,
    SFMono-Regular,
    Menlo,
    Consolas,
    monospace
  );
  --kpress-font-footnote: var(--kpress-host-font-footnote, var(--kpress-font-sans));
  --kpress-font-table: var(--kpress-host-font-table, var(--kpress-font-sans));
  --kpress-font-punctuation: "LocalPunct";
  --kpress-font-features-sans: normal;
  --kpress-font-weight-sans-light: 370;
  --kpress-font-weight-sans-medium: 550;
  --kpress-font-weight-sans-bold: 650;
  --kpress-font-size-large: 1.2rem;
  --kpress-font-size-normal: 1rem;
  --kpress-font-size-small: 0.95rem;
  --kpress-font-size-smaller: 0.9rem;
  --kpress-font-size-tiny: 0.85rem;
  --kpress-font-size-mono: 0.82rem;
  --kpress-font-size-mono-small: 0.75rem;
  --kpress-font-size-mono-tiny: 0.7rem;
  --kpress-line-height-normal: 1.5;
  --kpress-line-height-tight: 1.2;
  /* Section labels use real uppercase, not small-caps. Our subset Source Sans may
     not ship true `smcp` glyphs, so `font-variant: small-caps` synthesized thin,
     mis-sized caps that the 1.42 multiplier then propped up. Uppercase renders the
     font's real capital glyphs at exactly the size we ask for, so no compensation
     is needed and the multiplier is 1 (kept as a tunable dial, not removed, so the
     `calc(base * multiplier)` consumers don't all have to change). */
  --kpress-caps-transform: uppercase;
  --kpress-caps-variant: normal;
  --kpress-caps-spacing: 0.021em;
  --kpress-caps-heading-size-multiplier: 1;
  --kpress-caps-heading-line-height: calc(1.2 / var(--kpress-caps-heading-size-multiplier));
  /* One canonical uppercase section-label size (TOC title, metadata summary, tab
     labels, diagnostics) so they all match instead of drifting. */
  --kpress-caps-label-size: calc(
    var(--kpress-font-size-smaller) *
    var(--kpress-caps-heading-size-multiplier)
  );
  /* Prose reading measure. 48rem (~768px) matches kash's --content-width; the
     earlier 76ch (~640px in serif) read narrower than the reference. */
  --kpress-measure: 48rem;
  /* Settings gear position (standalone page shell only). The gear is `position:
     fixed`, pinned to the top-right of the document frame; these two tokens are
     its block/inline insets. Host-overridable through the `--kpress-host-*`
     hooks so a site can move it without touching kpress — e.g. align it to the
     content column's right edge instead of flush to the window, by setting on :root
       --kpress-host-settings-inset-inline: max(3rem, calc(50vw - 24rem));
     (24rem = half the 48rem --kpress-measure; use the literal on :root, where
     --kpress-measure is not in scope. See kpress-design.md → Settings menu.) */
  --kpress-settings-inset-block: var(--kpress-host-settings-inset-block, 0.75rem);
  --kpress-settings-inset-inline: var(--kpress-host-settings-inset-inline, 0.75rem);
  /* Core doc colors (--kpress-doc-bg/text/muted/border/link/code-bg) and the
     surface tints are set DIRECTLY per theme×palette in the Palette options
     section below — on :root (standalone) and .kpress (embedded) so they cascade
     to the whole shell (gear, tooltips, TOC), with no host-var / literal-fallback
     indirection that could silently theme-swap on a typo. An embedding host
     overrides these --kpress-doc-* tokens directly. */
  --kpress-doc-accent: oklch(51.09% 0.0861 186.4);
  /* Content card chrome: the reading column rendered as a bordered sheet
     floating over the page (see components.css "Content card" and
     kpress-design.md). Border + shadow are textpress's values verbatim; the
     dark themes deepen the shadow (overridden in the dark palette block). */
  --kpress-card-border: 1px solid var(--kpress-doc-border);
  --kpress-card-shadow:
    0 10px 15px -3px oklch(0.00% 0 0 / 0.1), 0 -2px 6px -1px oklch(0.00% 0 0 / 0.07);
  --kpress-print-page-margin: 0.7in;
  --kpress-print-font-size: 11pt;
  --kpress-print-footer: "Formatted by KPress";
  --font-sans: var(--kpress-font-sans);
  --font-serif: var(--kpress-font-prose);
  --font-mono: var(--kpress-font-mono);
  --font-features-sans: var(--kpress-font-features-sans);
  --font-weight-sans-medium: var(--kpress-font-weight-sans-medium);
  --font-weight-sans-bold: var(--kpress-font-weight-sans-bold);
  --font-size-large: var(--kpress-font-size-large);
  --font-size-normal: var(--kpress-font-size-normal);
  --font-size-small: var(--kpress-font-size-small);
  --font-size-smaller: var(--kpress-font-size-smaller);
  --font-size-tiny: var(--kpress-font-size-tiny);
  --font-size-mono: var(--kpress-font-size-mono);
  --font-size-mono-small: var(--kpress-font-size-mono-small);
  --font-size-mono-tiny: var(--kpress-font-size-mono-tiny);
  --line-height-normal: var(--kpress-line-height-normal);
  --line-height-tight: var(--kpress-line-height-tight);
  --caps-transform: var(--kpress-caps-transform);
  --caps-caps-variant: var(--kpress-caps-variant);
  --caps-spacing: var(--kpress-caps-spacing);
  --caps-heading-size-multiplier: var(--kpress-caps-heading-size-multiplier);
  --caps-heading-line-height: var(--kpress-caps-heading-line-height);
  --color-bg: var(--kpress-doc-bg);
  --color-bg-solid: var(--kpress-doc-bg);
  --color-bg-alt: var(--kpress-doc-surface-bg);
  --color-bg-alt-solid: var(--kpress-doc-surface-bg);
  --color-bg-meta-solid: var(--kpress-doc-surface-bg);
  --color-bg-selected: var(--kpress-doc-surface-selected);
  --color-text: var(--kpress-doc-text);
  --color-primary: var(--kpress-doc-link);
  --color-primary-light: color-mix(in srgb, var(--kpress-doc-link) 72%, white);
  --color-secondary: var(--kpress-doc-muted);
  --color-hint: var(--kpress-doc-muted);
  --color-hint-strong: var(--kpress-doc-muted);
  --color-hint-gentle: var(--kpress-doc-border);
  --color-border-hint: var(--kpress-doc-border);
  --color-hover-bg: var(--kpress-doc-surface-hover);
  --color-hover: var(--kpress-doc-border);
  --color-selection: color-mix(in srgb, var(--kpress-doc-link) 20%, transparent);
  --color-scrollbar: color-mix(in srgb, var(--kpress-doc-muted) 45%, transparent);
  --color-scrollbar-hover: color-mix(in srgb, var(--kpress-doc-muted) 70%, transparent);
  --color-success: var(--kpress-doc-success);
  --color-danger: var(--kpress-doc-danger);
  /* Subtle surface fill shared by code blocks, table headers, and the metadata
     block, so they read as one family — an alias of the code bg. The hover/selected
     interaction steps (TOC hover/active, hovered controls) are set per theme×palette
     in the Palette options section below, derived from each palette's link/muted. */
  --kpress-doc-surface-bg: var(--kpress-doc-code-bg);
  /* surface-hover / surface-selected are set per theme×palette in Palette options. */
  /* Task-list checkbox size: slightly larger than body text so the check glyph
     is clearly legible at a glance and not confused with a bullet. */
  --kpress-checkbox-size: 1.15em;
  /* Square list bullet — one size for prose lists, claim markers, and concept
     items, so every bulleted list matches. */
  --kpress-bullet-size: 0.8rem;
  /* Corner radii — one scale used everywhere. Rounded-vs-square is a deliberate
     per-surface choice (use --kpress-radius-none for square). */
  --kpress-radius-none: 0;
  --kpress-radius-sm: 3px;
  --kpress-radius-md: 6px;
  --kpress-radius-lg: 0.5rem;
  --kpress-radius-pill: 999px;
  /* Shared motion. One easing; a fast transition for hovers and size/shape
     changes, a slower fade for overlays. Suppressed under prefers-reduced-motion
     (see the reduce block in components.css). */
  --kpress-ease: ease-in-out;
  --kpress-transition-fast: 0.15s var(--kpress-ease);
  --kpress-transition-med: 0.2s var(--kpress-ease);
  --kpress-transition-slow: 0.4s var(--kpress-ease);
  --kpress-transition-fade: 0.3s var(--kpress-ease);
}

/* Global font switch. Default ("custom", set by render.py on the .kpress
   wrapper) uses the vendored PT Serif / Source Sans reader faces below.
   "system" opts out of the vendored faces and uses the platform system
   font stack, so no reader fonts are downloaded. Switchable via
   RenderOptions.font_mode at render time, and per reader via the settings
   widget's font-set chooser, which stamps data-kpress-font-set on <html>
   (persisted as `kpress.fontSet`; the pre-paint bootstrap re-applies it). */
.kpress[data-kpress-fonts="system"],
[data-kpress-font-set="system"] .kpress,
[data-kpress-font-set="system"] .kpress-page-main,
[data-kpress-font-set="system"] .kpress-tooltip {
  --kpress-font-body: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --kpress-font-sans: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --kpress-font-prose: Georgia, "Times New Roman", Times, serif;
  --kpress-font-punctuation: Georgia, "Times New Roman", Times, serif;
}

/* Reading-font chooser (settings widget): "sans" flips the prose body from the
   serif reading face to the sans stack, leaving headings/UI/code untouched.
   Stamped as data-kpress-prose-font on <html> (persisted as `kpress.proseFont`;
   pre-paint applies it before first paint). Hosts may point the sans prose
   stack anywhere via --kpress-host-font-prose-sans. */
[data-kpress-prose-font="sans"] .kpress,
[data-kpress-prose-font="sans"] .kpress-page-main,
[data-kpress-prose-font="sans"] .kpress-tooltip,
.kpress[data-kpress-prose-font="sans"] {
  --kpress-font-prose: var(--kpress-host-font-prose-sans, var(--kpress-font-sans));
}

/* ============================================================================
   PALETTE OPTIONS — the single source of truth for every theme color.

   Each theme×palette block sets the document color tokens (--kpress-doc-*)
   DIRECTLY to literal values — no host-var / fallback indirection, so a typo
   renders obviously broken instead of silently swapping themes. Blocks target
   BOTH :root (standalone: render.py stamps data-kpress-resolved-theme +
   data-kpress-palette on <html>, so the tokens cascade to the WHOLE shell — gear,
   tooltips, TOC, not just the article) AND .kpress (embedded: the host stamps the
   attrs on the wrapper). Selectors are FLAT — all attributes on one element, no
   descendant combinator. `neutral` is the default (bare, no [data-kpress-palette]);
   each other palette overrides ONLY the tokens that differ. An embedding host
   overrides any --kpress-doc-* directly. Add a palette = add its two blocks.

   Design: `warm` is modeled on textpress/kash and is GENTLE. The warmth is ONLY
   the cream code/surface background (hue ~83). Text, muted, border and link stay
   COOL (teal, hue ~208) at neutral's exact lightness — so text is plain near-black
   (never tan) and borders are a quiet hairline (never warm). Warm reads as
   "neutral with a teal accent over warm paper," not a tan wash.
   ============================================================================ */

/* neutral — light (default; also the pre-JS state). :root drives the standalone
   shell; .kpress drives the embedded fragment. */
:root,
.kpress {
  --kpress-doc-bg: oklch(100.00% 0 0);
  --kpress-doc-text: oklch(21.01% 0.0318 264.7);
  --kpress-doc-muted: oklch(50.06% 0.025 259.2);
  --kpress-doc-border: oklch(89.90% 0.0151 260.7);
  --kpress-doc-link: oklch(45.76% 0.1445 254.7);
  --kpress-doc-code-bg: oklch(97.85% 0.0045 258.3);
  --kpress-doc-surface-hover: color-mix(in srgb, var(--kpress-doc-link) 8%, transparent);
  --kpress-doc-surface-selected: color-mix(in srgb, var(--kpress-doc-link) 10%, transparent);
  --kpress-doc-success: oklch(52.73% 0.1371 150.1);
  --kpress-doc-danger: oklch(50.03% 0.1821 29.5);
}

/* neutral — dark */
:root[data-kpress-resolved-theme="dark"],
.kpress[data-kpress-resolved-theme="dark"],
.kpress[data-kpress-theme="dark"] {
  --kpress-doc-bg: oklch(18.98% 0.0094 255.6);
  --kpress-doc-text: oklch(94.40% 0.0097 252.8);
  --kpress-doc-muted: oklch(76.58% 0.0205 252.9);
  --kpress-doc-border: oklch(33.73% 0.0207 254.1);
  --kpress-doc-link: oklch(76.68% 0.1208 255.4);
  --kpress-doc-code-bg: oklch(24.16% 0.0153 256.8);
  --kpress-doc-surface-hover: color-mix(in srgb, var(--kpress-doc-muted) 85%, var(--kpress-doc-bg));
  --kpress-doc-surface-selected: color-mix(in srgb, var(--kpress-doc-link) 10%, transparent);
  --kpress-doc-success: oklch(72.27% 0.192 149.6);
  --kpress-doc-danger: oklch(59.30% 0.128 29);
  /* Deeper card shadow so the sheet still reads against the dark page. */
  --kpress-card-shadow:
    0 10px 15px -3px oklch(0.00% 0 0 / 0.3), 0 -2px 6px -1px oklch(0.00% 0 0 / 0.2);
}

/* warm — light: teal accent + cream surface (textpress/kash). Overrides only the
   cool-identity tokens — to teal (hue ~208) at neutral's exact lightness, so text
   stays near-black and the border stays a quiet hairline — plus the code surface
   to cream (hue ~83). bg, surfaces, success, danger inherit neutral. */
:root[data-kpress-palette="warm"],
.kpress[data-kpress-palette="warm"] {
  --kpress-doc-text: oklch(21.01% 0.022 208);
  --kpress-doc-muted: oklch(50.06% 0.022 208);
  --kpress-doc-border: oklch(89.90% 0.012 208);
  --kpress-doc-link: oklch(56.60% 0.061 208);
  --kpress-doc-code-bg: oklch(97.50% 0.006 83);
}

/* warm — dark: same teal accent (lighter) over neutral's dark surfaces. Must
   override the SAME token set as warm-light so warm-light never leaks into dark. */
:root[data-kpress-resolved-theme="dark"][data-kpress-palette="warm"],
.kpress[data-kpress-resolved-theme="dark"][data-kpress-palette="warm"] {
  --kpress-doc-text: oklch(94.40% 0.01 208);
  --kpress-doc-muted: oklch(76.58% 0.02 208);
  --kpress-doc-border: oklch(33.73% 0.016 208);
  --kpress-doc-link: oklch(74.90% 0.07 208);
  --kpress-doc-code-bg: oklch(24.16% 0.012 83);
}

@font-face {
  font-family: "PT Serif";
  font-style: normal;
  font-display: block;
  font-weight: 400;
  src: url("../fonts/pt-serif-latin-400-normal.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: "PT Serif";
  font-style: normal;
  font-display: block;
  font-weight: 700;
  src: url("../fonts/pt-serif-latin-700-normal.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: "PT Serif";
  font-style: italic;
  font-display: block;
  font-weight: 400;
  src: url("../fonts/pt-serif-latin-400-italic.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: "PT Serif";
  font-style: italic;
  font-display: block;
  font-weight: 700;
  src: url("../fonts/pt-serif-latin-700-italic.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: "LocalPunct";
  src: local("Georgia");
  unicode-range: U+0022, U+0027, U+2018, U+2019, U+201C, U+201D;
}

@font-face {
  font-family: "Source Sans 3 Variable";
  font-style: normal;
  font-display: block;
  font-weight: 200 900;
  src: url("../fonts/source-sans-3-latin-wght-normal.woff2") format("woff2-variations");
  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: "Source Sans 3 Variable";
  font-style: italic;
  font-display: block;
  font-weight: 200 900;
  src: url("../fonts/source-sans-3-latin-wght-italic.woff2") format("woff2-variations");
  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;
}
