/* ============================================================================
   space.css — Premium Positioning Space · shared design system ("Instrument")
   ----------------------------------------------------------------------------
   ONE source of truth for the visual language across every page. It works by
   redefining the CSS custom properties the pages already use (--bg, --surface,
   --accent, --text, --border, --serif, --mono, --sans ...), so linking this file
   re-skins a page without touching its markup or JS.

   Load LAST in <head> (after any inline <style>) so these token values win by
   source order. Higher-specificity :root[data-theme=...] selectors also guard
   against load-order surprises.

   Direction: dark-primary "instrument" — deep navy ground, a single signal-cyan
   accent, monospace for structure. This refines the existing dark "brand" theme
   (which the app already defaults to), so hardcoded per-page colors that were
   tuned for the old dark ground stay harmonious.

   Themes:
     default (no attr) + [data-theme="brand"]  -> Instrument dark   (primary)
     [data-theme=""]   + [data-theme="light"]  -> Instrument light  (toggle)
   ========================================================================== */

/* ---- Fonts: reuse the faces already loaded per-page (Instrument Sans + DM
   Mono). --serif is deliberately redirected to the sans stack: the DM Serif
   Display headings were the single biggest "AI-built" tell. ---- */

:root,
:root[data-theme="brand"] {
  --bg:            #0A1120;
  --surface:       #111C2E;
  --surface2:      #18273D;
  --border:        #22344E;
  --border-strong: #2E4A6E;
  --text:          #E8F0FA;
  --text-2:        #8CA3BD;
  --text-3:        #5C748F;
  --accent:        #39D0D8;
  --accent-2:      #1C8B93;

  --ok:            #5FD08A;
  --warn:          #E7B463;
  --crit:          #E77A72;

  --sans:  'Instrument Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --mono:  'DM Mono', ui-monospace, 'SF Mono', 'SFMono-Regular', Menlo, Consolas, monospace;
  /* --display: the characterful heading face (self-hosted Space Grotesk, a
     technical grotesque cut from the same lineage as DM Mono). --serif is kept
     as an alias so every existing `var(--serif)` heading picks it up at once. */
  --display: 'Space Grotesk', var(--sans);
  --serif: var(--display);

  --radius:    6px;
  --radius-lg: 10px;
  --shadow:    0 18px 50px -24px rgba(0,0,0,0.65);
  /* --shadow-sm: a light card-lift (kept faint so surfaces read as layered, not
     heavy). Dark grounds hide drop shadows, so there the top-edge highlight does
     most of the lifting. */
  --shadow-sm: 0 1px 3px rgba(0,0,0,0.30), 0 8px 22px -12px rgba(0,0,0,0.50);

  /* Instrument signature: a faint coordinate-grid backdrop. Token-driven so it
     retunes per theme. */
  --grid-cell: 34px;
  --grid-line: color-mix(in srgb, var(--border) 62%, transparent);

  color-scheme: dark;
}

:root[data-theme=""],
:root[data-theme="light"] {
  --bg:            #EEF1F5;
  --surface:       #FFFFFF;
  --surface2:      #F4F7FB;
  --border:        #D6DEEA;
  --border-strong: #B7C4D6;
  --text:          #0F1B2E;
  --text-2:        #4A5A72;
  --text-3:        #7688A0;
  --accent:        #0E7C9B;
  --accent-2:      #0B5F77;

  --ok:            #1E9E63;
  --warn:          #B9821F;
  --crit:          #C0392B;

  --shadow: 0 14px 40px -22px rgba(20,40,70,0.35);
  --shadow-sm: 0 1px 3px rgba(20,40,70,0.06), 0 8px 22px -12px rgba(20,40,70,0.16);

  /* Light grounds swallow faint hairlines, so the grid leans on the stronger
     border token to stay legible without shouting. */
  --grid-line: color-mix(in srgb, var(--border-strong) 42%, transparent);
  color-scheme: light;
}

/* ---- Global base polish (light-touch; token-driven so it follows the theme) ---- */

html { -webkit-text-size-adjust: 100%; }
body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }

/* Headings render in the display face (Space Grotesk) via the --display token.
   It carries its own personality, so it wants slightly less negative tracking
   than a neutral grotesque and a solid mid weight so it reads as deliberate. */
h1, h2, h3,
.greeting, .hero-title, .page-title, .section-title {
  font-family: var(--display);
  letter-spacing: -0.015em;
}
h1, h2, .greeting, .hero-title, .page-title { font-weight: 600; }

/* Digits that line up in columns (KPIs, tables) should be tabular. */
.tnum, .num, .kpi-value, [data-tnum] { font-variant-numeric: tabular-nums; }

/* Accessible keyboard focus everywhere (many pages define none). */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 3px;
}

/* Text selection uses the accent, not the browser default blue. */
::selection { background: rgba(57, 208, 216, 0.28); color: var(--text); }
:root[data-theme=""] ::selection,
:root[data-theme="light"] ::selection { background: rgba(14, 124, 155, 0.22); }

/* Themed scrollbars so the chrome matches the ground. */
* { scrollbar-color: var(--border-strong) transparent; scrollbar-width: thin; }
*::-webkit-scrollbar { width: 11px; height: 11px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border: 3px solid transparent;
  background-clip: content-box;
  border-radius: 999px;
}
*::-webkit-scrollbar-thumb:hover { background: var(--text-3); background-clip: content-box; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ============================================================================
   Optional shared primitives — opt-in classes (prefixed `sp-`) for pages being
   upgraded to the full treatment. They never collide with existing page styles.
   ========================================================================== */

/* ── Nav chrome ────────────────────────────────────────────────────────────
   Modernise the top-bar controls that every page shares (back / theme / sign
   out / settings / admin). Per-page rules style these as thin outlined mono
   pills (the "old" look); these :root-prefixed selectors (0,2,0) out-specify
   them to give clean filled chips with a crisp accent hover, without touching
   any page's markup. feedback.js sets only background-color on brand pages, so
   its subtle blurred fill is preserved. */
:root .back-btn, :root .back-portal-btn, :root .theme-btn, :root .signout-link,
:root .ctrl-btn, :root .settings-btn, :root .admin-btn, :root .topbar-btn,
:root .nav-btn {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--text-2);
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 7px 14px;
  transition: background .12s, border-color .12s, color .12s;
}
:root .back-btn:hover, :root .back-portal-btn:hover, :root .theme-btn:hover,
:root .signout-link:hover, :root .ctrl-btn:hover, :root .settings-btn:hover,
:root .admin-btn:hover, :root .topbar-btn:hover, :root .nav-btn:hover {
  color: var(--text);
  border-color: var(--accent);
  background: var(--surface);
}

/* Refined top bar: hairline base, slight translucency + blur so content scrolls
   under it cleanly. */
:root .topbar {
  background: color-mix(in srgb, var(--surface) 84%, transparent);
  border-bottom: 1px solid var(--border);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}

/* Shared sizing for the line-icon SVGs that replaced emoji in nav/dept cards.
   (The `sales.html`/hub pages use .nav-card-icon; sizing centralised here so
   every hub renders icons identically.) */
.nav-card-icon { color: var(--text-2); transition: color .15s; }
.nav-card-icon svg { width: 24px; height: 24px; display: block; }
.nav-card:hover .nav-card-icon,
a.nav-card:hover .nav-card-icon { color: var(--accent); }

.sp-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px;
}

.sp-label {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-2);
}

/* Status dot — the professional replacement for 🔴/🟡/🟢 status emoji.
   Usage: <span class="sp-dot crit"></span> Hot   (good | warn | crit | info) */
.sp-dot {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  background: var(--text-3); vertical-align: middle;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--text-3) 16%, transparent);
}
.sp-dot.good { background: var(--ok);     box-shadow: 0 0 0 3px color-mix(in srgb, var(--ok) 18%, transparent); }
.sp-dot.warn { background: var(--warn);   box-shadow: 0 0 0 3px color-mix(in srgb, var(--warn) 18%, transparent); }
.sp-dot.crit { background: var(--crit);   box-shadow: 0 0 0 3px color-mix(in srgb, var(--crit) 18%, transparent); }
.sp-dot.info { background: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent); }

.sp-pill {
  display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--mono); font-size: 11px; font-weight: 500;
  padding: 2px 8px; border-radius: 4px;
  background: rgba(124,147,173,0.14); color: var(--text-2);
}
.sp-pill.ok   { color: var(--ok);   background: color-mix(in srgb, var(--ok) 15%, transparent); }
.sp-pill.warn { color: var(--warn); background: color-mix(in srgb, var(--warn) 15%, transparent); }
.sp-pill.crit { color: var(--crit); background: color-mix(in srgb, var(--crit) 15%, transparent); }

.sp-btn {
  font-family: var(--mono); font-size: 12px;
  color: var(--text-2); background: none;
  border: 1px solid var(--border-strong);
  padding: 7px 14px; border-radius: var(--radius);
  cursor: pointer; text-decoration: none;
  transition: border-color .12s, color .12s, background .12s;
}
.sp-btn:hover { border-color: var(--accent); color: var(--text); }
.sp-btn.primary { background: var(--accent); border-color: var(--accent); color: #04222b; font-weight: 600; }
.sp-btn.primary:hover { background: var(--accent-2); border-color: var(--accent-2); color: #fff; }

/* ── Icon system ───────────────────────────────────────────────────────────
   Line icons via CSS mask, coloured by currentColor so they theme with text.
   Usage: <span class="i-search"></span> (sizes to 1em; add font-size to scale).
   Generated by scratchpad/gen-icons.js — re-run to regenerate. */
[class^="i-"], [class*=" i-"] {
  display: inline-block; width: 1em; height: 1em; vertical-align: -0.14em;
  background-color: currentColor; flex: none;
  -webkit-mask: var(--i) center / contain no-repeat;
          mask: var(--i) center / contain no-repeat;
}
.i-search { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Ccircle%20cx%3D%2211%22%20cy%3D%2211%22%20r%3D%226%22%2F%3E%3Cpath%20d%3D%22M20%2020l-4.2-4.2%22%2F%3E%3C%2Fsvg%3E"); }
.i-lock { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Crect%20x%3D%225%22%20y%3D%2211%22%20width%3D%2214%22%20height%3D%229%22%20rx%3D%221.6%22%2F%3E%3Cpath%20d%3D%22M8%2011V8a4%204%200%200%201%208%200v3%22%2F%3E%3C%2Fsvg%3E"); }
.i-unlock { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Crect%20x%3D%225%22%20y%3D%2211%22%20width%3D%2214%22%20height%3D%229%22%20rx%3D%221.6%22%2F%3E%3Cpath%20d%3D%22M8%2011V8a4%204%200%200%201%207.5-1.7%22%2F%3E%3C%2Fsvg%3E"); }
.i-trend-up { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M4%2015l5-5%203%203%206-7%22%2F%3E%3Cpath%20d%3D%22M14%206h5v5%22%2F%3E%3C%2Fsvg%3E"); }
.i-trend-down { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M4%209l5%205%203-3%206%207%22%2F%3E%3Cpath%20d%3D%22M14%2018h5v-5%22%2F%3E%3C%2Fsvg%3E"); }
.i-target { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%228%22%2F%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%224%22%2F%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%220.9%22%2F%3E%3C%2Fsvg%3E"); }
.i-bars { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M4%2020h16%22%2F%3E%3Crect%20x%3D%225%22%20y%3D%2212%22%20width%3D%223.4%22%20height%3D%226%22%2F%3E%3Crect%20x%3D%2210.3%22%20y%3D%228%22%20width%3D%223.4%22%20height%3D%2210%22%2F%3E%3Crect%20x%3D%2215.6%22%20y%3D%224%22%20width%3D%223.4%22%20height%3D%2214%22%2F%3E%3C%2Fsvg%3E"); }
.i-clipboard { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Crect%20x%3D%225%22%20y%3D%224.5%22%20width%3D%2214%22%20height%3D%2216.5%22%20rx%3D%221.6%22%2F%3E%3Cpath%20d%3D%22M9%204.5V3.6a1%201%200%200%201%201-1h4a1%201%200%200%201%201%201v.9%22%2F%3E%3C%2Fsvg%3E"); }
.i-note { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M6%203h9l3%203v15H6z%22%2F%3E%3Cpath%20d%3D%22M9%209h6M9%2013h6M9%2017h4%22%2F%3E%3C%2Fsvg%3E"); }
.i-edit { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M4%2020h4L19%209l-4-4L4%2016z%22%2F%3E%3Cpath%20d%3D%22M14%206l4%204%22%2F%3E%3C%2Fsvg%3E"); }
.i-calendar { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Crect%20x%3D%224%22%20y%3D%225%22%20width%3D%2216%22%20height%3D%2216%22%20rx%3D%221.5%22%2F%3E%3Cpath%20d%3D%22M4%209h16M8%203v4M16%203v4%22%2F%3E%3C%2Fsvg%3E"); }
.i-chat { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M5%205h14a1%201%200%200%201%201%201v9a1%201%200%200%201-1%201H9l-4%204V6a1%201%200%200%201%201-1z%22%2F%3E%3C%2Fsvg%3E"); }
.i-doc { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M6%203h9l3%203v15H6z%22%2F%3E%3Cpath%20d%3D%22M9%2012h6M9%2016h4%22%2F%3E%3C%2Fsvg%3E"); }
.i-wrench { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M15.5%205.5a4%204%200%200%200-5.3%204.9l-6%206%202.4%202.4%206-6a4%204%200%200%200%204.9-5.3l-2.6%202.6-1.8-.6-.6-1.8z%22%2F%3E%3C%2Fsvg%3E"); }
.i-bot { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Crect%20x%3D%225%22%20y%3D%228%22%20width%3D%2214%22%20height%3D%2211%22%20rx%3D%222%22%2F%3E%3Cpath%20d%3D%22M12%204v4M9.5%2013v1.4M14.5%2013v1.4M9.5%2017h5%22%2F%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%223.4%22%20r%3D%221.1%22%2F%3E%3C%2Fsvg%3E"); }
.i-people { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Ccircle%20cx%3D%229%22%20cy%3D%229%22%20r%3D%222.6%22%2F%3E%3Cpath%20d%3D%22M3.8%2018a5.2%205.2%200%200%201%2010.4%200M15%207.2a2.6%202.6%200%200%201%200%205M16%2013.4a5.2%205.2%200%200%201%204%204.6%22%2F%3E%3C%2Fsvg%3E"); }
.i-person { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%228%22%20r%3D%223.1%22%2F%3E%3Cpath%20d%3D%22M5.5%2019a6.5%206.5%200%200%201%2013%200%22%2F%3E%3C%2Fsvg%3E"); }
.i-book { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M12%206v14M12%206C10%204.5%207.5%204%205%204.5V18c2.5-.5%205%200%207%201.5M12%206c2-1.5%204.5-2%207-1.5V18c-2.5-.5-5%200-7%201.5%22%2F%3E%3C%2Fsvg%3E"); }
.i-map { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M9%204L4%206v14l5-2%206%202%205-2V4l-5%202-6-2z%22%2F%3E%3Cpath%20d%3D%22M9%204v14M15%206v14%22%2F%3E%3C%2Fsvg%3E"); }
.i-signal { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%221.4%22%2F%3E%3Cpath%20d%3D%22M8.6%208.6a5%205%200%200%200%200%206.8M15.4%208.6a5%205%200%200%201%200%206.8M5.6%205.6a9%209%200%200%200%200%2012.8M18.4%205.6a9%209%200%200%201%200%2012.8%22%2F%3E%3C%2Fsvg%3E"); }
.i-dollar { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M12%203v18M8%207.5A3%203%200%200%201%2011%206h2a2.5%202.5%200%200%201%200%205h-2a2.5%202.5%200%200%200%200%205h2a3%203%200%200%200%203-1.5%22%2F%3E%3C%2Fsvg%3E"); }
.i-cone { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M9.5%2020l2.5-15%202.5%2015M7%2020h10M9%2013h6%22%2F%3E%3C%2Fsvg%3E"); }
.i-refresh { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M4%2012a8%208%200%200%201%2013.7-5.6L20%208M20%204v4h-4M20%2012a8%208%200%200%201-13.7%205.6L4%2016M4%2020v-4h4%22%2F%3E%3C%2Fsvg%3E"); }
.i-check { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M5%2012l4.5%204.5L19%206.5%22%2F%3E%3C%2Fsvg%3E"); }
.i-spark { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M12%203.5l1.7%204.8L18.5%2010l-4.8%201.7L12%2016.5l-1.7-4.8L5.5%2010l4.8-1.7z%22%2F%3E%3C%2Fsvg%3E"); }
.i-ticket { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M4%208a1%201%200%200%201%201-1h14a1%201%200%200%201%201%201v2a2%202%200%200%200%200%204v2a1%201%200%200%201-1%201H5a1%201%200%200%201-1-1v-2a2%202%200%200%200%200-4z%22%2F%3E%3Cpath%20d%3D%22M14%207v10%22%2F%3E%3C%2Fsvg%3E"); }
.i-camera { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Crect%20x%3D%223%22%20y%3D%227%22%20width%3D%2218%22%20height%3D%2213%22%20rx%3D%222%22%2F%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2213.5%22%20r%3D%223.5%22%2F%3E%3Cpath%20d%3D%22M8%207l1.5-2.5h5L16%207%22%2F%3E%3C%2Fsvg%3E"); }
.i-image { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Crect%20x%3D%223%22%20y%3D%225%22%20width%3D%2218%22%20height%3D%2214%22%20rx%3D%222%22%2F%3E%3Ccircle%20cx%3D%228.5%22%20cy%3D%2210%22%20r%3D%221.6%22%2F%3E%3Cpath%20d%3D%22M4%2017l5-4%204%203%203-2%204%203%22%2F%3E%3C%2Fsvg%3E"); }
.i-pin { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M12%2021s6-5.3%206-10a6%206%200%200%200-12%200c0%204.7%206%2010%206%2010z%22%2F%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2211%22%20r%3D%222.2%22%2F%3E%3C%2Fsvg%3E"); }
.i-megaphone { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M4%2010v4l3%20.5%201.5%204.5H11l-1-4.5%209%203.5V6l-9%203.5H5a1%201%200%200%200-1%20.5z%22%2F%3E%3C%2Fsvg%3E"); }
.i-attach { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M20%2011.5l-8%208a5%205%200%200%201-7-7l8.5-8.5a3.3%203.3%200%200%201%204.7%204.7L9%2012.6a1.6%201.6%200%200%201-2.3-2.3l7.3-7.2%22%2F%3E%3C%2Fsvg%3E"); }
.i-building { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Crect%20x%3D%225%22%20y%3D%223%22%20width%3D%2214%22%20height%3D%2218%22%20rx%3D%221%22%2F%3E%3Cpath%20d%3D%22M9%207h2M13%207h2M9%2011h2M13%2011h2M10%2021v-3h4v3%22%2F%3E%3C%2Fsvg%3E"); }
.i-clock { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%228%22%2F%3E%3Cpath%20d%3D%22M12%208v4.2l2.8%201.8%22%2F%3E%3C%2Fsvg%3E"); }
.i-briefcase { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Crect%20x%3D%223%22%20y%3D%227%22%20width%3D%2218%22%20height%3D%2212%22%20rx%3D%222%22%2F%3E%3Cpath%20d%3D%22M8%207V5.5A1.5%201.5%200%200%201%209.5%204h5A1.5%201.5%200%200%201%2016%205.5V7M3%2013h18%22%2F%3E%3C%2Fsvg%3E"); }
.i-trash { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M5%207h14M10%207V5.2a1%201%200%200%201%201-1h2a1%201%200%200%201%201%201V7M6.5%207l1%2013h9l1-13%22%2F%3E%3C%2Fsvg%3E"); }
.i-folder { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M4%207a1%201%200%200%201%201-1h4l2%202h8a1%201%200%200%201%201%201v9a1%201%200%200%201-1%201H5a1%201%200%200%201-1-1z%22%2F%3E%3C%2Fsvg%3E"); }
.i-box { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M12%203l8%204.5v9L12%2021l-8-4.5v-9L12%203z%22%2F%3E%3Cpath%20d%3D%22M4%207.5%2012%2012l8-4.5M12%2012v9%22%2F%3E%3C%2Fsvg%3E"); }
.i-key { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Ccircle%20cx%3D%228%22%20cy%3D%228%22%20r%3D%224%22%2F%3E%3Cpath%20d%3D%22M10.8%2010.8L20%2020M16.5%2016.5l2-2%22%2F%3E%3C%2Fsvg%3E"); }
.i-plug { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M9%203v5M15%203v5M7%208h10v2.5a5%205%200%200%201-10%200zM12%2015.5V21%22%2F%3E%3C%2Fsvg%3E"); }
.i-phone { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M6%203h3l2%205-2.2%201.5a11%2011%200%200%200%205.2%205.2L16%2013l5%202v3a2%202%200%200%201-2.2%202A15.5%2015.5%200%200%201%204%205.2%202%202%200%200%201%206%203z%22%2F%3E%3C%2Fsvg%3E"); }
.i-mail { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Crect%20x%3D%223%22%20y%3D%225%22%20width%3D%2218%22%20height%3D%2214%22%20rx%3D%222%22%2F%3E%3Cpath%20d%3D%22M4%206.5%2012%2012l8-5.5%22%2F%3E%3C%2Fsvg%3E"); }
.i-health { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%228%22%2F%3E%3Cpath%20d%3D%22M12%208.2v7.6M8.2%2012h7.6%22%2F%3E%3C%2Fsvg%3E"); }
.i-scales { --i: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M12%204v16M7.5%2020h9M5%207h14%22%2F%3E%3Cpath%20d%3D%22M5%207l-2.3%205.5a2.4%202.4%200%200%200%204.6%200zM19%207l-2.3%205.5a2.4%202.4%200%200%200%204.6%200z%22%2F%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%224.3%22%20r%3D%221%22%2F%3E%3C%2Fsvg%3E"); }

/* ============================================================================
   Instrument brand signature — display face, coordinate grid, registration marks
   ----------------------------------------------------------------------------
   The identity layer. Self-hosted display face (no render flash / no third-party
   round-trip), a faint coordinate-grid ground, and corner registration
   crosshairs on cards — the "precision instrument" cues from the mockups.
   ========================================================================== */

/* All three faces are self-hosted (latin woff2, same-origin) so pages render
   their final type immediately — no third-party round-trip to Google Fonts, no
   FOUT, and the app keeps working if that host is blocked on the office network.
   font-display:swap is a belt-and-braces fallback; the files are tiny and local
   so the swap is imperceptible. */
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('/fonts/space-grotesk-var.woff2') format('woff2');
}
@font-face {
  font-family: 'Instrument Sans';
  font-style: normal;
  font-weight: 400 700;                 /* variable file, covers 400/500/600 */
  font-display: swap;
  src: url('/fonts/instrument-sans-var.woff2') format('woff2');
}
@font-face {
  font-family: 'DM Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/dm-mono-400.woff2') format('woff2');
}
@font-face {
  font-family: 'DM Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/dm-mono-500.woff2') format('woff2');
}

/* ── Coordinate-grid ground ──────────────────────────────────────────────────
   A fixed, viewport-wide grid painted behind all page content (z-index:-1 sits
   above the body/canvas background but below every in-flow element, so it shows
   through the gutters between cards). Masked to a soft dome so it reads as a
   signal fading out, strongest under the hero. Purely decorative + static, so
   it needs no reduced-motion handling. Opt out per page with `no-grid` on body. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  /* Grid lines + a soft dome vignette composited in the SAME background stack
     (top layer first). No mask-image: masking a full-viewport fixed layer forces
     an expensive per-frame repaint on scroll. The vignette fades the grid into
     the ground toward the edges, so it reads as a signal strongest under the
     hero. Static + decorative, so no reduced-motion handling needed. */
  background-image:
    radial-gradient(ellipse 125% 88% at 50% -10%, transparent 44%, var(--bg) 92%),
    linear-gradient(to right, var(--grid-line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--grid-line) 1px, transparent 1px);
  background-size:
    100% 100%,
    var(--grid-cell) var(--grid-cell),
    var(--grid-cell) var(--grid-cell);
  background-repeat: no-repeat, repeat, repeat;
}
body.no-grid::before { display: none; }

/* Registration crosshairs were removed — the corner "+" fiducials read as
   tacky on the tiles. The `.sp-reg` class is now an inert no-op left in markup
   for now; the grid backdrop carries the "instrument" signature on its own. */

/* ── Material / elevation ────────────────────────────────────────────────────
   A 1px lighter top-edge highlight (lit-from-above) plus a faint soft shadow so
   the main card/tile surfaces read as layered rather than flat. Applied to the
   recurring card classes across the app; kept subtle so it never reads heavy.
   Interactive tiles keep their own stronger :hover shadow (more specific). */
.sp-card, .sp-raise,
.nav-card, .dept-tile, .quick-tile,
.kpi, .stat-card {
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, var(--text) 6%, transparent),
    var(--shadow-sm);
}
:root[data-theme=""] .sp-card, :root[data-theme=""] .sp-raise,
:root[data-theme=""] .nav-card, :root[data-theme=""] .dept-tile, :root[data-theme=""] .quick-tile,
:root[data-theme=""] .kpi, :root[data-theme=""] .stat-card,
:root[data-theme="light"] .sp-card, :root[data-theme="light"] .sp-raise,
:root[data-theme="light"] .nav-card, :root[data-theme="light"] .dept-tile, :root[data-theme="light"] .quick-tile,
:root[data-theme="light"] .kpi, :root[data-theme="light"] .stat-card {
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.9),
    var(--shadow-sm);
}

/* ============================================================================
   Motion + states — all gated on `prefers-reduced-motion: no-preference`, so
   reduced-motion users get the static layout with zero animation.
   ========================================================================== */

@keyframes sp-rise-in { from { opacity: 0; transform: translateY(9px); } to { opacity: 1; transform: none; } }
@keyframes sp-shimmer { from { background-position: -160% 0; } to { background-position: 160% 0; } }

@media (prefers-reduced-motion: no-preference) {
  /* Staggered entrance for the common card-grid containers — cards cascade in
     on load. Scoped to known grids (never bare .grid) so it can't fire on
     arbitrary layouts. `both` keeps the pre-animation opacity:0 state. */
  :is(.dept-grid, .quick-grid, .nav-cards, .kpis, .stats-row, .stat-row) > * {
    animation: sp-rise-in 0.5s cubic-bezier(0.2, 0.7, 0.2, 1) both;
  }
  :is(.dept-grid, .quick-grid, .nav-cards, .kpis, .stats-row, .stat-row) > *:nth-child(1) { animation-delay: 0.02s; }
  :is(.dept-grid, .quick-grid, .nav-cards, .kpis, .stats-row, .stat-row) > *:nth-child(2) { animation-delay: 0.06s; }
  :is(.dept-grid, .quick-grid, .nav-cards, .kpis, .stats-row, .stat-row) > *:nth-child(3) { animation-delay: 0.10s; }
  :is(.dept-grid, .quick-grid, .nav-cards, .kpis, .stats-row, .stat-row) > *:nth-child(4) { animation-delay: 0.14s; }
  :is(.dept-grid, .quick-grid, .nav-cards, .kpis, .stats-row, .stat-row) > *:nth-child(5) { animation-delay: 0.18s; }
  :is(.dept-grid, .quick-grid, .nav-cards, .kpis, .stats-row, .stat-row) > *:nth-child(6) { animation-delay: 0.22s; }
  :is(.dept-grid, .quick-grid, .nav-cards, .kpis, .stats-row, .stat-row) > *:nth-child(7) { animation-delay: 0.26s; }
  :is(.dept-grid, .quick-grid, .nav-cards, .kpis, .stats-row, .stat-row) > *:nth-child(n+8) { animation-delay: 0.30s; }

  /* Opt-in entrance for anything else. */
  .sp-rise { animation: sp-rise-in 0.5s cubic-bezier(0.2, 0.7, 0.2, 1) both; }

  /* Theme cross-fade: space-motion.js stamps `.sp-theming` on <html> for one
     tick around a theme toggle, so the ground/surfaces/text glide between
     themes instead of snapping. Gated by the class so it never fires on the
     initial (pre-paint) theme application. */
  :root.sp-theming, :root.sp-theming body,
  :root.sp-theming .sp-card, :root.sp-theming .card,
  :root.sp-theming .topbar, :root.sp-theming .nav-card {
    transition: background-color 0.32s ease, color 0.32s ease, border-color 0.32s ease;
  }
}

/* Skeleton loader — a themed shimmer block to stand in for content while it
   loads, instead of a bare "Loading…" string. Reduced-motion users get a
   static tint (the shimmer keyframe simply doesn't run). Usage:
   <div class="sp-skeleton" style="height:2rem;width:60%"></div> */
.sp-skeleton {
  border-radius: var(--radius);
  background-color: var(--surface2);
  background-image: linear-gradient(
    100deg,
    transparent 30%,
    color-mix(in srgb, var(--text) 8%, transparent) 50%,
    transparent 70%
  );
  background-size: 220% 100%;
  background-repeat: no-repeat;
  animation: sp-shimmer 1.25s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  .sp-skeleton { animation: none; }
}
