/*
 * Heyming OS — Brand Foundation (heyming-engineering)
 *
 * Single source of truth for the design language across the marketing
 * site, the OS, and every HOSDL-aware app. Define tokens once, inherit
 * everywhere.
 *
 * Loaded via <link rel="stylesheet" href="/brand.css"> on every page
 * that wears Heyming OS chrome. Apps with their own CSS still benefit
 * from the cascade (scrollbar, focus, color tokens accessible via
 * var()), even if they don't adopt HOSDL components.
 *
 * Phase 1 of the brand pivot: this file replaces the previous sleek-
 * dark-violet brand with a quirky-engineering aesthetic synthesized
 * from Google '99 + Hacker News + Craigslist + GitHub. Paper-cream
 * surfaces, multicolor primary palette, serif display + sans body,
 * blue underlined links, no glass / no gradients / no squircles.
 * See BRAND.md for the full system documentation.
 *
 * For the canonical type, add this to <head> BEFORE this stylesheet:
 *   <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
 *   <link rel="stylesheet"
 *     href="https://fonts.googleapis.com/css2?family=Source+Serif+4:opsz,wght@8..60,400;8..60,600;8..60,700&family=JetBrains+Mono:wght@400;500;600&display=optional">
 * Pages that skip the preconnect / fonts link fall back to system-ui +
 * Georgia — still readable, no FOUT, the brand just looks slightly
 * different on each platform.
 *
 * Note on `display=optional`: chosen over `display=swap` to eliminate the
 * font-swap layout shift that drives a recurring CLS finding in Search
 * Console. With `optional`, the webfont is used only if it arrives within
 * the browser's short block period (~100ms); otherwise the fallback stays
 * for the rest of the page session — no mid-paint swap, no CLS. The font
 * is cached on subsequent visits so most repeat sessions still get the
 * branded type.
 *
 * Accessibility:
 *   - Every color combination on :root has been verified against WCAG 2.2 AA.
 *   - See BRAND.md for the full contrast matrix.
 *   - prefers-reduced-motion, prefers-contrast, and forced-colors honored below.
 *
 * The single invariant: app FUNCTIONALITY is preserved. Brand can repaint
 * anything; behavior must not regress.
 */

:root {
  /* ── Surfaces (paper-cream) ────────────────────────────────────────
   * Light, paper-grade base. surface-0 is the page (cream so it doesn't
   * harsh-flash like #fff); surface-1 is pure white for raised cards
   * and panels; surface-2 is a slightly warmer recess for popovers and
   * menus. The ladder cream → white → cream-warm reads as "physical
   * paper on a desk" rather than "anonymous neutral grey."
   *
   * --surface-glass and --surface-glass-blur are intentionally absent.
   * The new brand bans glass blur. Code that still references
   * --surface-glass falls through to undefined — the audit catches it.
   */
  --surface-0: #fafafa;
  --surface-1: #ffffff;
  --surface-2: #f0eee8;

  /* ── Borders / hairlines (real solid borders) ─────────────────────
   * Solid paper-grey borders, not 8% white-on-dark alpha. Hairline is
   * the default 1px divider; -strong is the 1-1.5px emphasized border
   * (button outlines, table rows, header rules); -accent is the link
   * blue used very sparingly for branded edges.
   */
  --hairline: #e5e5e0;
  --hairline-strong: #c8c8c0;
  --hairline-accent: rgba(26, 115, 232, 0.32);

  /* ── Text (dark on cream) ─────────────────────────────────────────
   * Verified against --surface-0: #fafafa. See BRAND.md contrast matrix.
   */
  --text-1: #1a1a1a; /* AAA, 16.7:1 — primary body & headlines */
  --text-2: #555555; /* AAA,  7.1:1 — secondary copy           */
  --text-3: #6e6e6e; /* AA,   4.9:1 — timestamps, microcopy    */
  --text-on-accent: #ffffff;

  /* ── Accent palette — Google '99 four primaries ─────────────────────
   * The single-violet system is replaced by a disciplined multicolor
   * palette. The four hues are used:
   *   1. Per-letter on the wordmark (the brand signature)
   *   2. As category accents (replaces --cat-game / -utility / -etc)
   *   3. As app-window title-bar tints in the OS (each app picks one)
   *   4. The blue serves as the single CTA / link color for the rest
   *      of the site
   *
   * Values are tuned for AA contrast on --surface-0 paper-cream and
   * for visual harmony with each other (luminance-balanced, evenly
   * spaced around the color wheel). They mirror the exact hex values
   * Google has used for the logo since 1999.
   */
  --accent-blue: #1a73e8;
  --accent-red: #ea4335;
  --accent-yellow: #fbbc04;
  --accent-green: #34a853;

  /* The "primary" alias keeps the old token name so cascade-only apps
   * keep working without rename. On light, foreground (text/icon) and
   * background (button-fill) roles share the same hue — they don't
   * need the two-violet split the old brand did.
   */
  --accent-primary: #1a73e8;
  --accent-primary-hover: #1558b8;
  --accent-primary-soft: #e8f0fe;
  --accent-primary-bg: #1a73e8;
  --accent-primary-bg-hover: #1558b8;

  /* ── Status (Material-aligned for light) ──────────────────────────
   * Verified for AA body on --surface-0:
   *   success 4.8:1, danger 4.6:1, warning fill paired with dark text. */
  --success: #188038;
  --danger: #d93025;
  --warning: #f29900;
  /* Soft tints for inline status banners / pill backgrounds — light-mode
   * tints are 12-15% mixed against white-cream and read as a clear color
   * cue without overwhelming the surface. */
  --success-soft: #e6f4ea;
  --danger-soft: #fce8e6;
  --warning-soft: #fef7e0;

  /* ── Category accents — the four primaries, semantic ─────────────── */
  /* Each app category claims one of the four primaries as its identity
   * color. NOT general brand colors — only used to signal app category
   * on chrome (icon chip, card-hover border, section-header dot). Text
   * and CTAs continue to read --accent-primary (blue). */
  --cat-system: var(--accent-blue);
  --cat-game: var(--accent-red);
  --cat-utility: var(--accent-green);
  --cat-entertainment: var(--accent-yellow);

  --cat-system-soft: #e8f0fe;
  --cat-game-soft: #fce8e6;
  --cat-utility-soft: #e6f4ea;
  --cat-entertainment-soft: #fef7e0;

  --cat-system-hairline: rgba(26, 115, 232, 0.32);
  --cat-game-hairline: rgba(234, 67, 53, 0.32);
  --cat-utility-hairline: rgba(52, 168, 83, 0.32);
  --cat-entertainment-hairline: rgba(251, 188, 4, 0.4);

  /* ── Pure values (canonical, theme-stable) ──────────────────────── */
  --pure-white: #ffffff;
  --pure-black: #000000;

  /* ── Scrims (modal / dialog backdrops) ──────────────────────────── */
  /* Light-mode scrims keep enough alpha that modal content reads clearly.
   * On a cream page, a 45-65% near-black scrim drops the page legibility
   * just far enough to let the modal pop without going pitch-dark behind. */
  --scrim: rgba(26, 26, 26, 0.45);
  --scrim-strong: rgba(26, 26, 26, 0.65);

  /* ── Shadow scale ─────────────────────────────────────────────────
   * Light-mode shadows are much subtler than the old dark-mode ladder.
   * Modals and elevated layers should default to a hairline border
   * instead of a heavy shadow. */
  --shadow-soft: 0 1px 2px rgba(0, 0, 0, 0.06);
  --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.08);
  --shadow-modal: 0 4px 16px rgba(0, 0, 0, 0.12);

  /* Per-app identity palettes (Pac-Man yellow, ghost colors, StepMania
   * arrow tints, ...) deliberately do NOT live in the brand layer.
   * They're declared in <app>/style.css :root or in
   * <app>/<app>-tailwind.js. The brand layer doesn't grow when a new
   * themed app ships. See BRAND.md → "Per-app identity palettes". */

  /* ── Focus ring (dual-ring) ────────────────────────────────────────
   * Inner accent carries the brand; outer halo guarantees contrast.
   * On light surfaces the outer halo is the same accent at 20% alpha
   * — visible against any of the four primaries and against any
   * paper-tone surface. */
  --focus-ring-inner: var(--accent-blue);
  --focus-ring-outer: rgba(26, 115, 232, 0.2);

  /* ── Type stacks ───────────────────────────────────────────────────
   * Display = Source Serif 4 (closest free analogue to Catull, Google's
   *           original wordmark serif), falls back through Lora,
   *           Georgia, Times New Roman.
   * UI      = system-ui (honest GitHub style), falls back through
   *           -apple-system, Segoe UI, Roboto, Verdana.
   * Mono    = JetBrains Mono first, IBM Plex Mono second, then ui-mono. */
  --font-display: 'Source Serif 4', 'Source Serif Pro', 'Lora', Georgia, 'Times New Roman', serif;
  --font-ui: system-ui, -apple-system, 'Segoe UI', Roboto, Verdana, sans-serif;
  --font-mono: 'JetBrains Mono', 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, Consolas,
    monospace;

  /* ── Type scale (px) ──────────────────────────────────────────────── */
  --text-micro: 12px;
  --text-caption: 14px;
  --text-body: 16px;
  --text-h3: 20px;
  --text-h2: 28px;
  --text-h1: 40px;
  --text-display: 56px;
  --text-display-lg: 72px;

  /* ── Radii ────────────────────────────────────────────────────────
   * Squircle 22% deleted — it was the most macOS-coded thing in the
   * brand. New scale is sharp at the bottom (2/4/8) for HN-density,
   * max 8px for cards. Pill stays for input chips and status pills. */
  --radius-sm: 2px;
  --radius: 4px;
  --radius-lg: 8px;
  --radius-xl: 8px;
  --radius-pill: 999px;

  /* ── Motion ──────────────────────────────────────────────────────── */
  --motion-hover: 150ms ease;
  --motion-modal: 220ms ease;
  --motion-slow: 320ms ease;

  /* ── Brand strings ────────────────────────────────────────────────
   * Authoritative tagline — mirrored in os/config.js as OS_TAGLINE
   * and in BRAND.md. If you edit this, edit all three. */
  --brand-tagline: 'A desktop that fits in a tab.';

  /* ── color-scheme ─────────────────────────────────────────────────
   * Tells the browser this surface is light, so native UI (page-level
   * scrollbars, default form controls, autofill bg, the date-picker
   * popover, scrollbar-color "auto", etc.) renders in its light
   * variant. The dark override below flips this to "dark" so OS-native
   * scrollbars and form widgets follow the page theme. Without this
   * declaration browsers default to light, painting a light scrollbar
   * over a near-black page in dark mode. */
  color-scheme: light;
}

/* NyxOS rebrand layer -------------------------------------------------------
 * Keep the upstream static OS architecture intact, but repaint the runtime
 * surfaces as Nyxbrkr Systems: black glass, cyan signal, magenta alerts and
 * green/yellow telemetry. This override intentionally sits last.
 */
:root,
:root[data-theme='dark'] {
  --surface-0: #05020d;
  --surface-1: #09091a;
  --surface-2: #10172a;
  --surface-glass: rgba(5, 2, 13, 0.82);
  --surface-glass-blur: blur(18px);

  --hairline: rgba(0, 255, 224, 0.18);
  --hairline-strong: rgba(0, 255, 224, 0.42);
  --hairline-accent: rgba(255, 43, 242, 0.48);

  --text-1: #f4fbff;
  --text-2: #bfefff;
  --text-3: #7bd8e3;
  --text-on-accent: #03030b;

  --accent-blue: #00aaff;
  --accent-red: #ff315a;
  --accent-yellow: #ffe95c;
  --accent-green: #00ff7f;
  --accent-primary: #00ffe0;
  --accent-primary-hover: #74fff0;
  --accent-primary-soft: rgba(0, 255, 224, 0.12);
  --accent-primary-bg: #00ffe0;
  --accent-primary-bg-hover: #74fff0;

  --success: #00ff7f;
  --danger: #ff315a;
  --warning: #ffe95c;
  --success-soft: rgba(0, 255, 127, 0.14);
  --danger-soft: rgba(255, 49, 90, 0.16);
  --warning-soft: rgba(255, 233, 92, 0.16);

  --cat-system: #00ffe0;
  --cat-game: #ff2bf2;
  --cat-utility: #00aaff;
  --cat-entertainment: #ffe95c;
  --cat-system-soft: rgba(0, 255, 224, 0.12);
  --cat-game-soft: rgba(255, 43, 242, 0.12);
  --cat-utility-soft: rgba(0, 170, 255, 0.12);
  --cat-entertainment-soft: rgba(255, 233, 92, 0.12);
  --cat-system-hairline: rgba(0, 255, 224, 0.42);
  --cat-game-hairline: rgba(255, 43, 242, 0.42);
  --cat-utility-hairline: rgba(0, 170, 255, 0.42);
  --cat-entertainment-hairline: rgba(255, 233, 92, 0.42);

  --scrim: rgba(0, 0, 0, 0.72);
  --scrim-strong: rgba(0, 0, 0, 0.86);
  --shadow-soft: 0 0 18px rgba(0, 255, 224, 0.12);
  --shadow-card: 0 0 24px rgba(0, 255, 224, 0.14), inset 0 0 18px rgba(255, 43, 242, 0.06);
  --shadow-modal: 0 24px 90px rgba(0, 0, 0, 0.7);

  --focus-ring-inner: #00ffe0;
  --focus-ring-outer: rgba(255, 43, 242, 0.32);
  --brand-tagline: 'The Nyxbrkr ecosystem in one command surface.';
  color-scheme: dark;
}

body.hos-page {
  background:
    linear-gradient(rgba(255, 43, 242, 0.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 255, 224, 0.05) 1px, transparent 1px),
    radial-gradient(circle at 18% 12%, rgba(0, 255, 224, 0.18), transparent 36%),
    radial-gradient(circle at 82% 82%, rgba(255, 43, 242, 0.14), transparent 34%),
    var(--surface-0);
  background-size: 28px 28px, 28px 28px, auto, auto, auto;
}

.wordmark,
.hos-hero-wordmark,
.os-setup-welcome-mark img {
  filter: drop-shadow(0 0 18px rgba(0, 255, 224, 0.28));
}

/* ─── Dark theme ─────────────────────────────────────────────────────
 * Theme #2. Two activation paths share the same token block:
 *
 *   1. Manual override — user toggles the home-page switcher, which sets
 *      <html data-theme="dark">. Wins absolute regardless of OS preference.
 *   2. OS preference — when no explicit choice is made, prefers-color-scheme
 *      auto-routes onto these same values. The :not([data-theme="light"])
 *      guard lets the Light option in the home toggle override OS dark.
 *
 * What changes:
 *   - Surfaces invert ladder-wise (deep ink page, slightly-lifted cards,
 *     a recess one step further). Not pure black: harsh CRT, fails
 *     gradient-soft shadows.
 *   - Text bumps to a near-white off the GitHub dimmed scale, with
 *     secondary/tertiary stepped to keep AA on surface-1.
 *   - Accent blue gets lifted (#4f8cff) so links clear AA on dark cards
 *     without driving people insane the way pure-blue links do on dark.
 *   - Status colors lift to their dark-mode tier; *-soft tints become
 *     deep tinted slabs sitting two notches off the page.
 *   - Scrim alpha increases so modals still part the surface visibly
 *     on a near-black page.
 *   - Shadows deepen but stay pure-black — see "pure-black/white policy"
 *     in BRAND.md, those tokens are theme-stable.
 *
 * What does NOT change:
 *   - --pure-white / --pure-black (theme-stable primitives).
 *   - Per-app identity palettes (declared in each themed app's own
 *     style.css or <app>-tailwind.js — outside the brand layer).
 *   - Type stacks and motion durations.
 *   - Radii.
 *   - --brand-tagline.
 *
 * Cascade contract: any app that paints chrome via brand tokens
 * (var(--surface-0), var(--text-1), var(--accent-primary), ...)
 * dark-modes for free. Apps that hard-code colors (identity-bound
 * apps in BRAND.md "Tier-3 carve-outs" and HOSDL.md "Tier
 * classification") stay as-is by design. */
:root[data-theme='dark'] {
  /* Native scrollbars + default form controls render dark. See the
   * matching `color-scheme: light` on :root above. */
  color-scheme: dark;

  --surface-0: #0e1217;
  --surface-1: #161b22;
  --surface-2: #1f262f;

  --hairline: #2a3138;
  --hairline-strong: #3a434b;
  --hairline-accent: rgba(96, 165, 250, 0.4);

  --text-1: #e6edf3; /* AAA, ~14.7:1 on surface-1 */
  --text-2: #aab1b9; /*  AA,  ~7.7:1 on surface-1 */
  --text-3: #8b949e; /*  AA,  ~5.0:1 on surface-1 */
  --text-on-accent: #ffffff;

  --accent-blue: #4f8cff;
  --accent-red: #ff6961;
  --accent-yellow: #f5c45e;
  --accent-green: #4cc26a;

  --accent-primary: #4f8cff;
  --accent-primary-hover: #75a5ff;
  --accent-primary-soft: #1a2740;
  --accent-primary-bg: #4f8cff;
  --accent-primary-bg-hover: #75a5ff;

  --success: #56d364;
  --danger: #f85149;
  --warning: #f0b73f;
  --success-soft: #1a2e1f;
  --danger-soft: #2d1b1d;
  --warning-soft: #2d2418;

  --cat-system: var(--accent-blue);
  --cat-game: var(--accent-red);
  --cat-utility: var(--accent-green);
  --cat-entertainment: var(--accent-yellow);

  --cat-system-soft: #1a2740;
  --cat-game-soft: #2d1b1d;
  --cat-utility-soft: #1a2e1f;
  --cat-entertainment-soft: #2d2418;

  --cat-system-hairline: rgba(79, 140, 255, 0.4);
  --cat-game-hairline: rgba(255, 105, 97, 0.4);
  --cat-utility-hairline: rgba(76, 194, 106, 0.4);
  --cat-entertainment-hairline: rgba(245, 196, 94, 0.45);

  --scrim: rgba(0, 0, 0, 0.65);
  --scrim-strong: rgba(0, 0, 0, 0.8);

  --shadow-soft: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.5);
  --shadow-modal: 0 4px 16px rgba(0, 0, 0, 0.65);

  --focus-ring-inner: var(--accent-blue);
  --focus-ring-outer: rgba(79, 140, 255, 0.32);
}

/* prefers-color-scheme: dark — apply the same overrides when the OS is
 * dark AND the user hasn't explicitly picked Light from the home toggle.
 * Block must mirror :root[data-theme="dark"] above; if you edit one,
 * edit the other (single source of dark-mode truth). */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    color-scheme: dark;

    --surface-0: #0e1217;
    --surface-1: #161b22;
    --surface-2: #1f262f;

    --hairline: #2a3138;
    --hairline-strong: #3a434b;
    --hairline-accent: rgba(96, 165, 250, 0.4);

    --text-1: #e6edf3;
    --text-2: #aab1b9;
    --text-3: #8b949e;
    --text-on-accent: #ffffff;

    --accent-blue: #4f8cff;
    --accent-red: #ff6961;
    --accent-yellow: #f5c45e;
    --accent-green: #4cc26a;

    --accent-primary: #4f8cff;
    --accent-primary-hover: #75a5ff;
    --accent-primary-soft: #1a2740;
    --accent-primary-bg: #4f8cff;
    --accent-primary-bg-hover: #75a5ff;

    --success: #56d364;
    --danger: #f85149;
    --warning: #f0b73f;
    --success-soft: #1a2e1f;
    --danger-soft: #2d1b1d;
    --warning-soft: #2d2418;

    --cat-system-soft: #1a2740;
    --cat-game-soft: #2d1b1d;
    --cat-utility-soft: #1a2e1f;
    --cat-entertainment-soft: #2d2418;

    --cat-system-hairline: rgba(79, 140, 255, 0.4);
    --cat-game-hairline: rgba(255, 105, 97, 0.4);
    --cat-utility-hairline: rgba(76, 194, 106, 0.4);
    --cat-entertainment-hairline: rgba(245, 196, 94, 0.45);

    --scrim: rgba(0, 0, 0, 0.65);
    --scrim-strong: rgba(0, 0, 0, 0.8);

    --shadow-soft: 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.5);
    --shadow-modal: 0 4px 16px rgba(0, 0, 0, 0.65);

    --focus-ring-outer: rgba(79, 140, 255, 0.32);
  }
}

/* ─── prefers-contrast: more ─────────────────────────────────────────
 * Bump --text-3 to the higher-contrast tier and thicken hairlines
 * for users who need it. Light- and dark-tier hairlines tracked
 * separately because the dark hairline range starts darker. */
@media (prefers-contrast: more) {
  :root {
    --text-3: var(--text-2);
    --hairline: #b8b8b0;
    --hairline-strong: #888880;
  }
  :root[data-theme='dark'] {
    --text-3: var(--text-2);
    --hairline: #4a5159;
    --hairline-strong: #6a737d;
  }
}
@media (prefers-contrast: more) and (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --text-3: var(--text-2);
    --hairline: #4a5159;
    --hairline-strong: #6a737d;
  }
}

/* ─── prefers-reduced-motion ─────────────────────────────────────────
 * Strict: kill all token-driven transitions and all running animations.
 * Components that read from --motion-* automatically inherit; the
 * universal-selector override catches everything else. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --motion-hover: 0ms linear;
    --motion-modal: 0ms linear;
    --motion-slow: 0ms linear;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ─── forced-colors (Windows High Contrast) ──────────────────────────
 * Step out of the way: let the user's OS palette drive everything. */
@media (forced-colors: active) {
  :root {
    --surface-0: Canvas;
    --surface-1: Canvas;
    --surface-2: Canvas;
    --hairline: CanvasText;
    --hairline-strong: CanvasText;
    --text-1: CanvasText;
    --text-2: CanvasText;
    --text-3: CanvasText;
    --text-on-accent: HighlightText;
    --accent-primary: LinkText;
    --accent-primary-bg: Highlight;
    --focus-ring-inner: Highlight;
    --focus-ring-outer: CanvasText;
  }
}

/* ─── Page-level opt-in ──────────────────────────────────────────────
 * Pages add class="hos-page" to <html> or <body> to inherit the new
 * paper-cream surface, dark text, and quirky-engineering type stack.
 *
 * The new brand is gradient-free. Where the previous version painted
 * a faint dual-glow violet wash to lift the page, the new version
 * just paints solid --surface-0 with a 1px solid hairline at top —
 * a subtle Google/HN-style header-rule that signals "engineering
 * project page." Apps that want a more saturated header bar add
 * a child <header> with their own background or use the .hos-status-strip
 * utility at the bottom.
 */
.hos-page {
  background: var(--surface-0);
  border-top: 1px solid var(--hairline);
  color: var(--text-1);
  font-family: var(--font-ui);
  font-size: var(--text-body);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* ─── Type scale utilities ─────────────────────────────────────────── */
.text-display-lg {
  font-family: var(--font-display);
  font-size: var(--text-display-lg);
  line-height: 1.06;
  letter-spacing: -0.02em;
  font-weight: 700;
}
.text-display {
  font-family: var(--font-display);
  font-size: var(--text-display);
  line-height: 1.1;
  letter-spacing: -0.015em;
  font-weight: 700;
}
.text-h1 {
  font-family: var(--font-display);
  font-size: var(--text-h1);
  line-height: 1.2;
  letter-spacing: -0.005em;
  font-weight: 700;
}
.text-h2 {
  font-family: var(--font-display);
  font-size: var(--text-h2);
  line-height: 1.28;
  font-weight: 600;
}
.text-h3 {
  font-size: var(--text-h3);
  line-height: 1.4;
  font-weight: 600;
}
.text-body {
  font-size: var(--text-body);
  line-height: 1.5;
}
.text-caption {
  font-size: var(--text-caption);
  line-height: 1.43;
}
.text-micro {
  font-size: var(--text-micro);
  line-height: 1.33;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 600;
}
.text-mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}
.text-muted {
  color: var(--text-2);
}
.text-subtle {
  color: var(--text-3);
}

/* ─── Surface utilities ────────────────────────────────────────────── */
.surface-0 {
  background: var(--surface-0);
  color: var(--text-1);
}
.surface-1 {
  background: var(--surface-1);
  color: var(--text-1);
  border: 1px solid var(--hairline);
}
.surface-2 {
  background: var(--surface-2);
  color: var(--text-1);
  border: 1px solid var(--hairline);
}
/* .surface-glass DELETED — no glass on the new brand. Code that still
 * references --surface-glass falls through to undefined; audit catches it. */

/* ─── Status / engineering footer ──────────────────────────────────────
 * HN/Google '99-style monospace metadata strip. Place it at the bottom
 * of any .hos-page. Format:
 *   <p class="hos-status-strip">48 apps · last updated 2026-05-24 ·
 *     <a href="...">github</a> · <a href="/sitemap.xml">sitemap</a></p> */
.hos-status-strip {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  color: var(--text-3);
  letter-spacing: 0;
  text-transform: none;
  padding: 8px 0;
  margin: 24px 0 0;
  border-top: 1px solid var(--hairline);
}
.hos-status-strip a {
  color: var(--accent-blue);
}

/* ─── Focus dual-ring (site-wide) ────────────────────────────────────
 * Inner accent + outer halo. Light-mode tuning: outer is the same
 * accent at 20% alpha so it reads on every paper surface and against
 * any of the four primary saturated fills. */
:focus-visible {
  outline: 2px solid var(--focus-ring-inner);
  outline-offset: 2px;
  box-shadow: 0 0 0 4px var(--focus-ring-outer);
}

/* ─── App-icon frame ─────────────────────────────────────────────────
 * The single visual primitive that turns an emoji avatar into an OS
 * app icon. The new brand drops the squircle 22% radius (too Apple-
 * coded) and uses a square card with a 4px radius and a hairline
 * border — like a chip in a directory listing. */
.app-icon-frame {
  --icon-frame-size: 48px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--icon-frame-size);
  height: var(--icon-frame-size);
  border-radius: var(--radius);
  background: var(--surface-1);
  border: 1px solid var(--hairline);
  font-size: calc(var(--icon-frame-size) * 0.6);
  line-height: 1;
  user-select: none;
}

/* ─── Tagline lockup ───────────────────────────────────────────────── */
.hos-lockup {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
}
.hos-lockup-tagline {
  font-family: var(--font-display);
  font-size: var(--text-h3);
  line-height: 1.3;
  color: var(--text-2);
  margin: 0;
  letter-spacing: 0;
  font-style: italic;
}
.hos-lockup-tagline::before {
  content: var(--brand-tagline);
}
.hos-lockup-tagline:not(:empty)::before {
  content: none;
}

/* ─── Wordmark sizing utilities ──────────────────────────────────────
 * The wordmark SVG ships per-letter primary-color fills baked in (see
 * brand/heyming-os-wordmark.svg). These classes drive width; height
 * stays proportional. No currentColor — per-letter colors can't inherit
 * from a single CSS color property. */
.wordmark {
  display: inline-block;
  width: 220px;
  height: auto;
}
.wordmark-sm {
  width: 140px;
}
.wordmark-lg {
  width: 320px;
}
.wordmark-xl {
  width: 480px;
}

/* ─── Page scrollbar (webkit) ────────────────────────────────────────
 * Light-mode scrollbars: paper-cream track, surface-2-strong thumb,
 * blue accent on hover. */
.hos-page ::-webkit-scrollbar {
  width: 12px;
  height: 12px;
  background: var(--surface-0);
}
.hos-page ::-webkit-scrollbar-thumb {
  background: var(--hairline-strong);
  border-radius: var(--radius-pill);
  border: 3px solid var(--surface-0);
}
.hos-page ::-webkit-scrollbar-thumb:hover {
  background: var(--accent-blue);
}

/* ─── Selection ──────────────────────────────────────────────────── */
.hos-page ::selection {
  background: var(--accent-primary-soft);
  color: var(--text-1);
}

/* ─── Form element defaults (zero specificity via :where) ────────────
 *
 * Every app that loads brand.css gets sensible brand-styled defaults for
 * bare <button>, <input>, <select>, <textarea>, and <a>. The rules use
 * `:where(selector)` so they evaluate at specificity (0,0,0) — any app
 * stylesheet with a real selector automatically wins. No `!important`,
 * no `.hos-page` opt-in required. Apps that already paint their own
 * controls are unaffected.
 *
 * Defaults are tuned for a light surface — buttons and inputs sit on
 * white surface-1 cards over a cream surface-0 page, with hairline
 * borders and dark text. */

:where(button, input, select, textarea) {
  font-family: inherit;
  font-size: inherit;
  color: inherit;
  line-height: 1.4;
}

/* Buttons — secondary-style by default: white surface, hairline
 * border, blue-link hover. Apps with primary CTAs typically reach for
 * accent-primary-bg via their own class (or .hos-btn-* helpers in
 * heyming-shell.css). */
:where(button) {
  background: var(--surface-1);
  color: var(--text-1);
  border: 1px solid var(--hairline-strong);
  border-radius: var(--radius);
  padding: 0.5em 1em;
  cursor: pointer;
  transition: background var(--motion-hover), border-color var(--motion-hover),
    color var(--motion-hover);
}
:where(button:hover:not(:disabled)) {
  background: var(--accent-primary-soft);
  border-color: var(--accent-primary);
  color: var(--accent-primary-hover);
}
:where(button:active:not(:disabled)) {
  background: var(--accent-primary-bg);
  border-color: var(--accent-primary-bg);
  color: var(--text-on-accent);
}
:where(button:disabled) {
  opacity: 0.45;
  cursor: not-allowed;
}

/* Text-flavored inputs + textarea + select — white card on cream page. */
:where(
    input:not([type='checkbox']):not([type='radio']):not([type='range']):not([type='color']):not(
        [type='file']
      ):not([type='submit']):not([type='button']):not([type='reset']):not([type='image']),
    textarea,
    select
  ) {
  background: var(--surface-1);
  color: var(--text-1);
  border: 1px solid var(--hairline-strong);
  border-radius: var(--radius);
  /* 16px font-size on mobile prevents iOS zoom-on-focus. */
  font-size: max(1em, 16px);
  padding: 0.5em 0.75em;
  transition: border-color var(--motion-hover), box-shadow var(--motion-hover);
}

:where(input::placeholder, textarea::placeholder) {
  color: var(--text-3);
}

:where(input:focus, textarea:focus, select:focus) {
  border-color: var(--accent-blue);
}

/* Native <select> chevron — link-blue triangle on white. */
:where(select) {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231a73e8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
  background-repeat: no-repeat;
  background-position: right 0.65em center;
  background-size: 14px;
  padding-right: 2.25em;
}
:where(select option) {
  background: var(--surface-1);
  color: var(--text-1);
}

/* Anchors — blue underlined, visited purple, hover yellow flash. The
 * non-negotiable engineering-page link convention. */
:where(a) {
  color: var(--accent-blue);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
  transition: color var(--motion-hover), background var(--motion-hover);
}
:where(a:visited) {
  color: #660099;
}
:where(a:hover) {
  color: var(--accent-primary-hover);
  background: #fffacd;
}

/* Dark-theme link tunings: academic purple is unreadable on near-black,
 * and HN-yellow hover fill burns the eye; lift the visited hue toward
 * a soft lilac and swap the hover backsplash for a deep amber that
 * still recalls the engineering-page hover convention. Order: explicit
 * data-theme="dark" wins; OS-level prefers-color-scheme: dark applies
 * when no explicit theme override is set.
 *
 * The whole selector is wrapped in :where() so specificity stays at
 * (0,0,0) — same contract as the light-mode rule above. Without the
 * wrap, `:root[data-theme='dark']` adds (0,2,0) and beats class-level
 * overrides like `.hos-cta-primary { color: var(--text-on-accent) }`,
 * which produced a visible visited-state bleed: the "Launch Heyming
 * OS" CTA flipped from white text to lilac after first click in dark
 * mode. App rules must always win on specificity. */
:where(:root[data-theme='dark'] a:visited) {
  color: #c290e8;
}
:where(:root[data-theme='dark'] a:hover) {
  color: var(--accent-primary-hover);
  background: #3a2f00;
}
@media (prefers-color-scheme: dark) {
  :where(:root:not([data-theme='light']) a:visited) {
    color: #c290e8;
  }
  :where(:root:not([data-theme='light']) a:hover) {
    color: var(--accent-primary-hover);
    background: #3a2f00;
  }
}

/* Checkbox / radio / range — accent-color tint via the native widget. */
:where(input[type='checkbox'], input[type='radio'], input[type='range']) {
  accent-color: var(--accent-blue);
}

/* fieldset / legend — quiet defaults. */
:where(fieldset) {
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  padding: 0.75em 1em 1em;
  margin: 0 0 1em;
}
:where(legend) {
  padding: 0 0.4em;
  color: var(--text-2);
  font-size: var(--text-caption);
  font-weight: 600;
}

/* hr — replace the heavy default groove with a hairline. */
:where(hr) {
  border: 0;
  border-top: 1px solid var(--hairline);
  margin: 1.25em 0;
}

/* code / kbd — quiet glyph treatment with the mono stack. */
:where(code, kbd, samp) {
  font-family: var(--font-mono);
  font-size: 0.9em;
}
:where(kbd) {
  background: var(--surface-2);
  color: var(--text-1);
  border: 1px solid var(--hairline-strong);
  border-bottom-width: 2px;
  border-radius: var(--radius);
  padding: 0.1em 0.4em;
  font-size: 0.85em;
}

/* Final NyxOS runtime paint pass. Must stay last. */
:root,
:root[data-theme='dark'],
:root:not([data-theme='light']) {
  --surface-0: #05020d;
  --surface-1: #09091a;
  --surface-2: #10172a;
  --surface-glass: rgba(5, 2, 13, 0.82);
  --surface-glass-blur: blur(18px);
  --hairline: rgba(0, 255, 224, 0.18);
  --hairline-strong: rgba(0, 255, 224, 0.42);
  --hairline-accent: rgba(255, 43, 242, 0.48);
  --text-1: #f4fbff;
  --text-2: #bfefff;
  --text-3: #7bd8e3;
  --text-on-accent: #03030b;
  --accent-blue: #00aaff;
  --accent-red: #ff315a;
  --accent-yellow: #ffe95c;
  --accent-green: #00ff7f;
  --accent-primary: #00ffe0;
  --accent-primary-hover: #74fff0;
  --accent-primary-soft: rgba(0, 255, 224, 0.12);
  --accent-primary-bg: #00ffe0;
  --accent-primary-bg-hover: #74fff0;
  --success: #00ff7f;
  --danger: #ff315a;
  --warning: #ffe95c;
  --scrim: rgba(0, 0, 0, 0.72);
  --scrim-strong: rgba(0, 0, 0, 0.86);
  --focus-ring-inner: #00ffe0;
  --focus-ring-outer: rgba(255, 43, 242, 0.32);
  --brand-tagline: 'The Nyxbrkr ecosystem in one command surface.';
  color-scheme: dark;
}
