/* KPress design tokens -- the source of truth for the KPress design system.
 *
 * STRUCTURE (one comment-headed section per group; the public subset is pinned by
 * contract.py and the design-system playground exercises the tunable surface):
 *
 *   Foundations (.kpress, .kpress-page-main, .kpress-tooltip) -- theme-INDEPENDENT:
 *     1. Typography: families / weights / sizes / line-heights / section-label caps
 *     2. Spacing & layout    3. Shape (radii)    4. Motion    5. Chrome (card)
 *     6. Print    7. Color (theme-independent roles)    8. Compatibility aliases
 *   Display/Page switches  -- font mode (custom/system), reading font (serif/sans)
 *   Color -- palette x theme -- the single source of truth for every theme color
 *   Webfonts (@font-face)
 *
 * NAMING: foundation tokens are --kpress-<group>-<role>[-<variant>]
 * (--kpress-font-*, --kpress-font-size-*, --kpress-radius-*, --kpress-transition-*);
 * color roles are --kpress-doc-<role>; host override hooks are --kpress-host-*;
 * bare --color-* / --font-* are textpress-compat ALIASES (section 8), not new tokens.
 *
 * 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. */
:root,
.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,
     chrome, print, the theme-independent color roles) and the --color-* / --font-*
     compatibility alias map (section 8). The actual theme COLOR VALUES are set per
     theme x palette in the "Color -- palette x theme" section below; an embedding
     host re-themes by overriding those --kpress-doc-* tokens directly. */

  /* ============================ 1. TYPOGRAPHY ============================ */
  /* SIZING POLICY: every font size in KPress derives from ONE base knob,
     --kpress-font-size-base, via calc(base * ratio) -- ratios are design, units
     are the host's choice. No font-size rule may reference `rem` directly (the
     lint in devtools/public_hygiene.py enforces this): `rem` would couple an
     embedded document's proportions to a root font size the embedder may not
     control, while the base knob keeps standalone pages preference-respecting
     (the 1rem default resolves against the reader's browser setting) and lets a
     host with any unit policy scale the whole document as one proportional
     unit. Embedders set --kpress-host-font-size-base ONCE (e.g. `17px` on
     :root); never override individual sizes. Deliberately root-relative and NOT
     derived from the base: layout lengths (--kpress-measure, container-query
     band conditions, grid tracks, tooltip width caps, page margins) -- see
     kpress-design.md "Sizing policy". Intentionally context-relative em/% sizes
     (the summary chevron, checkbox, sup/sub) also stay as they are. */
  --kpress-font-size-base: var(--kpress-host-font-size-base, 1rem);

  /* Families. body = UI/chrome sans; prose = serif reading face; sans = the sans
     stack; mono = code; footnote/table default to sans; punctuation borrows a
     serif's quote glyphs. Each reads a --kpress-host-* hook so a host can swap it. */
  --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;

  /* Weights (Source Sans variable axis): light 370, medium 550, bold 650. */
  --kpress-font-weight-sans-light: 370;
  --kpress-font-weight-sans-medium: 550;
  --kpress-font-weight-sans-bold: 650;

  /* Sizes. One ramp for prose + UI; the mono sizes are a touch smaller so code
     aligns visually with surrounding text. `normal` is the base itself --
     derived, not a second knob: hosts set the base, not normal. */
  --kpress-font-size-large: calc(var(--kpress-font-size-base) * 1.2);
  --kpress-font-size-normal: var(--kpress-font-size-base);
  --kpress-font-size-small: calc(var(--kpress-font-size-base) * 0.95);
  --kpress-font-size-smaller: calc(var(--kpress-font-size-base) * 0.9);
  --kpress-font-size-tiny: calc(var(--kpress-font-size-base) * 0.85);
  --kpress-font-size-mono: calc(var(--kpress-font-size-base) * 0.82);
  --kpress-font-size-mono-small: calc(var(--kpress-font-size-base) * 0.75);
  --kpress-font-size-mono-tiny: calc(var(--kpress-font-size-base) * 0.7);

  /* Prose section-heading sizes (H2-H4; H1 and H5/H6 keep their literals).
     These narrow/medium defaults step up on wide panes only (the >=64rem
     container band in components.css); phones and embedded panes keep the
     tighter scale. Body text does not scale with pane width — only the
     section headings do. */
  --kpress-font-size-h2: calc(var(--kpress-font-size-base) * 1.32);
  --kpress-font-size-h3: calc(var(--kpress-font-size-base) * 1.15);
  --kpress-font-size-h4: calc(var(--kpress-font-size-base) * 1.12);

  /* Line heights. */
  --kpress-line-height-normal: 1.5;
  --kpress-line-height-tight: 1.2;

  /* Section-label caps. 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)
  );

  /* ========================= 2. SPACING & LAYOUT ========================= */
  /* Prose reading measure. 48rem (~768px) matches kash's --content-width; the
     earlier 76ch (~640px in serif) read narrower than the reference. */
  --kpress-measure: 48rem;
  --kpress-page-margin-inline: 2rem;
  --kpress-page-margin-block-start: 2.5rem;
  /* 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);
  /* Document-actions cluster position (doc-actions widget; off by default).
     Defaults to the slot just inline-left of the settings gear (28px button
     + 12px gap = 2.5rem); host-overridable through the --kpress-host-* hooks,
     same pattern as the settings insets above. */
  --kpress-doc-actions-inset-block: var(
    --kpress-host-doc-actions-inset-block,
    var(--kpress-settings-inset-block)
  );
  --kpress-doc-actions-inset-inline: var(
    --kpress-host-doc-actions-inset-inline,
    calc(var(--kpress-settings-inset-inline) + 2.5rem)
  );
  /* Doc-actions badge: the format letters are the caps-label idiom one notch
     down — slightly smaller than the TOC "Contents" label — so the badge
     reads as an icon, not a heading. The frame corner is square by default
     to match the document's square corners. Both are host-tunable. */
  --kpress-doc-actions-badge-size: calc(var(--kpress-caps-label-size) * 0.85);
  --kpress-doc-actions-badge-radius: var(--kpress-radius-none);
  /* Inline gutter the document reserves for the floating TOC toggle in the
     narrow band. Deliberately a little tighter than the toggle's full
     footprint (0.75rem inset + 32px button): the toggle carries a translucent
     document-background fill, so a slight overlap with the text gutter stays
     legible while phones keep more reading width. A host whose pane inset
     already contributes to the gutter shrinks the reservation by redeclaring
     this on an element scope. See components.css -> .kpress-doc. */
  --kpress-toc-toggle-clearance: 2rem;
  /* 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. Sized with the base * 0.1 top offset
     on the ::before markers so the square's center sits at the crossbar of a
     capital F in the first line, not below it. NOTE for diverging hosts: the
     marker OFFSETS track the base, not this token, so overriding the bullet
     size shifts glyph-to-offset geometry slightly. */
  --kpress-bullet-size: calc(var(--kpress-font-size-base) * 0.9);

  /* ============================== 3. SHAPE ============================== */
  /* 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;

  /* ============================== 4. MOTION ============================= */
  /* 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);

  /* ========================= 5. CHROME (card) ========================== */
  /* 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);

  /* ============================== 6. PRINT ============================= */
  --kpress-print-page-margin: 0.7in;
  --kpress-print-font-size: 11pt;
  --kpress-print-footer: "Formatted by KPress";

  /* =============== 7. COLOR -- theme-independent roles ================= */
  /* Most color roles (--kpress-doc-bg/text/muted/border/link/code-bg + the
     surface hover/selected steps, success, danger) are set per theme x palette in
     the "Color -- palette x theme" 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. The two roles below do NOT vary by theme, so they live here:
       accent     -- a fixed teal used for small accents
       surface-bg -- the subtle fill shared by code blocks, table headers, and the
                     metadata block (an alias of the code bg) so they read as one
                     family; the hover/selected interaction steps that DO vary are
                     set per palette below. */
  --kpress-doc-accent: oklch(51.09% 0.0861 186.4);
  --kpress-doc-surface-bg: var(--kpress-doc-code-bg);

  /* ===================== 8. COMPATIBILITY ALIASES ===================== */
  /* textpress/kash vocabulary mapped onto the --kpress-* tokens above, so styles
     ported from kash keep working. These are ALIASES, not new tokens -- add new
     design values as --kpress-* and alias here only if a ported consumer needs it. */
  --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);
  /* Faint, neutral-reading hairline for inline code, code blocks, tooltips and
     the key-claims/concepts boxes -- modeled on textpress's `hint_gentle`
     (~rgba(155,172,175,0.2)). Derived from the muted gray (not the lighter
     blue-tinted doc-border) at low opacity so it reads gray, not blue. */
  --color-hint-gentle: color-mix(in srgb, var(--kpress-doc-muted) 18%, transparent);
  --color-border-hint: var(--kpress-doc-border);
  --color-border-hairline: var(--kpress-doc-border-hairline);
  --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);
}

/* ===================== DISPLAY/PAGE SWITCHES ========================= */

/* 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));
}

/* ============================================================================
   COLOR -- PALETTE x THEME -- the single source of truth for every theme color.

   Each theme x 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.

   SELECTOR GRAMMAR (the one theme vocabulary): CSS reads exactly ONE input,
   `data-kpress-resolved-theme="light|dark"` -- the resolver's OUTPUT. The mode
   attribute (data-kpress-theme: system|light|dark) is resolver state and never
   keys CSS (enforced by devtools/public_hygiene.py). Every keyed state uses the
   same three selector forms, in one rule:

     :root:where([state])            -- the standalone/host shell: tokens on the
                                        root so body-level chrome (video popover,
                                        future overlays) inherits them; :where()
                                        keeps it at :root's own specificity.
     :where([state]) :is(scopes)     -- ANY ancestor theme scope (:root or a host
                                        wrapper), flattened to (0,1,0) so it wins
                                        over the unkeyed defaults by source order
                                        alone.
     :is(scopes)[state]              -- the ELEMENT scope, (0,2,0): an element's
                                        own attribute beats any ancestor state,
                                        so a stamped element is a coherent theme
                                        island in either direction.

   Light and dark are keyed SYMMETRICALLY (light re-asserts its values; the
   unkeyed defaults remain as the no-attribute fallback, identical to light).
   `color-scheme` is declared in an adjacent rule keyed identically (component
   scopes only -- KPress never restyles a host root's UA behavior), so palette
   and color-scheme cannot resolve to different themes. Palette forms are
   flattened with :where() except the explicit palette x theme element forms,
   so the theme axis outranks a lone palette attribute across scopes. Combined
   states (palette + theme) bind fully when both attributes sit on the SAME
   scope element; splitting axes across scopes intentionally resolves theme
   first. Order in this file is load-bearing: defaults -> light -> warm ->
   dark -> warm-dark. `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, or stamps the attributes and lets
   these blocks resolve. Add a palette = add its two rules.

   ROLE ORDER within each block (a color family taxonomy -- the same grouping the
   playground palette editor uses): foreground (text, muted) -> hairline (border)
   -> interactive (link) -> surfaces (bg, code-bg, surface-hover, surface-selected)
   -> status (success, danger).

   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 / no-attribute state). :root drives
   the standalone shell; .kpress drives the embedded fragment. */
:root,
.kpress {
  --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);
  /* A crisp near-ink rule for deliberate frames (boxed-text): kash's
     border-hairline (hsl 188 2% 34%) was a *dark* thin line, not a faint one. */
  --kpress-doc-border-hairline: oklch(42.00% 0.006 260.7);
  --kpress-doc-link: oklch(45.76% 0.1445 254.7);
  --kpress-doc-bg: oklch(100.00% 0 0);
  --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);
}

/* Default color-scheme, component scopes only (never a host's root). */
.kpress,
.kpress-page-main,
.kpress-tooltip {
  color-scheme: light;
}

/* neutral -- light, keyed: the symmetric twin of the dark block below. Values
   MUST mirror the unkeyed defaults above (plus the light card shadow from the
   Chrome section), so a stamped light element inside a dark scope renders as a
   coherent light island instead of a specificity accident. */
:root:where([data-kpress-resolved-theme="light"]),
:where([data-kpress-resolved-theme="light"]) :is(.kpress, .kpress-page-main, .kpress-tooltip),
:is(.kpress, .kpress-page-main, .kpress-tooltip)[data-kpress-resolved-theme="light"] {
  --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-border-hairline: oklch(42.00% 0.006 260.7);
  --kpress-doc-link: oklch(45.76% 0.1445 254.7);
  --kpress-doc-bg: oklch(100.00% 0 0);
  --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);
  --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);
}

:where([data-kpress-resolved-theme="light"]) :is(.kpress, .kpress-page-main, .kpress-tooltip),
:is(.kpress, .kpress-page-main, .kpress-tooltip)[data-kpress-resolved-theme="light"] {
  color-scheme: light;
}

/* warm -- light values: 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. The lone-element form is :where()-flattened so the dark
   block below outranks a palette attribute split across scopes; the explicit
   warm+light element form binds the combined state at full strength. */
:root:where([data-kpress-palette="warm"]),
:where([data-kpress-palette="warm"]) :is(.kpress, .kpress-page-main, .kpress-tooltip),
:is(.kpress, .kpress-page-main, .kpress-tooltip):where([data-kpress-palette="warm"]),
:is(
  .kpress,
  .kpress-page-main,
  .kpress-tooltip
)[data-kpress-palette="warm"][data-kpress-resolved-theme="light"] {
  --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-border-hairline: oklch(42.00% 0.006 208);
  --kpress-doc-link: oklch(56.60% 0.061 208);
  /* A mild cream -- kept very light (matches textpress's near-white code surface)
     so monospace spans and tooltips read as a gentle tan, not a heavy one. */
  --kpress-doc-code-bg: oklch(98.40% 0.005 83);
}

/* neutral -- dark. */
:root:where([data-kpress-resolved-theme="dark"]),
:where([data-kpress-resolved-theme="dark"]) :is(.kpress, .kpress-page-main, .kpress-tooltip),
:is(.kpress, .kpress-page-main, .kpress-tooltip)[data-kpress-resolved-theme="dark"] {
  --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-border-hairline: oklch(80.00% 0.008 254.1);
  --kpress-doc-link: oklch(76.68% 0.1208 255.4);
  --kpress-doc-bg: oklch(18.98% 0.0094 255.6);
  --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);
}

:where([data-kpress-resolved-theme="dark"]) :is(.kpress, .kpress-page-main, .kpress-tooltip),
:is(.kpress, .kpress-page-main, .kpress-tooltip)[data-kpress-resolved-theme="dark"] {
  color-scheme: dark;
}

/* warm -- dark: same teal accent (lighter) over neutral's dark surfaces. Must
   override the SAME token set as the warm light block so warm light values
   never leak into dark. */
:root:where([data-kpress-resolved-theme="dark"][data-kpress-palette="warm"]),
:where([data-kpress-resolved-theme="dark"][data-kpress-palette="warm"])
  :is(.kpress, .kpress-page-main, .kpress-tooltip),
:is(
  .kpress,
  .kpress-page-main,
  .kpress-tooltip
)[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-border-hairline: oklch(80.00% 0.007 208);
  --kpress-doc-link: oklch(74.90% 0.07 208);
  --kpress-doc-code-bg: oklch(24.16% 0.012 83);
}

/* ============================== WEBFONTS ============================== */

@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;
}
