/**
 * Wrench Time — Donkey Factory Design System v7
 * ───────────────────────────────────────────────────────────────────────────
 * Tri-theme: light (default) / dark / high-contrast.
 *
 * Theme application:
 *   <html>                   → light (default tokens on :root)
 *   <html class="dark">      → dark token overrides
 *   <html class="hc">        → high-contrast token overrides (independent)
 *   <html class="dark hc">   → high-contrast dark variant
 *
 * Tailwind compat: keeps .dark class so existing dark: utilities still work.
 *
 * All component classes prefixed .wt-* and consume tokens — never hex literals.
 */

/* ── 1. Tokens ──────────────────────────────────────────────────────────── */

:root {
  /* Surfaces — depth scale, low to high */
  --bg:              #fafafa;
  --surface-mute:    #f4f4f5;
  --surface:         #ffffff;
  --surface-raised:  #ffffff;
  --surface-sunken:  #f4f4f5;

  /* Borders */
  --border:          #e4e4e7;
  --border-strong:   #d4d4d8;
  --border-muted:    #f1f1f4;

  /* Text */
  --text:            #18181b;
  --text-muted:      #52525b;
  --text-subtle:     #71717a;
  --text-on-primary: #ffffff;

  /* Brand — violet/indigo */
  --primary:         #7c3aed;
  --primary-hover:   #6d28d9;
  --primary-soft:    #ede9fe;
  --primary-soft-hover: #ddd6fe;
  --primary-strong:  #5b21b6;
  --primary-contrast:#ffffff;

  /* Semantic */
  --success:         #16a34a;
  --success-soft:    #dcfce7;
  --success-text:    #166534;
  --warning:         #ea580c;
  --warning-soft:    #fff7ed;
  --warning-text:    #9a3412;
  --danger:          #dc2626;
  --danger-soft:     #fee2e2;
  --danger-text:     #991b1b;
  --info:            #2563eb;
  --info-soft:       #dbeafe;
  --info-text:       #1e40af;

  /* Focus ring (WCAG 2.4.7) */
  --focus-ring:      #7c3aed;
  --focus-ring-offset: #ffffff;

  /* Radii */
  --radius-xs:  0.25rem;
  --radius-sm:  0.375rem;
  --radius:     0.5rem;
  --radius-md:  0.625rem;
  --radius-lg:  0.75rem;
  --radius-xl:  1rem;
  --radius-2xl: 1.25rem;
  --radius-pill: 9999px;

  /* Shadows — subtle in light mode */
  --shadow-xs:  0 1px 2px rgba(15, 15, 25, 0.04);
  --shadow-sm:  0 1px 3px rgba(15, 15, 25, 0.06), 0 1px 2px rgba(15, 15, 25, 0.04);
  --shadow:     0 4px 12px rgba(15, 15, 25, 0.06), 0 2px 4px rgba(15, 15, 25, 0.04);
  --shadow-lg:  0 12px 32px rgba(15, 15, 25, 0.10), 0 4px 8px rgba(15, 15, 25, 0.05);
  --shadow-focus: 0 0 0 3px color-mix(in srgb, var(--focus-ring) 35%, transparent);

  /* Motion */
  --duration-fast: 120ms;
  --duration:      180ms;
  --duration-slow: 280ms;
  --ease:          cubic-bezier(0.2, 0, 0, 1);
  --ease-spring:   cubic-bezier(0.34, 1.56, 0.64, 1);

  /* Typography */
  --font-sans: -apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', system-ui, sans-serif;
  --font-mono: ui-monospace, 'JetBrains Mono', 'SF Mono', Menlo, Consolas, monospace;

  /* Layout */
  --container: 64rem;       /* 1024px main */
  --container-narrow: 48rem;
  --container-wide: 80rem;
  /* Header height: outer rendered height incl. 0.75rem+0.75rem __inner
     padding. Sticky tab bar + progress bar offset from this. */
  --header-height: 4.5rem;
  /* Tab bar height = py-2 wrapper (16px) + tab-track padding (10px) +
     wt-tab min-height (44px) = 70px. Round up to 4.5rem so the progress
     bar below has breathing room under the tab bar. */
  --tabbar-height: 4.5rem;

  /* Tap targets */
  --tap-min: 2.75rem;       /* 44px */
  --tap-comfort: 3rem;      /* 48px WCAG */
}

/* Dark theme overrides — violet-tinted neutrals */
.dark {
  --bg:              #0a0a0f;
  --surface-mute:    #131319;
  --surface:         #18181f;
  --surface-raised:  #1f1f28;
  --surface-sunken:  #0e0e14;

  --border:          #28283a;
  --border-strong:   #3a3a52;
  --border-muted:    #1d1d28;

  --text:            #f5f5f7;
  --text-muted:      #b4b4c4;
  --text-subtle:     #8a8aa0;
  --text-on-primary: #ffffff;

  --primary:         #a78bfa;
  --primary-hover:   #c4b5fd;
  --primary-soft:    #1e1a2e;
  --primary-soft-hover: #2a2342;
  --primary-strong:  #ddd6fe;
  --primary-contrast:#0a0a0f;

  --success:         #4ade80;
  --success-soft:    rgba(34, 197, 94, 0.12);
  --success-text:    #86efac;
  --warning:         #fb923c;
  --warning-soft:    rgba(234, 88, 12, 0.12);
  --warning-text:    #fed7aa;
  --danger:          #f87171;
  --danger-soft:     rgba(220, 38, 38, 0.15);
  --danger-text:     #fca5a5;
  --info:            #60a5fa;
  --info-soft:       rgba(37, 99, 235, 0.15);
  --info-text:       #93c5fd;

  --focus-ring:      #a78bfa;
  --focus-ring-offset: #0a0a0f;

  --shadow-xs:  0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-sm:  0 1px 3px rgba(0, 0, 0, 0.5), 0 1px 2px rgba(0, 0, 0, 0.3);
  --shadow:     0 4px 16px rgba(0, 0, 0, 0.45), 0 2px 4px rgba(0, 0, 0, 0.3);
  --shadow-lg:  0 16px 40px rgba(0, 0, 0, 0.55), 0 4px 8px rgba(0, 0, 0, 0.35);
}

/* High-contrast theme — accessibility max. Composes with dark/light.
   Base (.hc) defines font-scaling + common shadow/border tweaks.
   Color palette is split into .hc.dark (black/white) and .hc:not(.dark)
   (white/black) so HC can be turned on without forcing a theme change. */
.hc {
  /* Scale up root font-size so every rem-based element (buttons, inputs,
     tabs, step cards) grows proportionally — easier on low-vision users
     without rewriting each component. 16 → 18px base. */
  font-size: 112.5%;
  /* Slightly wider letter spacing improves character disambiguation
     ('l' vs '1' vs 'I', 'O' vs '0') on low-contrast displays. */
  letter-spacing: 0.005em;

  --shadow-xs:  none;
  --shadow-sm:  none;
  --shadow:     none;
  --shadow-lg:  none;
}

/* HC-dark: black background, white text, amber accents. */
.hc.dark {
  --bg:              #000000;
  --surface-mute:    #000000;
  --surface:         #000000;
  --surface-raised:  #0a0a0a;
  --surface-sunken:  #000000;

  --border:          #ffffff;
  --border-strong:   #ffffff;
  --border-muted:    #ffffff;

  --text:            #ffffff;
  --text-muted:      #ffffff;
  --text-subtle:     #f4f4f4;
  --text-on-primary: #000000;

  --primary:         #fbbf24;
  --primary-hover:   #fcd34d;
  --primary-soft:    #1a1500;
  --primary-soft-hover: #2a2200;
  --primary-strong:  #fde68a;
  --primary-contrast:#000000;

  --success:         #10b981;
  --success-soft:    #001a10;
  --success-text:    #34d399;
  --warning:         #fbbf24;
  --warning-soft:    #1a1500;
  --warning-text:    #fbbf24;
  --danger:          #f87171;
  --danger-soft:     #1a0000;
  --danger-text:     #fca5a5;
  --info:            #60a5fa;
  --info-soft:       #001020;
  --info-text:       #93c5fd;

  --focus-ring:      #fbbf24;
  --focus-ring-offset: #000000;
}

/* HC-light: white background, black text, deep purple accents.
   Uses :not(.dark) so this applies when .hc is on AND .dark is off. */
.hc:not(.dark) {
  --bg:              #ffffff;
  --surface-mute:    #ffffff;
  --surface:         #ffffff;
  --surface-raised:  #f7f7f7;
  --surface-sunken:  #ffffff;

  --border:          #000000;
  --border-strong:   #000000;
  --border-muted:    #000000;

  --text:            #000000;
  --text-muted:      #000000;
  --text-subtle:     #0a0a0a;
  --text-on-primary: #ffffff;

  /* Deep violet passes WCAG AAA (contrast > 7:1) against white. */
  --primary:         #5b21b6;
  --primary-hover:   #4c1d95;
  --primary-soft:    #f5edfc;
  --primary-soft-hover: #ebdefa;
  --primary-strong:  #3b0764;
  --primary-contrast:#ffffff;

  --success:         #065f46;
  --success-soft:    #ecfdf5;
  --success-text:    #064e3b;
  --warning:         #78350f;  /* amber-900 — 9.5:1 on white (was 7.6:1) */
  --warning-soft:    #fffbeb;
  --warning-text:    #78350f;
  --danger:          #991b1b;
  --danger-soft:     #fef2f2;
  --danger-text:     #7f1d1d;
  --info:            #1e3a8a;
  --info-soft:       #eff6ff;
  --info-text:       #1e40af;

  --focus-ring:      #000000;
  --focus-ring-offset: #ffffff;
}

/* HC typography — bump every small-text class above the WCAG AA large-text
   threshold (~18.5px). Root is already scaled to 112.5% in .hc, so rem
   values here resolve against an 18px base. Higher-hierarchy classes stay
   put — this only affects the "tiny" tier (captions, pills, eyebrows,
   subtle helpers, small buttons). Also restores full text contrast on
   anything styled as "subtle" since HC explicitly rejects low-contrast UX. */
.hc .wt-subtle        { font-size: 1rem; color: var(--text); }
.hc .wt-eyebrow,
.hc .wt-eyebrow-mono  { font-size: 0.9375rem; font-weight: 800; }
.hc .wt-pill          { font-size: 0.9375rem; font-weight: 700; }
.hc .wt-nav .wt-pill  { font-size: 0.875rem;  padding: 0.25rem 0.625rem; }
.hc .wt-btn-sm        { font-size: 0.9375rem; min-height: 2.5rem; }
.hc .wt-btn           { font-weight: 700; }
.hc .wt-tab           { font-size: 0.9375rem; font-weight: 700; }
.hc .wt-mono          { font-size: 0.9375rem; }
.hc input,
.hc textarea,
.hc select            { font-size: 1rem; }
.hc .wt-footer,
.hc footer            { font-size: 0.9375rem; }
/* Thicken borders so shapes stay legible at bigger sizes — matches HC
   expectation that UI chrome is never hair-thin. */
.hc .wt-btn,
.hc .wt-input,
.hc .wt-pill,
.hc .wt-icon-btn,
.hc input[type="text"],
.hc input[type="url"],
.hc input[type="email"],
.hc textarea,
.hc select            { border-width: 2px; }
/* Stronger focus ring in HC — 3px instead of 2px. */
.hc a:focus-visible,
.hc button:focus-visible,
.hc input:focus-visible,
.hc select:focus-visible,
.hc textarea:focus-visible,
.hc [tabindex]:focus-visible,
.hc .wt-icon-btn:focus-visible,
.hc .wt-btn:focus-visible { outline-width: 3px; outline-offset: 3px; }

/* ── 2. Base ────────────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  font-family: var(--font-sans);
  /* 1rem so the root scale (including .hc's 112.5% bump) propagates. */
  font-size: 1rem;
  line-height: 1.55;
  background: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  transition: background-color var(--duration) var(--ease),
              color var(--duration) var(--ease);
}

img, svg, video { max-width: 100%; display: block; }
button { font: inherit; cursor: pointer; }
input, select, textarea { font: inherit; }

/* Tailwind fallback */
.hidden { display: none !important; }

::selection {
  background: var(--primary-soft);
  color: var(--primary-strong);
}
.dark ::selection { color: var(--primary); }

/* Scrollbar — subtle */
@media (pointer: fine) {
  ::-webkit-scrollbar { width: 10px; height: 10px; }
  ::-webkit-scrollbar-track { background: transparent; }
  ::-webkit-scrollbar-thumb {
    background: var(--border-strong);
    border-radius: var(--radius-pill);
    border: 2px solid var(--bg);
  }
  ::-webkit-scrollbar-thumb:hover { background: var(--text-subtle); }
}

/* ── 3. Focus ring (WCAG 2.4.7) ─────────────────────────────────────────── */

:focus { outline: none; }

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible,
.wt-icon-btn:focus-visible,
.wt-btn:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.hc :focus-visible {
  outline-width: 3px;
  outline-color: var(--focus-ring);
}

/* ── 4. Typography scale ────────────────────────────────────────────────── */

.wt-h1 { font-size: clamp(2.25rem, 5.5vw, 3.25rem); font-weight: 800; line-height: 1.1; letter-spacing: -0.025em; color: var(--text); }

/* Hero tagline cycles through multiple phrases — lock to a single line so
   adding a longer phrase can't visually stack it. Smaller font-size floor
   on narrow viewports keeps the whole tagline on one line down to ~320px. */
#hero-h1 {
  white-space: nowrap;
  font-size: clamp(1.5rem, 7vw, 3.25rem);
}

/* In high-contrast mode the root font-size scales to 112.5% and the bolder
   stroke widens every glyph, so the tagline can spill past the container
   padding. Escape the .wt-container's horizontal padding using the standard
   50%-50vw breakout so the larger HC text has the full viewport minus a
   small gutter to fit on one line. Font-size stays the same. */
.hc #hero-h1 {
  margin-left: calc(50% - 50vw + 0.5rem);
  margin-right: calc(50% - 50vw + 0.5rem);
}
.wt-h2 { font-size: clamp(1.375rem, 3vw, 1.625rem); font-weight: 700; line-height: 1.2; letter-spacing: -0.018em; color: var(--text); }
.wt-h3 { font-size: 1.125rem; font-weight: 700; line-height: 1.3; letter-spacing: -0.012em; color: var(--text); }
.wt-eyebrow { font-size: 0.75rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--primary); }
.wt-body { font-size: 0.9375rem; line-height: 1.6; color: var(--text); }
.wt-muted { color: var(--text-muted); }
.wt-subtle { color: var(--text-subtle); font-size: 0.8125rem; }
.wt-mono { font-family: var(--font-mono); }

/* ── 5. Surfaces & cards ────────────────────────────────────────────────── */

.wt-surface { background: var(--surface); color: var(--text); }
.wt-surface-mute { background: var(--surface-mute); color: var(--text); }

.wt-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
}
.wt-card-flat {
  background: var(--surface);
  border-radius: var(--radius-lg);
}
.wt-card-soft {
  background: var(--surface-mute);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}

.wt-divider {
  border: 0;
  border-top: 1px solid var(--border);
  margin: 1rem 0;
}

/* ── 6. Buttons ─────────────────────────────────────────────────────────── */

.wt-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: var(--tap-comfort);
  padding: 0 1.125rem;
  border-radius: var(--radius-md);
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  border: 1px solid transparent;
  background: transparent;
  color: var(--text);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease),
              border-color var(--duration-fast) var(--ease),
              color var(--duration-fast) var(--ease),
              transform var(--duration-fast) var(--ease),
              box-shadow var(--duration-fast) var(--ease);
  text-decoration: none;
  white-space: nowrap;
  user-select: none;
}
.wt-btn:active:not(:disabled) { transform: translateY(0.5px) scale(0.985); }
.wt-btn:disabled { opacity: 0.5; cursor: not-allowed; }

.wt-btn-primary {
  background: var(--primary);
  color: var(--primary-contrast);
  border-color: var(--primary);
  box-shadow: var(--shadow-sm);
}
.wt-btn-primary:hover:not(:disabled) {
  background: var(--primary-hover);
  border-color: var(--primary-hover);
  box-shadow: var(--shadow);
}
.hc .wt-btn-primary { color: var(--primary-contrast); }

.wt-btn-secondary {
  background: var(--surface);
  border-color: var(--border-strong);
  color: var(--text);
}
.wt-btn-secondary:hover:not(:disabled) {
  background: var(--surface-mute);
  border-color: var(--primary);
}

.wt-btn-ghost {
  background: transparent;
  color: var(--text-muted);
}
.wt-btn-ghost:hover:not(:disabled) {
  background: var(--surface-mute);
  color: var(--text);
}

.wt-btn-danger {
  background: transparent;
  color: var(--danger);
  border-color: transparent;
}
.wt-btn-danger:hover:not(:disabled) {
  background: var(--danger-soft);
}

.wt-btn-sm { min-height: 2.25rem; padding: 0 0.875rem; font-size: 0.8125rem; border-radius: var(--radius); }
.wt-btn-lg { min-height: 3.25rem; padding: 0 1.5rem; font-size: 0.9375rem; border-radius: var(--radius-lg); }
.wt-btn-block { width: 100%; }

/* Icon-only buttons (toolbar) */
.wt-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap-comfort);
  height: var(--tap-comfort);
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-subtle);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background 160ms var(--ease, ease-out),
              color 160ms var(--ease, ease-out),
              transform 160ms var(--ease, ease-out),
              border-color 160ms var(--ease, ease-out),
              box-shadow 160ms var(--ease, ease-out);
  transition: background var(--duration-fast) var(--ease),
              color var(--duration-fast) var(--ease),
              border-color var(--duration-fast) var(--ease);
}
.wt-icon-btn:hover {
  background: var(--surface-mute);
  color: var(--text);
  border-color: var(--border);
  transform: translateY(-1px);
  box-shadow: 0 2px 8px -3px rgba(0, 0, 0, 0.14);
}
.wt-icon-btn:active {
  transform: translateY(0) scale(0.94);
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.12);
  transition-duration: 80ms;
}
.wt-icon-btn[aria-pressed="true"] {
  background: var(--primary-soft);
  color: var(--primary);
  border-color: color-mix(in srgb, var(--primary) 24%, var(--border));
}
.wt-icon-btn[aria-pressed="true"]:hover {
  background: color-mix(in srgb, var(--primary) 20%, var(--surface));
}
/* Larger SVG so icons actually fill the toolbar — 28px in a 48px button.
   Icon scales up 8% on hover for a subtle "alive" feedback. */
.wt-icon-btn svg {
  width: 1.75rem;
  height: 1.75rem;
  transition: transform 160ms var(--ease, ease-out);
}
.wt-icon-btn:hover svg { transform: scale(1.08); }
.wt-icon-btn:active svg { transform: scale(0.98); }

/* HC + reduced-motion: no scale/lift, just color feedback */
.hc .wt-icon-btn,
.hc .wt-icon-btn svg { transition: none; }
.hc .wt-icon-btn:hover,
.hc .wt-icon-btn:active { transform: none; box-shadow: none; }
.hc .wt-icon-btn:hover svg,
.hc .wt-icon-btn:active svg { transform: none; }
@media (prefers-reduced-motion: reduce) {
  .wt-icon-btn, .wt-icon-btn svg { transition: none; }
  .wt-icon-btn:hover, .wt-icon-btn:active { transform: none; box-shadow: none; }
  .wt-icon-btn:hover svg, .wt-icon-btn:active svg { transform: none; }
}

@media (max-width: 640px) {
  .wt-icon-btn { width: var(--tap-comfort); height: var(--tap-comfort); }
  .wt-icon-btn svg { width: 1.625rem; height: 1.625rem; }
}

/* ── 7. Inputs ──────────────────────────────────────────────────────────── */

.wt-input {
  display: block;
  width: 100%;
  min-height: var(--tap-comfort);
  padding: 0.75rem 1rem;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  font-size: 0.9375rem;
  line-height: 1.4;
  transition: border-color var(--duration-fast) var(--ease),
              box-shadow var(--duration-fast) var(--ease),
              background var(--duration-fast) var(--ease);
}
.wt-input::placeholder { color: var(--text-subtle); }
.wt-input:hover { border-color: var(--text-subtle); }
.wt-input:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: var(--shadow-focus);
}
.wt-input.wt-input-error {
  border-color: var(--danger);
  animation: wt-shake 0.4s ease-out;
}
.wt-input--with-icon { padding-left: 2.75rem; }

@keyframes wt-shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-4px); }
  40% { transform: translateX(4px); }
  60% { transform: translateX(-3px); }
  80% { transform: translateX(3px); }
}

/* ── 8. Pills & badges ──────────────────────────────────────────────────── */

.wt-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.25rem 0.625rem;
  border-radius: var(--radius-pill);
  font-size: 0.75rem;
  font-weight: 600;
  background: var(--surface-mute);
  color: var(--text-muted);
  border: 1px solid var(--border);
  white-space: nowrap;
}
.wt-pill-primary { background: var(--primary-soft); color: var(--primary); border-color: transparent; }
.wt-pill-success { background: var(--success-soft); color: var(--success-text); border-color: transparent; }
.wt-pill-warning { background: var(--warning-soft); color: var(--warning-text); border-color: transparent; }
.wt-pill-danger  { background: var(--danger-soft);  color: var(--danger-text);  border-color: transparent; }
.wt-pill-info    { background: var(--info-soft);    color: var(--info-text);    border-color: transparent; }

.wt-pill-pro {
  background: linear-gradient(135deg, var(--primary), #a855f7);
  color: #fff;
  border-color: transparent;
  font-weight: 700;
}

/* ── 9. Banners ─────────────────────────────────────────────────────────── */

.wt-banner {
  padding: 1rem 1.25rem;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  background: var(--surface);
}
.wt-banner-warning {
  background: var(--warning-soft);
  border-color: color-mix(in srgb, var(--warning) 40%, transparent);
  color: var(--warning-text);
}
.wt-banner-danger {
  background: var(--danger-soft);
  border-color: color-mix(in srgb, var(--danger) 40%, transparent);
  color: var(--danger-text);
}
.wt-banner-info {
  background: var(--info-soft);
  border-color: color-mix(in srgb, var(--info) 40%, transparent);
  color: var(--info-text);
}
.wt-banner-primary {
  background: var(--primary-soft);
  border-color: color-mix(in srgb, var(--primary) 40%, transparent);
  color: var(--primary-strong);
}
.dark .wt-banner-primary { color: var(--primary); }

/* ── 10. Header ─────────────────────────────────────────────────────────── */

.wt-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: color-mix(in srgb, var(--surface) 85%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--border);
  transition: padding var(--duration) var(--ease), box-shadow var(--duration) var(--ease);
}
.wt-header__inner {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0.75rem 1rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  min-height: var(--header-height);
}
.wt-header--compact { box-shadow: var(--shadow-sm); }
.wt-header--compact .wt-header__inner { padding-top: 0.5rem; padding-bottom: 0.5rem; }

.wt-logo {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  text-decoration: none;
  color: var(--text);
  font-size: 0.9375rem;
  font-weight: 800;
  letter-spacing: -0.018em;
  flex-shrink: 0;
}
.wt-logo__accent { color: var(--primary); }

/* Donkey Factory brand lockup — transparent PNG baked from the source JPEGs
   via luminance threshold + alpha smoothing. Theme-swapped figure color so
   the mark always reads on the current surface:
     light mode → black figure on transparent  (wt-brandlock--light)
     dark  mode → white figure on transparent  (wt-brandlock--dark)
     HC    mode → always use the black variant for maximum text-on-bg contrast */
.wt-brandlock {
  display: block;
  height: 3rem;
  width: auto;
  max-width: 100%;
  object-fit: contain;
  flex-shrink: 0;
  vertical-align: middle;
}
/* Brandlock swap — driven by resolved theme. HC composes with theme:
   HC-light uses the black-figure PNG (visible on white bg), HC-dark uses
   the white-figure PNG (visible on black bg). No HC-specific override. */
.wt-brandlock--dark { display: none; }
html[data-theme-resolved="dark"] .wt-brandlock--light { display: none; }
html[data-theme-resolved="dark"] .wt-brandlock--dark  { display: block; }

.wt-brandlock__wordmark {
  font-size: 0.9375rem;
  line-height: 1;
  letter-spacing: -0.012em;
}
@media (max-width: 520px) {
  .wt-brandlock__wordmark { display: none; }
  .wt-brandlock { height: 2.5rem; }
}
@media (min-width: 768px) {
  .wt-brandlock { height: 3.5rem; }
}
.wt-footer-brand {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  opacity: 0.92;
  transition: opacity 200ms ease;
}
.wt-footer-brand:hover { opacity: 1; }
.wt-brandlock--footer {
  height: 5.5rem !important;
}
@media (min-width: 768px) {
  .wt-brandlock--footer { height: 7rem !important; }
}

.wt-nav {
  display: flex;
  align-items: center;
  gap: 0.25rem;
}
.wt-nav > #auth-controls:not(.hidden) {
  margin-left: 0.5rem;
  padding-left: 0.625rem;
  border-left: 1px solid var(--border);
}
/* Tighten icon gap on small screens so 4 icons fit ≥360px */
@media (max-width: 640px) {
  .wt-nav { gap: 0.125rem; }
  .wt-nav .wt-pill { font-size: 0.6875rem; padding: 0.125rem 0.5rem; }
}

/* ── Floating Sign-in pill (top-right, logged-out only) ──────────────────── */
:root {
  /* Tunables — header right-padding reserve must match pill footprint */
  --wt-float-offset: 0.75rem;   /* distance from viewport right edge */
  --wt-float-width:  6.5rem;    /* pill width with "Sign in" label */
  --wt-float-gap:    0.75rem;   /* breathing room between pill and nav icons */
}
@media (max-width: 380px) {
  :root {
    --wt-float-width: 3rem;     /* icon-only collapse */
    --wt-float-gap:   0.5rem;
  }
}

/* Reserve header right-padding so nav icons don't sit beneath the pill.
   Scoped to signed-out state so logged-in users don't get extra empty space. */
body:has(#auth-float[data-state="signed-out"]:not(.is-hidden)) .wt-header__inner {
  padding-right: calc(
    max(var(--wt-float-offset), env(safe-area-inset-right, 0rem))
    + var(--wt-float-width)
    + var(--wt-float-gap)
  );
}

.wt-auth-float {
  position: fixed;
  top: max(var(--wt-float-offset), env(safe-area-inset-top));
  right: max(var(--wt-float-offset), env(safe-area-inset-right));
  z-index: 40; /* below voice-overlay (z-50) and skip-link (z-[100]) */
  pointer-events: none;
  transition: opacity var(--duration) var(--ease), transform var(--duration) var(--ease);
}
.wt-auth-float[data-state="signed-in"],
.wt-auth-float.is-hidden {
  opacity: 0;
  transform: translateY(-4px);
  pointer-events: none;
  visibility: hidden;
}
.wt-auth-float__pill {
  pointer-events: auto;
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-height: var(--tap-comfort);
  padding: 0.5rem 0.875rem;
  border-radius: 9999px;
  background: var(--primary);
  color: var(--primary-contrast);
  font: 600 0.8125rem/1 var(--font-sans, system-ui);
  text-decoration: none;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18), 0 1px 2px rgba(0, 0, 0, 0.12);
  transition: transform var(--duration) var(--ease), box-shadow var(--duration) var(--ease), background var(--duration) var(--ease);
}
.wt-auth-float__pill:hover {
  transform: translateY(-1px);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.24), 0 2px 4px rgba(0, 0, 0, 0.14);
}
.wt-auth-float__pill:focus-visible {
  outline: 2px solid var(--focus, var(--primary));
  outline-offset: 3px;
}
.wt-auth-float__pill svg {
  width: 1rem;
  height: 1rem;
  flex-shrink: 0;
}
@media (prefers-reduced-motion: reduce) {
  .wt-auth-float, .wt-auth-float__pill { transition: none; }
  .wt-auth-float__pill:hover { transform: none; }
}
/* On very narrow viewports collapse pill to icon-only */
@media (max-width: 380px) {
  .wt-auth-float__pill span { display: none; }
  .wt-auth-float__pill { padding: 0.5rem; width: var(--tap-comfort); height: var(--tap-comfort); justify-content: center; }
}

/* ── 11. Layout helpers ─────────────────────────────────────────────────── */

.wt-container { max-width: var(--container); margin: 0 auto; padding: 0 1rem; width: 100%; }
.wt-container-narrow { max-width: var(--container-narrow); margin: 0 auto; padding: 0 1rem; width: 100%; }

.wt-stack-xs > * + * { margin-top: 0.375rem; }
.wt-stack-sm > * + * { margin-top: 0.625rem; }
.wt-stack    > * + * { margin-top: 1rem; }
.wt-stack-lg > * + * { margin-top: 1.5rem; }

/* ── 12. Hero ───────────────────────────────────────────────────────────── */

.wt-hero {
  text-align: center;
  padding: 0.25rem 0 0.5rem;
  position: relative;
}
@media (min-width: 768px) {
  .wt-hero { padding: 0.5rem 0 0.75rem; }
}

/* Hero statue (static poster). Height is driven by the image's intrinsic
   aspect ratio (1376×768 ≈ 1.79:1) rather than a fixed box, so there's no
   dead vertical space above or below the artwork on any viewport.
   Small negative bottom margin lets the feathered edge overlap the eyebrow
   for a softer transition. */
.wt-hero-statue {
  /* Fills its flex-grown wrapper; <img> inside uses object-fit: contain so
     the aspect ratio is preserved while the box can scale freely. Upper
     bounds are applied on the WRAPPER (.wt-hero-statue-wrap) per breakpoint,
     not here, so the above-fold flex column controls sizing. */
  width: 100%;
  height: 100%;
  max-width: 100%;
  margin: 0 auto -0.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  z-index: 0;
  line-height: 0;
  overflow: hidden;
}
@media (min-width: 640px) {
  .wt-hero-statue {
    margin: 0 auto -0.75rem;
  }
}
@media (min-width: 1024px) {
  .wt-hero-statue {
    margin: 0 auto -1rem;
  }
}

/* ─── Above-the-fold flex layout ─────────────────────────────────────────
   Wrapper fills (100dvh - header - main vertical padding). Children:
     • #hero (copy)                → flex 0 0 auto, pins top
     • #hero-statue-section        → flex 1 1 0, grows to absorb slack
     • .wt-input-overlay (form)    → flex 0 0 auto, pins bottom (magnet)
   Works on any viewport: tall screens get a big statue, short screens get
   a small one, but the input + example line always sit at the bottom of
   the visible fold. */
.wt-above-fold {
  display: flex;
  flex-direction: column;
  /* Use SMALL viewport height (`svh`) — the measurement WITH the mobile
     browser chrome (URL bar) visible. This is stable; the container keeps
     the same height whether or not iOS Safari shows its address bar.
     `dvh` would give us a slightly taller initial fold, but its value
     CHANGES as the URL bar slides in/out during scroll, which makes the
     flex-grow statue wrapper shrink and regrow live — that's the "jumpy"
     feel the user reports. `svh` trades a little headroom for a rock-
     steady layout that doesn't dance. */
  min-height: calc(100vh - var(--header-height) - 4rem);   /* legacy fallback */
  min-height: calc(100svh - var(--header-height) - 4rem);  /* modern, stable */
}
.wt-above-fold > #hero { flex: 0 0 auto; }
.wt-above-fold > .wt-hero-statue-wrap {
  flex: 1 1 0;
  /* Floor the statue so the grown gallery (3x3) can't crush it on short
     viewports. Mobile gets a 12rem floor (the statue is the brand anchor);
     desktop keeps 0 so the flex-grow math works unchanged. */
  min-height: 12rem;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  z-index: 0;
  width: 100%;
  /* Upper bound tuned to leave room for the larger h1 + subcopy above. */
  max-width: 34rem;
  margin: 0 auto;
}
@media (min-width: 768px) {
  .wt-above-fold > .wt-hero-statue-wrap { min-height: 0; }
}
.wt-above-fold > .wt-input-overlay { flex: 0 0 auto; }

/* Input overlay — magnets to bottom of above-fold, slight negative margin
   preserves the "float over statue" read without clipping. */
.wt-input-overlay {
  position: relative;
  z-index: 3;
  margin-top: -1.5rem;
  padding-bottom: 0.75rem;
}
@media (min-width: 768px) {
  .wt-input-overlay { margin-top: -2rem; }
}
@media (min-width: 1024px) {
  .wt-input-overlay { margin-top: -2.5rem; }
}
.wt-input-overlay .wt-input {
  box-shadow: 0 10px 30px -12px rgba(0, 0, 0, 0.25), 0 2px 6px -2px rgba(0, 0, 0, 0.08);
}
.wt-input-overlay .wt-btn-primary {
  box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.35), var(--shadow-sm);
}
/* Reduced-motion / HC: drop the overlap for unambiguous layout. */
@media (prefers-reduced-motion: reduce) {
  .wt-input-overlay { margin-top: 0; }
}
.hc .wt-input-overlay { margin-top: 0; }
.hc .wt-input-overlay .wt-input,
.hc .wt-input-overlay .wt-btn-primary { box-shadow: none; }

/* ─── Demo gallery (chip band) ───────────────────────────────────────────
   9 example chips under the input, all pre-extracted (data-demo-slug → cached
   JSON, instant, no wallet debit). Was a 3x3 card grid that ate 414px of the
   first screen; now a wrapping band of text-only pills that reflows to the
   viewport. Full context lives in each button's aria-label + title. */
.wt-demo-gallery {
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
  margin-top: 1rem;
}
.wt-demo-gallery__lead {
  margin: 0;
  text-align: center;
  font-size: 0.8125rem;
  color: var(--text-muted);
  font-weight: 600;
  letter-spacing: 0.01em;
}
.wt-demo-gallery__sublead {
  color: var(--text-subtle);
  font-weight: 400;
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.75rem;
  margin-left: 0.375rem;
}
/* Chips wrap to fill the row rather than sitting on a fixed 3-col grid, so a
   long name like "Smart thermostat" gets the width it needs and short ones
   stop wasting it. Centred because the band sits under a centred form. */
.wt-demo-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.375rem;
}
@media (min-width: 768px) {
  .wt-demo-grid { gap: 0.5rem; }
}

/* Per-category accent. Purely decorative — the trade is always spelled out in
   each button's aria-label, so nothing here is conveyed by colour alone. */
.wt-demo-tile { --demo-accent: var(--primary); }
.wt-demo-tile[data-cat="plumbing"]   { --demo-accent: #38bdf8; }
.wt-demo-tile[data-cat="electrical"] { --demo-accent: #fbbf24; }
.wt-demo-tile[data-cat="drywall"]    { --demo-accent: #a78bfa; }
.wt-demo-tile[data-cat="hvac"]       { --demo-accent: #34d399; }
.wt-demo-tile[data-cat="tile"]       { --demo-accent: #fb7185; }

/* Gradient-edge pill: the border is a two-stop gradient painted into the
   border-box while the fill stays flat in the padding-box, which reads as a
   lit edge rather than a drawn outline. min-height holds the 48px jobsite tap
   target (--tap-comfort) — this app gets used in gloves. */
.wt-demo-tile {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: var(--tap-comfort);
  padding: 0.5rem 0.9375rem 0.5rem 0.8125rem;
  color: var(--text);
  border: 1px solid transparent;
  border-radius: 999px;
  background:
    linear-gradient(var(--surface), var(--surface)) padding-box,
    linear-gradient(140deg,
      color-mix(in srgb, var(--demo-accent) 45%, transparent) 0%,
      color-mix(in srgb, var(--border) 70%, transparent) 40%,
      color-mix(in srgb, var(--border) 70%, transparent) 100%) border-box;
  box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 6%, transparent);
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: -0.006em;
  line-height: 1.2;
  white-space: nowrap;
  cursor: pointer;
  transition: transform 180ms var(--ease, ease-out),
              box-shadow 180ms var(--ease, ease-out),
              background 180ms var(--ease, ease-out);
}
/* Accent dot with a soft halo — the one spot of colour per pill. */
.wt-demo-tile::before {
  content: "";
  flex: none;
  width: 0.375rem;
  height: 0.375rem;
  border-radius: 50%;
  background: var(--demo-accent);
  box-shadow: 0 0 0 0.1875rem color-mix(in srgb, var(--demo-accent) 18%, transparent);
  transition: box-shadow 180ms var(--ease, ease-out);
}
/* Two labels per chip: the full name on desktop, a short one on phones. Both
   are real text rather than CSS content so they stay selectable and
   translatable, and neither is the accessible name — that comes from the
   button's aria-label, which always carries the full trade + runtime. */
.wt-demo-tile__name  { color: var(--text); }
.wt-demo-tile__short { color: var(--text); display: none; }
.wt-demo-tile__time {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.6875rem;
  font-weight: 500;
  color: var(--text-subtle);
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
}
.wt-demo-tile:hover {
  transform: translateY(-2px);
  background:
    linear-gradient(color-mix(in srgb, var(--demo-accent) 7%, var(--surface)),
                    color-mix(in srgb, var(--demo-accent) 4%, var(--surface))) padding-box,
    linear-gradient(140deg,
      color-mix(in srgb, var(--demo-accent) 85%, transparent) 0%,
      color-mix(in srgb, var(--demo-accent) 30%, transparent) 65%,
      color-mix(in srgb, var(--border) 70%, transparent) 100%) border-box;
  box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 8%, transparent),
              0 8px 22px -12px color-mix(in srgb, var(--demo-accent) 60%, transparent);
}
.wt-demo-tile:hover::before {
  box-shadow: 0 0 0 0.25rem color-mix(in srgb, var(--demo-accent) 28%, transparent);
}
.wt-demo-tile:hover .wt-demo-tile__time { color: var(--text-muted); }
.wt-demo-tile:focus-visible {
  outline: 2px solid var(--focus-ring, var(--primary));
  outline-offset: 2px;
}
.wt-demo-tile:active { transform: translateY(0); }

/* Difficulty chip — color-coded by level. 4-step scale: easy → intermediate
   → hard → advanced. The demo gallery no longer renders one (the chips are
   text-only); these remain for the My Collection level chip. */
.wt-level-chip--easy {
  color: color-mix(in srgb, var(--success, #16a34a) 80%, black);
  background: color-mix(in srgb, var(--success, #16a34a) 14%, transparent);
}
.wt-level-chip--intermediate {
  color: color-mix(in srgb, var(--warning, #d97706) 90%, black);
  background: color-mix(in srgb, var(--warning, #d97706) 14%, transparent);
}
.wt-level-chip--hard {
  color: color-mix(in srgb, #ea580c 85%, black);
  background: color-mix(in srgb, #ea580c 14%, transparent);
}
.wt-level-chip--advanced {
  color: color-mix(in srgb, var(--danger, #dc2626) 85%, black);
  background: color-mix(in srgb, var(--danger, #dc2626) 14%, transparent);
}
/* Reduced-motion / HC */
@media (prefers-reduced-motion: reduce) {
  .wt-demo-tile,
  .wt-demo-tile::before { transition: none; }
  .wt-demo-tile:hover,
  .wt-demo-tile:active { transform: none; }
}
/* High contrast drops every gradient and glow for a flat, hard-edged pill —
   the lit-edge treatment is exactly the kind of low-contrast decoration this
   mode exists to remove. */
.hc .wt-demo-tile {
  background: var(--surface);
  border: 2px solid var(--text);
  box-shadow: none;
}
.hc .wt-demo-tile:hover {
  background: var(--text);
  color: var(--surface);
  transform: none;
  box-shadow: none;
}
.hc .wt-demo-tile:hover .wt-demo-tile__name,
.hc .wt-demo-tile:hover .wt-demo-tile__time { color: var(--surface); }
.hc .wt-demo-tile::before { background: currentColor; box-shadow: none; }
.hc .wt-demo-tile:active { transform: none; }

/* ─── Embed warning card ──────────────────────────────────────────────────
   Renders inside the video player container when YouTube oEmbed preflight
   reports the video as non-embeddable (creator disabled embedding, video
   private/removed, etc.). Replaces the broken iframe and points the user
   to the YouTube URL. Same footprint as the iframe so layout doesn't shift. */
.wt-embed-warning {
  display: flex;
  gap: 0.875rem;
  align-items: flex-start;
  padding: 1rem 1.125rem;
  background: color-mix(in srgb, var(--warning, #f59e0b) 8%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--warning, #f59e0b) 40%, var(--border));
  border-radius: var(--radius-lg, 0.75rem);
  color: var(--text);
  width: 100%;
  height: 100%;
  min-height: 8rem;
  box-sizing: border-box;
}
.wt-embed-warning__icon {
  flex-shrink: 0;
  color: var(--warning, #f59e0b);
  margin-top: 0.125rem;
}
.wt-embed-warning__body { flex: 1; min-width: 0; }
.wt-embed-warning__headline {
  font-weight: 600;
  font-size: 0.9375rem;
  line-height: 1.3;
  margin: 0 0 0.25rem;
}
.wt-embed-warning__text {
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--text-muted, var(--text));
  margin: 0 0 0.625rem;
}
.wt-embed-warning__link {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--primary);
  text-decoration: none;
  padding: 0.35rem 0.75rem;
  border: 1px solid var(--primary);
  border-radius: var(--radius-md);
  transition: background 120ms var(--ease, ease-out);
}
.wt-embed-warning__link:hover {
  background: color-mix(in srgb, var(--primary) 10%, transparent);
}
.wt-embed-warning__link:focus-visible {
  outline: 2px solid var(--focus-ring, var(--primary));
  outline-offset: 2px;
}
.hc .wt-embed-warning { border-width: 2px; }

/* ─── Pro-tech panel: stripe-card entries (Safety + Tips) ────────────────
   Design language: industrial workshop dashboard. Monochrome surface with
   a left accent stripe encoding severity/kind. No tinted backgrounds.
   Hairline dividers. Monospace metadata. Compact panel header with stat
   chips. Optimized for 2026 UI — readable, workmanlike, no chromatic noise. */

.wt-panel-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.75rem 0.125rem 0.5rem;
  margin: 0 0 0.25rem;
  border-bottom: 1px solid var(--border);
}
.wt-panel-header:not(:first-child) {
  margin-top: 1.5rem;
}
.wt-panel-header__label {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-subtle);
}
.wt-panel-header__stats {
  display: inline-flex;
  gap: 0.375rem;
  align-items: center;
}

/* Stat chip — small, mono, used for counts + severity breakdown */
.wt-stat {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 0.1875rem 0.5rem;
  border-radius: 0.25rem;
  color: var(--text-muted, var(--text-subtle));
  background: color-mix(in srgb, var(--border) 40%, transparent);
}
.wt-stat--critical {
  color: var(--danger, #dc2626);
  background: color-mix(in srgb, var(--danger, #dc2626) 12%, transparent);
}
.wt-stat--advisory {
  color: var(--warning, #d97706);
  background: color-mix(in srgb, var(--warning, #d97706) 14%, transparent);
}

/* Entry — the stripe-card shared by Safety warnings + Tips */
.wt-entry {
  --stripe-color: var(--border-strong, var(--border));
  display: grid;
  grid-template-columns: 3px 1fr;
  gap: 0.875rem;
  align-items: stretch;
  padding: 0.875rem 0.125rem 0.875rem 0;
  border-bottom: 1px solid var(--border);
  background: transparent;
  transition: background 120ms var(--ease, ease-out);
}
.wt-entry:last-child { border-bottom: 0; }
.wt-entry:hover {
  background: color-mix(in srgb, var(--surface) 60%, transparent);
}

.wt-entry__stripe {
  background: var(--stripe-color);
  border-radius: 2px;
  min-height: 100%;
}
.wt-entry__body {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
}
.wt-entry__text {
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--text);
  margin: 0;
  word-wrap: break-word;
}
.wt-entry__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-top: 0.125rem;
}
.wt-entry__meta {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.6875rem;
  color: var(--text-subtle);
  letter-spacing: 0.02em;
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  flex-wrap: wrap;
  min-width: 0;
}
.wt-entry__likes {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  color: var(--text-muted, var(--text-subtle));
}

/* Severity / kind chip — small uppercase, picks up the stripe color */
.wt-entry__chip {
  align-self: flex-start;
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--stripe-color);
}
.wt-entry__tag {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0.1875rem 0.5rem;
  border-radius: 0.25rem;
}
.wt-entry__tag--user {
  color: var(--primary);
  background: color-mix(in srgb, var(--primary) 14%, transparent);
}
.wt-entry__delete {
  flex-shrink: 0;
  background: transparent;
  border: 0;
  padding: 0.25rem;
  color: var(--text-subtle);
  cursor: pointer;
  border-radius: 0.25rem;
  transition: color 120ms var(--ease, ease-out), background 120ms var(--ease, ease-out);
}
.wt-entry__delete:hover {
  color: var(--danger, #dc2626);
  background: color-mix(in srgb, var(--danger, #dc2626) 10%, transparent);
}

/* Variant: stripe colors by severity/kind */
.wt-entry--critical { --stripe-color: var(--danger, #dc2626); }
.wt-entry--advisory { --stripe-color: var(--warning, #d97706); }
.wt-entry--tip      { --stripe-color: #10b981; }
.wt-entry--insight  { --stripe-color: #8b5cf6; }
.wt-entry--user     { --stripe-color: var(--primary); }

/* Critical variant gets a stronger stripe + slightly denser type */
.wt-entry--critical {
  padding-top: 1rem;
  padding-bottom: 1rem;
}
.wt-entry--critical .wt-entry__stripe {
  background: linear-gradient(
    to bottom,
    var(--stripe-color) 0,
    var(--stripe-color) 70%,
    color-mix(in srgb, var(--stripe-color) 40%, transparent) 100%
  );
}
.wt-entry--critical .wt-entry__text { font-weight: 500; }

/* ─── Community Spotlight ────────────────────────────────────────────────
   Compact top-of-tabs card showing the community verdict + most-liked tip.
   Replaces the Tips tab — individual tips now render inline on their
   matching step via _assignTipsToSteps. Two-column on tablet+, stacked on
   mobile. Single-card mode when only verdict OR only top-tip is present. */

.wt-spotlight {
  display: flex;
  flex-direction: column;
  gap: 0;
  margin: 0 0 1rem;
  padding: 1rem 1.125rem 1.125rem;
  background: color-mix(in srgb, var(--primary) 4%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--primary) 18%, var(--border));
  border-radius: var(--radius-md);
  position: relative;
}
.wt-spotlight__card {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  min-width: 0;
}
.wt-spotlight__card[hidden] { display: none; }
.wt-spotlight__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.875rem;
  flex-wrap: wrap;
  min-height: 1.25rem;
}
.wt-spotlight__eyebrow {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  line-height: 1;
}
.wt-spotlight__eyebrow--verdict { color: var(--primary); }
.wt-spotlight__eyebrow--tip     { color: #10b981; }

/* Star rating — 5 glyphs with filled/empty split + numeric label */
.wt-spotlight__stars {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  line-height: 1;
}
.wt-spotlight__stars[hidden] { display: none; }
.wt-spotlight__stars-glyphs {
  display: inline-flex;
  font-size: 0.9375rem;
  letter-spacing: 0.02em;
  line-height: 1;
  /* Stack filled over empty for precise overlay; we render both side-by-side. */
}
.wt-spotlight__stars-filled { color: #f59e0b; }
.wt-spotlight__stars-empty  { color: color-mix(in srgb, var(--text-subtle) 40%, transparent); }
.wt-spotlight__stars-num {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.wt-spotlight__stars-denom {
  color: var(--text-subtle);
  font-weight: 500;
}

/* Hairline divider between verdict and top-tip cards */
.wt-spotlight__divider {
  border: 0;
  height: 1px;
  background: var(--border);
  margin: 0.875rem 0;
  opacity: 0.8;
}
.wt-spotlight__divider[hidden] { display: none; }

.wt-spotlight__quote {
  margin: 0;
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--text);
  font-style: italic;
  word-wrap: break-word;
}
.wt-spotlight__quote--tip {
  font-size: 1.0625rem;
  line-height: 1.5;
  letter-spacing: -0.005em;
  position: relative;
  padding-left: 1.375rem;
}
.wt-spotlight__quote--tip::before {
  content: '\201C';                 /* smart left double-quote */
  position: absolute;
  left: 0;
  top: -0.125rem;
  font-family: Georgia, 'Times New Roman', serif;
  font-style: normal;
  font-size: 1.875rem;
  line-height: 1;
  color: #10b981;
  opacity: 0.6;
}
.wt-spotlight__meta {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.6875rem;
  letter-spacing: 0.02em;
  color: var(--text-subtle);
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  flex-wrap: wrap;
}
.wt-spotlight__likes {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  color: var(--text-muted, var(--text-subtle));
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* HC: no tint, thicker border, simpler stars */
.hc .wt-spotlight { border-width: 2px; background: var(--surface); }
.hc .wt-spotlight__stars-filled { color: var(--text); }
.hc .wt-spotlight__stars-empty  { color: var(--text-subtle); }
.hc .wt-spotlight__quote--tip::before { opacity: 1; }

/* Community Verdict — legacy typographic quote block (retained for inline
   step/history contexts that still call it). New spotlight above is the
   primary surface. */
.wt-verdict {
  margin: 0 0 1.25rem;
  padding: 0.25rem 0 0.25rem 1rem;
  border-left: 2px solid var(--primary);
}
.wt-verdict__eyebrow {
  display: block;
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--primary);
  margin-bottom: 0.5rem;
}
.wt-verdict__body {
  margin: 0;
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--text);
  font-style: italic;
}

/* Empty-state panel */
.wt-panel-empty {
  text-align: center;
  padding: 2.5rem 1rem;
  color: var(--text-subtle);
}
.wt-panel-empty__icon {
  width: 2rem;
  height: 2rem;
  margin: 0 auto 0.5rem;
  color: color-mix(in srgb, #10b981 70%, var(--text-subtle));
}
.wt-panel-empty__text {
  font-size: 0.875rem;
  color: var(--text-muted, var(--text-subtle));
  margin: 0;
}

/* HC mode: 2px stripes, no background hover, bolder type */
.hc .wt-entry {
  border-bottom-width: 2px;
}
.hc .wt-entry__stripe {
  min-width: 4px;
}
.hc .wt-entry:hover { background: transparent; }
.hc .wt-verdict { border-left-width: 4px; }

/* Reduced-motion: drop hover transition */
@media (prefers-reduced-motion: reduce) {
  .wt-entry { transition: none; }
  .wt-entry:hover { background: transparent; }
  .wt-entry__delete { transition: none; }
}

/* Mobile — keep stripe visible, compress padding */
@media (max-width: 480px) {
  .wt-entry { padding: 0.75rem 0; gap: 0.75rem; }
  .wt-entry__text { font-size: 0.875rem; }
}

/* ─── Spec cards: Tools + Parts ───────────────────────────────────────────
   Shared .wt-spec-card base with two variants:
   - .wt-spec-card--tool : cool slate/blue. Metal-on-pegboard feel (soft
     drop shadow, slight lift on hover). "Things I use."
   - .wt-spec-card--part : warm amber. Item-in-a-tray feel (no shadow, subtle
     inner tint, flat). "Things I install/consume."
   Shared panel-header + stat chips tie it into the Safety + Tips aesthetic. */

.wt-panel-header--full { grid-column: 1 / -1; }

/* Full-width headers inside a CSS grid */
#tools-grid { display: grid; grid-template-columns: 1fr; gap: 0.625rem; }
#parts-list { display: grid; grid-template-columns: 1fr; gap: 0.625rem; }
@media (min-width: 640px) {
  #tools-grid, #parts-list { grid-template-columns: 1fr 1fr; }
  .wt-panel-header--full { grid-column: 1 / -1; }
}

.wt-spec-card {
  display: grid;
  grid-template-columns: 2.5rem 1fr;
  gap: 0.875rem;
  align-items: start;
  padding: 0.875rem 1rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  transition: transform 140ms var(--ease, ease-out),
              box-shadow 140ms var(--ease, ease-out),
              border-color 140ms var(--ease, ease-out);
  position: relative;
  min-width: 0;
}
.wt-spec-card__icon {
  width: 2.5rem;
  height: 2.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 0.5rem;
  flex-shrink: 0;
}
.wt-spec-card__body {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}
.wt-spec-card__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.625rem;
  min-width: 0;
}
.wt-spec-card__name {
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--text);
  margin: 0;
  min-width: 0;
  word-wrap: break-word;
  flex: 1 1 auto;
}
.wt-spec-card__spec {
  font-size: 0.8125rem;
  line-height: 1.45;
  color: var(--text-muted, var(--text-subtle));
  margin: 0;
}
.wt-spec-card__chips {
  display: inline-flex;
  gap: 0.25rem;
  align-items: center;
  flex-shrink: 0;
  flex-wrap: wrap;
  justify-content: flex-end;
  max-width: 60%;
}

/* Tool variant — cool slate/blue, drop shadow (sitting on a workbench) */
.wt-spec-card--tool {
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.035), 0 3px 6px -3px rgba(0, 0, 0, 0.08);
}
.wt-spec-card--tool:hover {
  transform: translateY(-1px);
  box-shadow: 0 2px 0 rgba(0, 0, 0, 0.05), 0 6px 12px -6px rgba(0, 0, 0, 0.12);
  border-color: color-mix(in srgb, #0ea5e9 35%, var(--border));
}
.wt-spec-card--tool .wt-spec-card__icon {
  background: color-mix(in srgb, #0ea5e9 10%, var(--surface));
  color: #0369a1;
  border: 1px solid color-mix(in srgb, #0ea5e9 22%, var(--border));
}
html[data-theme-resolved="dark"] .wt-spec-card--tool .wt-spec-card__icon {
  background: color-mix(in srgb, #0ea5e9 16%, var(--surface));
  color: #7dd3fc;
  border-color: color-mix(in srgb, #0ea5e9 28%, var(--border));
}

/* Part variant — warm amber, flat, items-in-a-tray */
.wt-spec-card--part {
  background: color-mix(in srgb, var(--surface) 96%, #f59e0b 4%);
  border-color: color-mix(in srgb, #f59e0b 18%, var(--border));
  box-shadow: inset 0 1px 0 color-mix(in srgb, #f59e0b 8%, transparent);
}
.wt-spec-card--part:hover {
  transform: translateY(-1px);
  border-color: color-mix(in srgb, #f59e0b 40%, var(--border));
}
.wt-spec-card--part .wt-spec-card__icon {
  background: color-mix(in srgb, #f59e0b 14%, var(--surface));
  color: #b45309;
  border: 1px solid color-mix(in srgb, #f59e0b 26%, var(--border));
}
html[data-theme-resolved="dark"] .wt-spec-card--part {
  background: color-mix(in srgb, var(--surface) 92%, #f59e0b 8%);
  border-color: color-mix(in srgb, #f59e0b 22%, var(--border));
}
html[data-theme-resolved="dark"] .wt-spec-card--part .wt-spec-card__icon {
  background: color-mix(in srgb, #f59e0b 22%, var(--surface));
  color: #fcd34d;
  border-color: color-mix(in srgb, #f59e0b 32%, var(--border));
}

/* Chips (shared with tips/safety patterns but with tool/part colors) */
.wt-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0.1875rem 0.5rem;
  border-radius: 0.25rem;
  white-space: nowrap;
  flex-shrink: 0;
}
.wt-chip__mono {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, monospace);
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
}
.wt-chip--required {
  color: #0369a1;
  background: color-mix(in srgb, #0ea5e9 14%, transparent);
}
.wt-chip--optional {
  color: var(--text-subtle);
  background: color-mix(in srgb, var(--border) 55%, transparent);
}
.wt-chip--qty {
  color: #b45309;
  background: color-mix(in srgb, #f59e0b 16%, transparent);
  text-transform: none;
  letter-spacing: 0;
  font-size: 0.75rem;
  font-weight: 600;
}
.wt-chip--qty-tool {
  color: #0369a1;
  background: color-mix(in srgb, #0ea5e9 14%, transparent);
  text-transform: none;
  letter-spacing: 0;
  font-size: 0.75rem;
  font-weight: 600;
}
html[data-theme-resolved="dark"] .wt-chip--required,
html[data-theme-resolved="dark"] .wt-chip--qty-tool { color: #7dd3fc; background: color-mix(in srgb, #0ea5e9 22%, transparent); }
html[data-theme-resolved="dark"] .wt-chip--qty { color: #fcd34d; background: color-mix(in srgb, #f59e0b 22%, transparent); }

/* Stat chip additions (part variant for Parts panel header) */
.wt-stat--required {
  color: #0369a1;
  background: color-mix(in srgb, #0ea5e9 12%, transparent);
}
.wt-stat--part {
  color: #b45309;
  background: color-mix(in srgb, #f59e0b 14%, transparent);
}
html[data-theme-resolved="dark"] .wt-stat--required { color: #7dd3fc; background: color-mix(in srgb, #0ea5e9 20%, transparent); }
html[data-theme-resolved="dark"] .wt-stat--part     { color: #fcd34d; background: color-mix(in srgb, #f59e0b 20%, transparent); }

/* HC + reduced-motion */
.hc .wt-spec-card { box-shadow: none !important; border-width: 2px; }
.hc .wt-spec-card:hover { transform: none; }
@media (prefers-reduced-motion: reduce) {
  .wt-spec-card { transition: none; }
  .wt-spec-card:hover { transform: none; }
}
/* Mobile — tighten the horizontal padding and text so more chips fit per row,
   but never touch min-height: the 48px tap target is the whole point on a
   phone held in one gloved hand. */
@media (max-width: 767px) {
  .wt-demo-grid { gap: 0.375rem; }
  .wt-demo-tile {
    padding: 0.5rem 0.75rem 0.5rem 0.625rem;
    gap: 0.4375rem;
    font-size: 0.8125rem;
  }
  /* Drop the runtime on phones — it is the least load-bearing detail and
     cutting it buys a whole row back. It survives in the aria-label. */
  .wt-demo-tile__time { display: none; }
  /* Swap to short labels so three chips fit per row instead of two. Nine
     full-length pills wrapped to five rows on a 390px screen, which is the
     footprint this redesign existed to kill. */
  .wt-demo-tile__name  { display: none; }
  .wt-demo-tile__short { display: inline; }
  /* Hover lift is meaningless on touch and leaves pills stuck in hover state
     after a tap on iOS. */
  .wt-demo-tile:hover { transform: none; }
}
/* Extra-narrow (≤380px) — iPhone SE etc. shrink a hair more */
@media (max-width: 380px) {
  .wt-demo-tile {
    padding: 0.5rem 0.625rem 0.5rem 0.5625rem;
    font-size: 0.75rem;
  }
}
.wt-hero h1 { margin: 0 0 0.75rem; }
.wt-hero p {
  margin: 0 auto;
  max-width: 40rem;
  color: var(--text-muted);
  font-size: clamp(1rem, 1.6vw, 1.1875rem);
  line-height: 1.55;
}
/* Hero text sits above the 3D statue canvas so the overlap region
   reads the headline, not the model. #hero-statue uses z-index:0. */
.wt-hero .wt-eyebrow-mono,
.wt-hero h1,
.wt-hero p {
  position: relative;
  z-index: 2;
}

/* ── 13. Tabs ───────────────────────────────────────────────────────────── */

.wt-tab-track {
  display: flex;
  gap: 0.25rem;
  padding: 0.3125rem;
  background: var(--surface-mute);
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
}
.wt-tab {
  flex: 1;
  min-height: var(--tap-min);
  padding: 0 0.875rem;
  border-radius: var(--radius);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.005em;
  color: var(--text-muted);
  background: transparent;
  border: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.375rem;
  white-space: nowrap;
  transition: background var(--duration-fast) var(--ease),
              color var(--duration-fast) var(--ease),
              box-shadow var(--duration-fast) var(--ease);
}
.wt-tab:hover { color: var(--text); background: var(--surface); }
.wt-tab-active {
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-sm);
}
.dark .wt-tab-active {
  background: var(--surface-raised);
  color: var(--primary);
  box-shadow: 0 0 0 1px var(--border-strong);
}

/* ── 14. Step cards (timeline) ──────────────────────────────────────────── */

.wt-step-card {
  display: flex;
  gap: 0.875rem;
  padding: 0.875rem 1rem 1.25rem;
  position: relative;
  border-radius: var(--radius-lg);
  transition: background var(--duration-fast) var(--ease);
}
.wt-step-card:hover { background: var(--surface-mute); }

.wt-step-card:not(:last-child)::before {
  content: '';
  position: absolute;
  left: calc(1rem + 1.125rem);
  top: calc(0.875rem + 2.25rem + 0.25rem);
  bottom: 0;
  width: 2px;
  background: var(--border);
  pointer-events: none;
}
.wt-step-card--done:not(:last-child)::before {
  background: var(--success);
  opacity: 0.35;
}
.wt-step-card--active {
  background: var(--primary-soft);
}
.wt-step-card--done .wt-step-instruction {
  text-decoration: line-through;
  text-decoration-color: var(--border-strong);
  color: var(--text-muted);
  opacity: 0.75;
}

.wt-step-num {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--radius-pill);
  background: var(--surface-mute);
  color: var(--text-muted);
  font-size: 0.75rem;
  font-weight: 700;
  font-feature-settings: "tnum";
  flex-shrink: 0;
  margin-top: 0.125rem;
  position: relative;
  z-index: 1;
  border: 1.5px solid var(--border);
  transition: background var(--duration) var(--ease),
              color var(--duration) var(--ease),
              border-color var(--duration) var(--ease),
              box-shadow var(--duration) var(--ease);
}
.wt-step-card--active .wt-step-num {
  background: var(--primary);
  color: var(--primary-contrast);
  border-color: var(--primary);
  box-shadow: 0 0 0 4px var(--primary-soft);
}
.wt-step-card--done .wt-step-num {
  background: var(--success);
  color: #fff;
  border-color: var(--success);
}

@keyframes wt-check-pop {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.25); }
  65%  { transform: scale(0.9); }
  100% { transform: scale(1); }
}
.wt-step-num--checked { animation: wt-check-pop 0.35s var(--ease-spring); }

.wt-step-check {
  appearance: none;
  width: 1.75rem;
  height: 1.75rem;
  min-width: 1.75rem;
  border: 2px solid var(--border-strong);
  border-radius: var(--radius-pill);
  background: transparent;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  margin-top: 0.25rem;
  transition: all var(--duration-fast) var(--ease);
}
.wt-step-check:hover { border-color: var(--primary); background: var(--primary-soft); }
.wt-step-check:checked { background: var(--success); border-color: var(--success); }
.wt-step-check:checked::after {
  content: '';
  display: block;
  width: 0.6875rem;
  height: 0.6875rem;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='white'%3E%3Cpath fill-rule='evenodd' d='M12.416 3.376a.75.75 0 0 1 .208 1.04l-5 7.5a.75.75 0 0 1-1.154.114l-3-3a.75.75 0 0 1 1.06-1.06l2.353 2.353 4.493-6.74a.75.75 0 0 1 1.04-.207Z' clip-rule='evenodd'/%3E%3C/svg%3E") no-repeat center;
  background-size: contain;
}

.wt-step-instruction {
  font-size: 0.9375rem;
  line-height: 1.65;
  font-weight: 430;
  letter-spacing: -0.005em;
  color: var(--text);
}

.wt-step-instruction--typing::after {
  content: '';
  display: inline-block;
  width: 0.5ch;
  height: 1em;
  margin-left: 1px;
  vertical-align: text-bottom;
  background: var(--primary, currentColor);
  animation: wt-caret-blink 0.9s steps(1) infinite;
}

@keyframes wt-caret-blink {
  50% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .wt-step-instruction--typing::after { animation: none; opacity: 0; }
}

.hc .wt-step-instruction--typing::after { display: none; }

.wt-step-warning {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  margin-top: 0.5rem;
  padding: 0.625rem 0.875rem;
  border-radius: var(--radius);
  background: var(--warning-soft);
  border-left: 3px solid var(--warning);
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--warning-text);
}

/* ── Step chips (tools vs parts/ingredients) ──────────────────────────── */
/*
 * Tools chips lean neutral (slate/violet) — matches the existing rail.
 * Parts/ingredients chips use a warm "honey" palette (amber) so the two
 * chip families read distinctly at a glance. Dark-mode lifts the amber
 * tone so it stays legible on dim surfaces.
 */
.wt-chip--part {
  background: rgba(245, 158, 11, 0.08) !important;
  border-color: rgba(245, 158, 11, 0.35) !important;
  color: #b45309 !important;
}
.wt-chip--part svg { color: #d97706 !important; }
html.dark .wt-chip--part,
[data-theme="dark"] .wt-chip--part {
  background: rgba(251, 191, 36, 0.10) !important;
  border-color: rgba(251, 191, 36, 0.40) !important;
  color: #fcd34d !important;
}
html.dark .wt-chip--part svg,
[data-theme="dark"] .wt-chip--part svg {
  color: #fbbf24 !important;
}
/* High-contrast mode: switch to bold outline + system color */
.hc .wt-chip--part {
  background: transparent !important;
  border: 2px solid currentColor !important;
  color: #b45309 !important;
}
.hc.dark .wt-chip--part { color: #fcd34d !important; }

/* ── 15. Progress bar ───────────────────────────────────────────────────── */

.wt-progress {
  position: relative;
  height: 0.5rem;
  background: var(--surface-mute);
  border-radius: var(--radius-pill);
  overflow: hidden;
  border: 1px solid var(--border);
}
.wt-progress__fill {
  position: relative;
  height: 100%;
  background: linear-gradient(90deg, var(--primary), color-mix(in srgb, var(--primary) 60%, #fff));
  border-radius: var(--radius-pill);
  transition: width var(--duration) var(--ease);
}
.wt-progress__fill::after {
  content: '';
  position: absolute;
  right: -2px;
  top: 50%;
  transform: translateY(-50%);
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--primary);
  box-shadow: 0 0 8px 2px color-mix(in srgb, var(--primary) 50%, transparent);
  transition: opacity var(--duration) var(--ease);
}
.wt-progress--complete .wt-progress__fill {
  background: linear-gradient(90deg, var(--success), color-mix(in srgb, var(--success) 60%, #fff));
}

@keyframes wt-burst {
  0%   { transform: scale(0.8); opacity: 0; }
  50%  { transform: scale(1.06); }
  100% { transform: scale(1); opacity: 1; }
}
.wt-burst { animation: wt-burst 0.4s var(--ease-spring) both; }

/* ── 16. Garage cards ───────────────────────────────────────────────────── */

.wt-garage-card {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1rem;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  background: var(--surface);
  cursor: pointer;
  transition: border-color var(--duration-fast) var(--ease),
              box-shadow var(--duration-fast) var(--ease),
              transform var(--duration-fast) var(--ease);
}
.wt-garage-card:hover {
  border-color: var(--primary);
  box-shadow: var(--shadow);
  transform: translateY(-1px);
}
.wt-garage-progress {
  height: 0.375rem;
  border-radius: var(--radius-pill);
  background: var(--surface-mute);
  overflow: hidden;
  margin-top: 0.375rem;
  border: 1px solid var(--border-muted);
}
.wt-garage-progress__fill {
  height: 100%;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, var(--primary), color-mix(in srgb, var(--primary) 50%, #fff));
  transition: width var(--duration) var(--ease);
}

/* ── 17. Loading spinner ────────────────────────────────────────────────── */

.wt-loader {
  width: 28px;
  height: 28px;
  border: 2.5px solid var(--border);
  border-top-color: var(--primary);
  border-radius: 50%;
  animation: wt-spin 0.65s linear infinite;
  margin: 0 auto;
}
@keyframes wt-spin { to { transform: rotate(360deg); } }

/* ── 18. Modals ─────────────────────────────────────────────────────────── */

.wt-modal-backdrop {
  position: fixed;
  inset: 0;
  background: color-mix(in srgb, #000 55%, transparent);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  z-index: 50;
}
.wt-modal {
  position: fixed;
  inset: 0;
  z-index: 51;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  pointer-events: none;
}
.wt-modal__panel {
  position: relative;
  z-index: 51;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg);
  max-width: 28rem;
  width: 100%;
  max-height: 90vh;
  overflow-y: auto;
  pointer-events: auto;
}
.wt-modal:not(.hidden) .wt-modal__panel { animation: wt-modal-in var(--duration) var(--ease-spring); }
@keyframes wt-modal-in {
  from { opacity: 0; transform: translateY(8px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* ── 19. Section transitions ────────────────────────────────────────────── */

.wt-fade-in {
  animation: wt-fade-in var(--duration) var(--ease);
}
@keyframes wt-fade-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ── 20. Upgrade banner / toast ─────────────────────────────────────────── */

@keyframes wt-slide-up {
  from { transform: translateY(100%); opacity: 0; }
  to   { transform: translateY(0);    opacity: 1; }
}
.wt-upgrade-banner { animation: wt-slide-up 0.35s var(--ease-spring) both; }

@keyframes wt-toast-in {
  from { opacity: 0; transform: translate(-50%, -12px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}
.wt-toast-in:not(.hidden) { animation: wt-toast-in var(--duration) var(--ease) both; }

/* ── 21. Voice mode overlay ─────────────────────────────────────────────── */

.voice-overlay { animation: wt-slide-up 0.3s var(--ease-spring) both; }
.voice-active {
  color: var(--danger) !important;
  animation: voice-pulse 1.5s ease-in-out infinite;
}
@keyframes voice-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.5; }
}

/* Two-row voice card: top = status + waveform + stop; bottom = protocol hints.
   Three states driven by .wt-voice--asleep / --awake / --paused on #voice-overlay. */
.wt-voice-card {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0.75rem 1rem;
  box-shadow: var(--shadow-lg);
  background: color-mix(in srgb, var(--surface) 95%, transparent);
  backdrop-filter: blur(10px);
  border-left: 3px solid transparent;
  transition: border-color 200ms var(--ease);
}
.wt-voice--asleep .wt-voice-card { border-left-color: color-mix(in srgb, var(--txm) 40%, transparent); }
.wt-voice--awake  .wt-voice-card { border-left-color: var(--accent); }

.wt-voice-main {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

/* Status dot — pulses amber when awake, dim gray when asleep.
   Clickable as a fallback to the wake word: tap to wake immediately.
   Larger tap target (28x28) with visual dot centered inside. */
.wt-voice-dot {
  position: relative;
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  transition: background 150ms var(--ease);
}
.wt-voice-dot:hover { background: color-mix(in srgb, var(--accent) 15%, transparent); }
.wt-voice-dot:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.wt-voice--asleep .wt-voice-dot::after {
  content: 'tap';
  position: absolute;
  font-size: 0.5625rem;
  color: var(--txm);
  bottom: -0.875rem;
  left: 50%;
  transform: translateX(-50%);
  opacity: 0.7;
  white-space: nowrap;
  pointer-events: none;
}
.wt-voice--awake .wt-voice-dot::after { display: none; }
.wt-voice-dot::before {
  content: '';
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--txm);
  transition: background 200ms var(--ease);
}
.wt-voice-dot__ring {
  position: absolute;
  inset: 7px;
  border-radius: 50%;
  border: 2px solid transparent;
  pointer-events: none;
}
.wt-voice--asleep .wt-voice-dot::before { background: color-mix(in srgb, var(--txm) 60%, transparent); }
.wt-voice--awake  .wt-voice-dot::before { background: var(--accent); }
.wt-voice--awake  .wt-voice-dot__ring   { animation: wt-voice-ring 1.2s ease-out infinite; }
@keyframes wt-voice-ring {
  0%   { border-color: color-mix(in srgb, var(--accent) 80%, transparent); transform: scale(1); opacity: 1; }
  100% { border-color: transparent; transform: scale(1.8); opacity: 0; }
}

.wt-voice-hints {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  flex-wrap: wrap;
  font-size: 0.75rem;
  line-height: 1.2;
  color: var(--txm);
}
.wt-voice-hint-label {
  font-weight: 600;
  color: var(--txm);
  margin-right: 0.125rem;
}
.wt-voice-hint-arrow,
.wt-voice-hint-sep {
  color: color-mix(in srgb, var(--txm) 50%, transparent);
  font-weight: 600;
}
.wt-voice-hint-chip {
  display: inline-block;
  padding: 0.125rem 0.5rem;
  border-radius: 999px;
  background: var(--s3);
  border: 1px solid var(--bd);
  color: var(--text);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.6875rem;
  white-space: nowrap;
}
.wt-voice-hint-chip--wake  { border-color: var(--accent); color: var(--accent); }
.wt-voice-hint-chip--end   { border-color: color-mix(in srgb, var(--accent) 60%, var(--bd)); }

/* ── Mode-aware visibility ─────────────────────────────────────────────── */
/* Show only the hint row matching the active mode. */
.wt-voice-mode--wake .wt-voice-hints--ptt,
.wt-voice-mode--ptt  .wt-voice-hints--wake { display: none; }

/* Upgrade state — the overlay is reused to explain why voice did not start.
   Everything that implies a live session (dot, waveform, transcript, command
   hints) is stripped out; only the message and its dismiss button remain, and
   the message is allowed to wrap instead of truncating to one line. */
.wt-voice--upgrade .wt-voice-dot,
.wt-voice--upgrade .wt-voice-waveform,
.wt-voice--upgrade #voice-noise-indicator,
.wt-voice--upgrade #voice-transcript,
.wt-voice--upgrade .wt-voice-mode-toggle,
.wt-voice--upgrade .wt-voice-hints,
.wt-voice--upgrade .wt-voice-ptt { display: none; }
.wt-voice--upgrade .wt-voice-card { border-left-color: var(--accent); }
.wt-voice--upgrade #voice-status {
  white-space: normal;
  overflow: visible;
  line-height: 1.5;
  color: var(--text);
}

/* PTT button only shows in PTT mode. */
.wt-voice-mode--wake .wt-voice-ptt { display: none; }

/* In PTT mode the waveform + dot take less visual real estate since the
   user is driving with the button, not the wake word. */
.wt-voice-mode--ptt .wt-voice-waveform { display: none; }
.wt-voice-mode--ptt .wt-voice-dot::after { content: none; }
.wt-voice-mode--ptt .wt-voice-dot { cursor: default; }
.wt-voice-mode--ptt .wt-voice-dot:hover { background: transparent; }

/* ── Mode toggle button (left side of the bar) ─────────────────────────── */
.wt-voice-mode-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.375rem 0.75rem;
  border-radius: 999px;
  border: 1px solid var(--bd);
  background: var(--s2);
  color: var(--text);
  font-size: 0.75rem;
  font-weight: 600;
  cursor: pointer;
  flex-shrink: 0;
  transition: all 150ms var(--ease);
  min-height: 32px;
}
.wt-voice-mode-toggle:hover  { background: var(--s3); border-color: var(--accent); }
.wt-voice-mode-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.wt-voice-mode-toggle__icon  { width: 14px; height: 14px; display: inline-flex; }
.wt-voice-mode-toggle__icon svg { width: 100%; height: 100%; }
/* Only the matching icon + label shows */
.wt-voice-mode-toggle__icon--ptt,
.wt-voice-mode-toggle__label--ptt,
.wt-voice-mode--ptt .wt-voice-mode-toggle__icon--wake,
.wt-voice-mode--ptt .wt-voice-mode-toggle__label--wake { display: none; }
.wt-voice-mode--ptt .wt-voice-mode-toggle__icon--ptt,
.wt-voice-mode--ptt .wt-voice-mode-toggle__label--ptt { display: inline-flex; }
.wt-voice-mode--ptt .wt-voice-mode-toggle {
  border-color: var(--accent);
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}

/* ── Push-to-talk button (large, pressable, tap-friendly) ──────────────── */
.wt-voice-ptt {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
  width: 100%;
  min-height: 5.25rem;
  padding: 0.75rem 1rem;
  margin-top: 0.25rem;
  border-radius: var(--radius-lg);
  border: 2px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, var(--s2));
  color: var(--accent);
  font-size: 1rem;
  font-weight: 700;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: none; /* prevent pinch/scroll interception during hold */
  transition: transform 90ms var(--ease), background 120ms var(--ease), box-shadow 120ms var(--ease);
  box-shadow: 0 2px 8px color-mix(in srgb, var(--accent) 20%, transparent);
}
.wt-voice-ptt:hover  { background: color-mix(in srgb, var(--accent) 18%, var(--s2)); }
.wt-voice-ptt:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
.wt-voice-ptt--pressed,
.wt-voice-ptt:active {
  background: var(--accent);
  color: white;
  transform: scale(0.98);
  box-shadow: inset 0 2px 8px color-mix(in srgb, #000 25%, transparent);
  animation: wt-ptt-pulse 1.2s ease-in-out infinite;
}
@keyframes wt-ptt-pulse {
  0%, 100% { box-shadow: inset 0 2px 8px color-mix(in srgb, #000 25%, transparent), 0 0 0 0 color-mix(in srgb, var(--accent) 60%, transparent); }
  50%      { box-shadow: inset 0 2px 8px color-mix(in srgb, #000 25%, transparent), 0 0 0 8px color-mix(in srgb, var(--accent) 0%, transparent); }
}
.wt-voice-ptt__icon { width: 22px; height: 22px; display: inline-flex; }
.wt-voice-ptt__icon svg { width: 100%; height: 100%; }
.wt-voice-ptt__label { font-weight: 700; letter-spacing: 0.01em; }
.wt-voice-ptt__hint {
  font-size: 0.6875rem;
  font-weight: 400;
  opacity: 0.75;
  letter-spacing: 0.04em;
}
@media (prefers-reduced-motion: reduce) {
  .wt-voice-ptt--pressed,
  .wt-voice-ptt:active { animation: none; }
}

/* On narrow phones make the mode toggle more compact */
@media (max-width: 480px) {
  .wt-voice-mode-toggle { padding: 0.25rem 0.5rem; font-size: 0.6875rem; }
  .wt-voice-mode-toggle__label--wake,
  .wt-voice-mode-toggle__label--ptt { display: none !important; }
  .wt-voice-ptt { min-height: 4.5rem; font-size: 0.9375rem; }
}

/* Fewer hints shown on narrow phones to keep the overlay compact */
@media (max-width: 480px) {
  .wt-voice-hint-arrow,
  .wt-voice-hint-sep { display: none; }
  .wt-voice-hint-chip { font-size: 0.625rem; padding: 0.125rem 0.375rem; }
}

/* ── Voice onboarding modal ─────────────────────────────────────────────── */
.wt-voice-onboard {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  /* Use dynamic viewport units so mobile browser chrome (url bar) doesn't
     cut the modal off at the top or bottom when it expands/contracts */
  padding-top: max(1rem, env(safe-area-inset-top));
  padding-bottom: max(1rem, env(safe-area-inset-bottom));
}
.wt-voice-onboard.hidden { display: none; }
.wt-voice-onboard__backdrop {
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, #000 60%, transparent);
  backdrop-filter: blur(4px);
}
.wt-voice-onboard__panel {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--bd);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl);
  padding: 1.75rem 1.5rem;
  max-width: 30rem;
  width: 100%;
  max-height: min(90vh, calc(100dvh - 2rem));
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  animation: wt-voice-onboard-in 0.28s var(--ease-spring) both;
  box-sizing: border-box;
}
@keyframes wt-voice-onboard-in {
  from { opacity: 0; transform: translateY(12px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0)    scale(1); }
}
.wt-voice-onboard__title {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--text);
  margin: 0 0 0.5rem;
  line-height: 1.3;
}
.wt-voice-onboard__lead {
  font-size: 0.9375rem;
  color: var(--txm);
  margin: 0 0 1.25rem;
  line-height: 1.5;
}

/* Mobile tuning — shrink padding + type scale so the whole modal fits without
   needing to scroll on a 375×667 iPhone SE viewport. */
@media (max-width: 480px) {
  .wt-voice-onboard { padding: 0.75rem; }
  .wt-voice-onboard__panel {
    padding: 1.25rem 1rem;
    border-radius: var(--radius);
  }
  .wt-voice-onboard__title { font-size: 1.125rem; }
  .wt-voice-onboard__lead  { font-size: 0.875rem; margin-bottom: 1rem; }
  .wt-voice-onboard__steps { gap: 0.625rem; margin-bottom: 1rem; }
  .wt-voice-onboard__steps li { font-size: 0.875rem; }
  .wt-voice-onboard__num {
    width: 1.5rem; height: 1.5rem; font-size: 0.8125rem;
  }
  .wt-voice-onboard__example {
    padding: 0.625rem 0.75rem;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.25rem;
    margin-bottom: 1rem;
  }
}
.wt-voice-onboard__steps {
  list-style: none;
  padding: 0;
  margin: 0 0 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.wt-voice-onboard__steps li {
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
  font-size: 0.9375rem;
  color: var(--text);
  line-height: 1.4;
}
.wt-voice-onboard__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 50%;
  background: var(--accent);
  color: white;
  font-weight: 700;
  font-size: 0.875rem;
}
.wt-voice-onboard__hint {
  display: block;
  font-size: 0.8125rem;
  color: var(--txm);
  margin-top: 0.125rem;
}
/* Two-mode picker in the onboarding modal */
.wt-voice-onboard__modes {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin: 0 0 1.25rem;
}
.wt-voice-onboard__mode {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 0.875rem 1rem;
  border-radius: var(--radius);
  border: 2px solid var(--bd);
  background: var(--s2);
  color: var(--text);
  text-align: left;
  cursor: pointer;
  transition: all 150ms var(--ease);
  font: inherit;
}
.wt-voice-onboard__mode:hover {
  border-color: color-mix(in srgb, var(--accent) 60%, var(--bd));
  background: var(--s3);
}
.wt-voice-onboard__mode--selected {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, var(--s2));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 20%, transparent);
}
.wt-voice-onboard__mode-icon {
  flex-shrink: 0;
  width: 2rem;
  height: 2rem;
  color: var(--accent);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.wt-voice-onboard__mode-icon svg { width: 100%; height: 100%; }
.wt-voice-onboard__mode-body {
  display: flex;
  flex-direction: column;
  gap: 0.1875rem;
}
.wt-voice-onboard__mode-body strong { font-size: 0.9375rem; color: var(--text); }
.wt-voice-onboard__mode-hint {
  font-size: 0.8125rem;
  color: var(--txm);
  line-height: 1.4;
}

.wt-voice-onboard__example {
  background: var(--s2);
  border: 1px dashed var(--bd);
  border-radius: var(--radius);
  padding: 0.75rem 1rem;
  margin: 0 0 1.25rem;
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
.wt-voice-onboard__example-label {
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--txm);
  font-weight: 700;
}
.wt-voice-onboard__example-text {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.875rem;
  color: var(--text);
}
.wt-voice-onboard__btn {
  width: 100%;
}

/* Step card flash when voice navigates to it — one pulse of the active color */
@keyframes wt-step-voice-flash {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 60%, transparent); }
  40%  { box-shadow: 0 0 0 6px color-mix(in srgb, var(--accent) 35%, transparent); }
  100% { box-shadow: 0 0 0 0 transparent; }
}
.wt-step-card--voice-flash {
  animation: wt-step-voice-flash 1.6s ease-out both;
}
@media (prefers-reduced-motion: reduce) {
  .wt-step-card--voice-flash { animation: none; outline: 2px solid var(--accent); outline-offset: 2px; }
}

/* ── 22. Mobile swipe panels ────────────────────────────────────────────── */

@media (max-width: 640px) {
  .wt-panels-swipe {
    display: flex;
    overflow-x: auto;
    /* A flex row is as tall as its tallest child, and `stretch` then pulls
       every other child up to match. With Steps at ~5900px that left Tools
       and Safety with thousands of pixels of dead space under their content.
       `flex-start` lets each panel keep its own height; the container's own
       height is then driven from the active panel by _syncSwipeHeight() in
       app.js, and overflow-y clips whichever taller neighbour is parked
       alongside it mid-swipe. */
    align-items: flex-start;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    transition: height 220ms var(--ease, ease-out);
  }
  .wt-panels-swipe::-webkit-scrollbar { display: none; }
  .wt-panels-swipe > .wt-panel {
    scroll-snap-align: start;
    /* Force every swipe to stop at the NEXT panel, not skip past it.
       Without this, iOS kinetic momentum on a fast flick carries through
       two panels at once. `always` overrides the momentum. */
    scroll-snap-stop: always;
    flex: 0 0 100%;
    min-width: 100%;
    /* Every panel must stay laid out for the swipe to have anything to
       scroll to, so this deliberately overrides the .hidden class that
       drives the desktop show/hide path. */
    display: block !important;
    align-self: flex-start;
  }
}
@media (prefers-reduced-motion: reduce) {
  .wt-panels-swipe { transition: none; }
}
@media (min-width: 641px) {
  .wt-panels-swipe { display: block; }
  .wt-panels-swipe > .wt-panel.hidden { display: none; }
}

/* ── 23. Print ──────────────────────────────────────────────────────────── */

@media print {
  :root {
    --bg: #ffffff;
    --surface: #ffffff;
    --surface-mute: #ffffff;
    --text: #000000;
    --text-muted: #333333;
    --border: #cccccc;
  }
  header, footer, #hero, #url-input, #extract-form, #extract-btn,
  #paste-btn, #try-example, #loading-section, #error-section,
  #rate-limit-section, #auth-required-section, #garage-section,
  #history-section, #video-player-container, #cookie-consent,
  #upgrade-modal, #upgrade-banner, #upgrade-toast, #share-toast,
  #byok-modal, .wt-upgrade-banner, #voice-toggle, #hc-toggle,
  #theme-toggle, #byok-btn, #usage-badge, #pro-badge,
  #steps-progress-reset, #share-btn, #print-btn, #add-tip-btn,
  #user-tip-input, [role="tablist"] {
    display: none !important;
  }
  .wt-panel, #panel-tools, #panel-steps, #panel-safety, #panel-tips {
    display: block !important;
  }
  #panels-container {
    display: block !important;
    overflow: visible !important;
    background: #fff !important;
    border: none !important;
  }
  body, main, .wt-step-card, .wt-garage-card { background: #fff !important; color: #000 !important; }
  .wt-step-card { padding: 0.5rem 0.75rem !important; break-inside: avoid; page-break-inside: avoid; }
  .wt-step-card:not(:last-child)::before { display: none !important; }
  .wt-step-card--done { opacity: 1 !important; }
  .wt-step-num { background: #000 !important; color: #fff !important; border: none !important; }
  .wt-step-instruction { color: #000 !important; }
  #panel-tools::before { content: 'Tools'; display: block; font-size: 1rem; font-weight: 700; margin-bottom: 0.5rem; border-bottom: 1px solid #ccc; padding-bottom: 0.25rem; }
  #panel-steps::before { content: 'Steps'; display: block; font-size: 1rem; font-weight: 700; margin-bottom: 0.5rem; border-bottom: 1px solid #ccc; padding-bottom: 0.25rem; margin-top: 1rem; }
  #panel-safety::before { content: 'Safety Warnings'; display: block; font-size: 1rem; font-weight: 700; margin-bottom: 0.5rem; border-bottom: 1px solid #ccc; padding-bottom: 0.25rem; margin-top: 1rem; }
  #panel-tips::before { content: 'Tips'; display: block; font-size: 1rem; font-weight: 700; margin-bottom: 0.5rem; border-bottom: 1px solid #ccc; padding-bottom: 0.25rem; margin-top: 1rem; }
  #results-section::after {
    content: 'stepstube — stepstube.keymakers.ai';
    display: block; margin-top: 2rem; padding-top: 0.5rem;
    border-top: 1px solid #ccc; font-size: 0.75rem; color: #666; text-align: center;
  }
  * { animation: none !important; transition: none !important; box-shadow: none !important; }
}

/* ── 24. Reduced motion ─────────────────────────────────────────────────── */

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

/* ── 25. Legacy token aliases ───────────────────────────────────────────── */
/* Map old design system v6 token names → v7 tokens.                       */
/* Keeps landing/terms/privacy and any --pg/--s1/--tx1 inline styles working */
/* while we migrate them. Remove once all references are updated.          */

:root, .dark, .hc {
  --pg:   var(--bg);
  --s1:   var(--surface-mute);
  --s2:   var(--surface);
  --s3:   var(--surface-mute);
  --bd:   var(--border);
  --bd2:  var(--border-strong);
  --tx1:  var(--text);
  --tx2:  var(--text-muted);
  --txm:  var(--text-subtle);
  --pr:   var(--primary);
  --pr2:  var(--primary-hover);
  --prs:  var(--primary-soft);
  --prm:  var(--primary-strong);
  --warn: var(--warning);
}

/* Tailwind dark: compatibility:                                            */
/* The .dark class is still applied on <html> (by theme-init.js when        */
/* resolved theme is dark), so existing dark: utilities keep working.       */

/* ════════════════════════════════════════════════════════════════════════ */
/* Empty-state vignettes (renderGarage / renderHistory)                     */
/* Quiet, brand-tinted line illustrations + invitation copy. The SVGs use   */
/* currentColor so they auto-tint to the local text variable.               */
/* ════════════════════════════════════════════════════════════════════════ */
.wt-empty-vignette {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.25rem;
  padding: 2.25rem 1.5rem 2rem;
  margin: 0;
  border-radius: 1.25rem;
  background: var(--s2);
  border: 1px dashed var(--bd);
  color: var(--tx2);
  text-align: center;
}
.wt-empty-vignette--wide { padding-block: 1.75rem; }
.wt-empty-vignette__art {
  display: block;
  width: 100%;
  max-width: 420px;
  height: auto;
  color: var(--pr); /* drives currentColor inside the SVG */
  opacity: 0.85;
}
.wt-empty-vignette__caption {
  max-width: 38ch;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.wt-empty-vignette__title {
  font-family: var(--wt-font-display, inherit);
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0.005em;
  color: var(--tx1);
  margin: 0;
}
.wt-empty-vignette__copy {
  font-size: 0.875rem;
  line-height: 1.55;
  color: var(--txm);
  margin: 0;
}
@media (min-width: 640px) {
  .wt-empty-vignette { padding: 2.5rem 2rem 2.25rem; }
  .wt-empty-vignette__art { max-width: 520px; }
}
@media (prefers-reduced-motion: no-preference) {
  .wt-empty-vignette__art {
    transition: opacity 320ms ease, transform 320ms ease;
  }
  .wt-empty-vignette:hover .wt-empty-vignette__art { opacity: 1; }
}
.hc .wt-empty-vignette {
  border-style: solid;
  border-width: 2px;
  border-color: var(--bd2);
}
.hc .wt-empty-vignette__art { opacity: 1; }

/* Destructive-action two-step confirm state. Applied by wtConfirm() in app.js. */
.wt-confirm-pending {
  background-color: color-mix(in srgb, var(--danger, #dc2626) 14%, var(--bg2)) !important;
  color: var(--danger, #dc2626) !important;
  outline: 2px solid var(--danger, #dc2626);
  outline-offset: 2px;
}
@media (prefers-reduced-motion: no-preference) {
  .wt-confirm-pending {
    animation: wt-confirm-pulse 1.2s ease-in-out infinite;
  }
}
@keyframes wt-confirm-pulse {
  0%, 100% { outline-color: var(--danger, #dc2626); }
  50%      { outline-color: color-mix(in srgb, var(--danger, #dc2626) 40%, transparent); }
}
.hc .wt-confirm-pending {
  outline-width: 3px;
  background-color: var(--bg2) !important;
}

/* ═══════════════════════════════════════════════════════════════════════
   Mobile polish pass — UI.18 swarm audit fixes.
   Addresses: sticky stack math, overflow, touch targets, chip wrapping,
   progressive density. Desktop-untouched where possible. */

/* ─── Global overflow guard ───────────────────────────────────────────── */
body {
  /* `clip` (CSS3) clips overflow WITHOUT creating a scroll container. Using
     `hidden` here created an implicit scroll context on body that conflicted
     with nested `.wt-panels-swipe` horizontal touch scroll — swipe tabs
     stopped responding on mobile. `clip` fixes that while still preventing
     rogue long words/URLs from triggering horizontal page scroll.
     Browser support: Chrome 90+, Safari 16+, Firefox 81+. */
  overflow-x: clip;
}

/* ─── Sticky stack — correct offsets ──────────────────────────────────── */
.wt-tab-sticky {
  position: sticky;
  top: var(--header-height);
  z-index: 30;
  background: var(--bg);
  /* Solid backdrop so scrolled content doesn't peek through the py-2 gap
     above the tab track. */
}
.wt-progress-sticky {
  position: sticky;
  top: calc(var(--header-height) + var(--tabbar-height));
  z-index: 20;
  /* Crisp bottom edge so step cards scrolling under the sticky bar have
     a clean hand-off instead of blurring into it. */
  border-bottom: 1px solid var(--border);
  padding-top: 0.5rem;
}

/* The progress bar is now a sibling of the panels-container (not inside
   it), so `position: sticky` binds to the viewport correctly on every
   viewport size. Visibility is gated by tab via switchTab() — only
   visible when Steps tab is active. */

/* Panels container — intentionally NO `overflow: hidden` here. It breaks
   `position: sticky` on the progress bar descendant in Chromium/WebKit by
   creating a new scroll container context. The `body { overflow-x: hidden }`
   above already catches any stray horizontal scroll from card shadows. */

/* ─── Panel header: wrap stats on narrow screens ──────────────────────── */
.wt-panel-header {
  flex-wrap: wrap;
  row-gap: 0.375rem;
}
@media (max-width: 480px) {
  .wt-panel-header {
    /* Stack stats under the label so they stop colliding at 375px */
    align-items: flex-start;
  }
  .wt-panel-header__stats {
    width: 100%;
    justify-content: flex-start;
  }
}

/* Bump stat chips up a tick — 10px was below arm's-length legibility */
.wt-stat { font-size: 0.6875rem; }

/* ─── Spec cards — chips drop below name on narrow screens ────────────── */
@media (max-width: 520px) {
  .wt-spec-card__head {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.375rem;
  }
  .wt-spec-card__chips {
    max-width: 100%;
    justify-content: flex-start;
    flex-wrap: wrap;
  }
}

/* ─── Tab bar — Safety count becomes a dot on mobile ──────────────────── */
@media (max-width: 480px) {
  #safety-count-badge {
    /* Collapse the numeric pill to a severity dot — count stays visible
       inside the panel header anyway. Prevents the Safety tab from clipping
       its own label when the count is 2+ digits. */
    width: 0.5rem;
    height: 0.5rem;
    min-width: 0.5rem;
    padding: 0;
    border-radius: 50%;
    font-size: 0;
    line-height: 0;
    overflow: hidden;
    color: transparent;
  }
}

/* ─── Step cards: tighter mobile density ──────────────────────────────── */
@media (max-width: 480px) {
  /* Step-row labels collapse to a compact chip above the chip row */
  .wt-step-row__label {
    font-size: 0.5625rem;
    padding-bottom: 0.125rem;
    padding-top: 0;
    min-width: 0;
    color: var(--text-subtle);
  }
  /* Slightly tighter pill padding to fit more per row */
  .wt-step-pill {
    font-size: 0.6875rem;
    padding: 0.125rem 0.4375rem;
  }
  /* Inline note compresses */
  .wt-step-note {
    padding-left: 0.625rem;
    margin-top: 0.5rem;
  }
  .wt-step-note__text { font-size: 0.75rem; line-height: 1.5; }
  .wt-step-note__eyebrow { font-size: 0.5625rem; }
  /* Warning banner tightens */
  .wt-step-warning {
    padding: 0.4375rem 0.625rem;
    font-size: 0.75rem;
  }
}

/* Step completion checkbox — 48px tap target minimum (WCAG AAA, gloved
   hands). The visual checkbox stays small; the hit-area expands via padding
   and a transparent extended label wrapper. */
.wt-step-check {
  cursor: pointer;
}
@media (max-width: 640px) {
  .wt-step-check {
    width: 2.75rem;
    height: 2.75rem;
    padding: 0.625rem;
    box-sizing: border-box;
  }
}

/* ─── Spotlight — tighter quote ornament on mobile ────────────────────── */
@media (max-width: 480px) {
  .wt-spotlight { padding: 0.875rem 1rem; }
  .wt-spotlight__quote {
    font-size: 0.875rem;
    line-height: 1.5;
  }
  .wt-spotlight__quote--tip {
    font-size: 0.9375rem;
    padding-left: 1rem;
  }
  .wt-spotlight__quote--tip::before {
    font-size: 1.375rem;
    top: 0.05rem;
    opacity: 0.45;
  }
  .wt-spotlight__header {
    align-items: flex-start;
    gap: 0.5rem;
    flex-wrap: wrap;
  }
  .wt-spotlight__eyebrow {
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 60%;
  }
  .wt-spotlight__stars-num { font-size: 0.6875rem; }
  .wt-spotlight__divider { margin: 0.75rem 0; }
}

/* ─── Safe-area insets for all fixed bottom bars ──────────────────────── */
#voice-overlay,
#upgrade-banner,
#cookie-consent,
.wt-mobile-extract-bar {
  padding-bottom: max(0.75rem, env(safe-area-inset-bottom, 0.75rem));
}


/* ─── Step-card inline rows: Tools + Parts + Notes ────────────────────────
   Labeled rows inside each step card so the user scans each step as a
   "recipe card": instruction → tools → parts → warnings → pro tips. Visual
   language here matches the Tools tab (cool-blue for tools, amber for
   parts) and the Tips tab (quote-block notes with mono attribution). */

.wt-step-row {
  display: flex;
  align-items: flex-start;
  gap: 0.625rem;
  margin-top: 0.625rem;
  flex-wrap: wrap;
}
.wt-step-row__label {
  flex-shrink: 0;
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-subtle);
  padding-top: 0.25rem;
  min-width: 2.75rem;
}
.wt-step-row__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3125rem;
  flex: 1 1 auto;
  min-width: 0;
}

/* Unified pill shape shared by tool + part step chips */
.wt-step-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.3125rem;
  padding: 0.1875rem 0.5rem 0.1875rem 0.4375rem;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -0.005em;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  transition: border-color 120ms var(--ease, ease-out), background 120ms var(--ease, ease-out);
}
.wt-step-pill svg {
  width: 0.8125rem;
  height: 0.8125rem;
  flex-shrink: 0;
}
.wt-step-pill__qty {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, monospace);
  font-variant-numeric: tabular-nums;
  font-size: 0.6875rem;
  font-weight: 700;
  opacity: 0.85;
}

/* Tool pill — cool slate/blue (matches Tools tab) */
.wt-step-pill--tool {
  color: #0369a1;
  background: color-mix(in srgb, #0ea5e9 7%, var(--surface));
  border-color: color-mix(in srgb, #0ea5e9 20%, var(--border));
}
.wt-step-pill--tool:hover {
  border-color: color-mix(in srgb, #0ea5e9 40%, var(--border));
  background: color-mix(in srgb, #0ea5e9 12%, var(--surface));
}
html[data-theme-resolved="dark"] .wt-step-pill--tool {
  color: #7dd3fc;
  background: color-mix(in srgb, #0ea5e9 14%, var(--surface));
  border-color: color-mix(in srgb, #0ea5e9 26%, var(--border));
}

/* Part pill — warm amber (matches Parts tab) */
.wt-step-pill--part {
  color: #b45309;
  background: color-mix(in srgb, #f59e0b 9%, var(--surface));
  border-color: color-mix(in srgb, #f59e0b 24%, var(--border));
}
.wt-step-pill--part:hover {
  border-color: color-mix(in srgb, #f59e0b 44%, var(--border));
  background: color-mix(in srgb, #f59e0b 14%, var(--surface));
}
html[data-theme-resolved="dark"] .wt-step-pill--part {
  color: #fcd34d;
  background: color-mix(in srgb, #f59e0b 16%, var(--surface));
  border-color: color-mix(in srgb, #f59e0b 30%, var(--border));
}

/* Inline pro-tip / experience note — margin-note on a mechanic's manual.
   Subtle quote-block with left stripe, mono attribution eyebrow, italic body. */
.wt-step-note {
  --note-color: var(--text-subtle);
  margin: 0.625rem 0 0;
  padding: 0.5rem 0 0.5rem 0.75rem;
  border-left: 2px solid var(--note-color);
  background: transparent;
  display: block;
}
.wt-step-note__eyebrow {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.625rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-bottom: 0.25rem;
}
.wt-step-note__label {
  font-weight: 700;
  color: var(--note-color);
}
.wt-step-note__meta {
  font-weight: 500;
  color: var(--text-subtle);
  letter-spacing: 0.02em;
  text-transform: none;
}
.wt-step-note__text {
  margin: 0;
  font-size: 0.8125rem;
  line-height: 1.55;
  color: var(--text);
}

/* Variants: tip (emerald, "pro tip") vs insight (violet, "experience") */
.wt-step-note--tip { --note-color: #10b981; }
.wt-step-note--insight { --note-color: #8b5cf6; }

/* HC: thicker stripes, no color blending for chips */
.hc .wt-step-note { border-left-width: 4px; }
.hc .wt-step-pill { border-width: 2px; background: var(--surface); }
.hc .wt-step-pill--tool { color: var(--text); }
.hc .wt-step-pill--part { color: var(--text); }

/* Reduced-motion: no hover transitions on pills */
@media (prefers-reduced-motion: reduce) {
  .wt-step-pill { transition: none; }
}

/* Mobile: collapse the "Tools" / "Parts" label above the chips so it
   doesn't eat horizontal space on narrow screens. */
@media (max-width: 480px) {
  .wt-step-row {
    flex-direction: column;
    gap: 0.25rem;
  }
  .wt-step-row__label {
    padding-top: 0;
    min-width: 0;
  }
}

/* ─── Results view: kill dead space below the active tab panel ───────────
   Default layout gives <main> flex: 1 so the footer sticks to the bottom
   of the viewport on short pages (empty state, error banners, etc). But
   when results are showing and the active tab panel is short (e.g. Safety
   with two warnings), that same flex-grow paints a huge empty gap between
   the last card and the footer. Scope the override to "results visible"
   via :has() so short-content states still push the footer down. */
body:has(#results-section:not(.hidden)) #main-content {
  flex: 0 0 auto;
  padding-bottom: 1rem;
}
/* Trim the trailing padding inside each tab panel too — the outer
   panels-container already has breathing room above the footer. */
body:has(#results-section:not(.hidden)) .wt-panel:not(.hidden) {
  padding-bottom: 0;
}

/* ─── My Collection cards (rating + tags) ────────────────────────────────
   Used in the saved-guides grid. Anonymous users get the body-only layout
   (same as the historical Recent card); account holders get the footer
   with a 5-star rating rail + tag chips. */
.wt-col-card {
  display: flex;
  flex-direction: column;
  background: var(--s2);
  border: 1px solid var(--bd);
  border-radius: 0.75rem;
  overflow: hidden;
  transition: border-color 140ms var(--ease, ease-out),
              box-shadow 140ms var(--ease, ease-out);
}
.wt-col-card:hover {
  border-color: color-mix(in srgb, var(--primary) 40%, var(--bd));
}
.wt-col-card__body {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  cursor: pointer;
  transition: opacity 140ms var(--ease, ease-out);
}
.wt-col-card__body:hover { opacity: 0.9; }
.wt-col-card__footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 0.875rem;
  padding: 0.5rem 0.75rem 0.625rem;
  border-top: 1px solid color-mix(in srgb, var(--bd) 60%, transparent);
  background: color-mix(in srgb, var(--s3) 35%, transparent);
}

/* Star rating rail — 5 interactive star buttons */
.wt-col-rating {
  display: inline-flex;
  gap: 0.125rem;
  flex: 0 0 auto;
}
.wt-col-rating__star {
  background: transparent;
  border: 0;
  padding: 0.1875rem 0.25rem;
  font-size: 1rem;
  line-height: 1;
  color: var(--bd);
  cursor: pointer;
  transition: color 120ms var(--ease, ease-out), transform 120ms var(--ease, ease-out);
}
.wt-col-rating__star:hover { transform: scale(1.15); color: var(--primary); }
.wt-col-rating__star.is-active { color: var(--primary); }
.wt-col-rating__star:focus-visible {
  outline: 2px solid var(--focus-ring, var(--primary));
  outline-offset: 1px;
  border-radius: 3px;
}

/* Gemini-assigned metadata chips — read-only. Level uses the shared color
   scale (.wt-level-chip--easy|intermediate|hard|advanced). Category is a
   neutral pill so it doesn't compete with the level chip. */
.wt-col-chips {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0.3125rem;
  align-items: center;
}
.wt-level-chip,
.wt-cat-chip {
  display: inline-block;
  padding: 0.125rem 0.5rem;
  font-size: 0.6875rem;
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, monospace);
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: capitalize;
  border-radius: 999px;
  line-height: 1.5;
}
.wt-cat-chip {
  color: var(--txm);
  background: color-mix(in srgb, var(--txm) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--txm) 20%, var(--bd));
}

@media (prefers-reduced-motion: reduce) {
  .wt-col-card,
  .wt-col-rating__star { transition: none; }
  .wt-col-rating__star:hover { transform: none; }
}
.hc .wt-col-card { box-shadow: none; }



/* ── Extraction progress checklist + clickable Pro badge ─────────────────── */
.wt-progress-steps {
  list-style: none;
  margin: 0.75rem auto 0;
  padding: 0;
  display: inline-flex;
  flex-direction: column;
  gap: 0.375rem;
  text-align: left;
  font-size: 0.8125rem;
}
.wt-progress-steps[hidden] { display: none; }
.wt-progress-steps li {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--text-muted);
}
.wt-progress-steps__dot {
  width: 0.75rem;
  height: 0.75rem;
  border-radius: 9999px;
  border: 2px solid currentColor;
  flex: 0 0 auto;
  box-sizing: border-box;
}
.wt-progress-steps li[data-state="active"] { color: var(--text); font-weight: 600; }
.wt-progress-steps li[data-state="active"] .wt-progress-steps__dot {
  border-color: var(--primary);
  border-top-color: transparent;
  animation: wt-progress-spin 0.9s linear infinite;
}
.wt-progress-steps li[data-state="done"] { color: var(--text-muted); }
.wt-progress-steps li[data-state="done"] .wt-progress-steps__dot {
  background: var(--primary);
  border-color: var(--primary);
}
@keyframes wt-progress-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .wt-progress-steps li[data-state="active"] .wt-progress-steps__dot {
    animation: none;
    border-top-color: var(--primary);
    background: var(--primary);
  }
}

button.wt-pill-btn {
  font-family: inherit;
  cursor: pointer;
  position: relative;
}
button.wt-pill-btn:disabled { cursor: default; opacity: 1; }
/* Invisible extension so the small pill still meets a 48px touch target */
button.wt-pill-btn:not(:disabled)::after {
  content: "";
  position: absolute;
  inset: -0.75rem -0.5rem;
}
button.wt-pill-btn:not(:disabled):hover { filter: brightness(1.08); }
button.wt-pill-btn:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

/* ── Referral panel (Invite friends) ─────────────────────────────────────── */
.wt-referral-row { display: flex; gap: 0.5rem; align-items: stretch; }
.wt-referral-row .wt-input { flex: 1; min-width: 0; min-height: 48px; }
.wt-referral-copy { min-height: 48px; min-width: 48px; padding: 0 1rem; }
#share-guide-btn:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
