/* ============================================================
 * APEX CLIENT CRM (James Demo) · SHARED COMPONENT PRIMITIVES · CANONICAL
 *
 * Every visual primitive used on more than one of the 48 client
 * screens lives here. Page-local styles go in pages/<flow>/<screen>.css
 * with a .page-<screen>- prefix and NEVER redefine a primitive.
 *
 * Mirrors the locked Apex Sales OS primitives
 * (donor: shared/styles/02-primitives.css in this same repo) and adds
 * the James-CRM journey primitives the F1->F10 client flow needs:
 * the data-state orb shell, the context-bar, the progress-strip, the
 * wizard-card, the hold-btn (1500ms conic-gradient arc + white-wash),
 * the cockpit-kpi, the war-room hero, sparklines, steps-mini pills,
 * the done-strip, and the drawer-scrim.
 *
 * Class naming: kebab-case, no BEM, no SCSS.
 * Color: only var(--*). Never hardcoded.
 *   Exception: rgba(99,91,255,*) and rgba(255,255,255,*) for shadow,
 *   focus ring, blocked stripes, and white-wash where no token carries
 *   the precise alpha needed. These are the locked purple/white channels.
 *
 * BRAND LAWS BAKED IN (do not break):
 *   - Cool-spectrum / purple only. Primary #635bff.
 *   - Done / success = indigo #4f46e5. NEVER traffic-light green.
 *   - Stuck / error / off = gunmetal #1a1f36. NEVER red. NO red token.
 *   - ZERO emoji. Real SVG icons only (Lucide-style strokes).
 *   - Real Apex orb (rounded app-icon gradient sphere). Never a CSS "A".
 *   - No-scroll: every screen fits 1440x900. Lists scroll internally only.
 *   - Em-dashes forbidden in visible copy. Commas only.
 *   - No god / channel language anywhere.
 *
 * Animation keyframes referenced here:
 *   tickPulse, livePulse, dotPulse, shimmer, spin    — defined in 01-base.css
 *   orbRing, orbBar, orb-pulse, rec-pulse,
 *   celebration-heavy-fade, route-fade, stage-cross  — defined in 04-transitions.css
 * Keyframes defined locally (component-coupled): holdArc, washSweep, wfBarPulse.
 *
 * Owner: Terminal 0 (shared-foundation / 02-primitives).
 * READ-ONLY to every other terminal. Do not modify outside this file.
 *
 * Sections (in order):
 *   1.  Topbar + brand
 *   2.  Context bar + breadcrumbs
 *   3.  Progress strip (journey phase rail)
 *   4.  Buttons
 *   5.  Hold-to-confirm button (conic arc + white wash)
 *   6.  Chips + status chips
 *   7.  Steps-mini pills
 *   8.  Sparkline
 *   9.  Cockpit KPI tile
 *   10. War room hero
 *   11. View tabs + body
 *   12. Wizard card
 *   13. Modal
 *   14. Drawer + drawer-scrim
 *   15. Toast (+ push toast)
 *   16. Tables
 *   17. Bubbles (iMessage style)
 *   18. Apex orb (data-state driven)
 *   19. Slide stage
 *   20. Charts (area / hourly / heatmap / stacked / contrib / waveform)
 *   21. Form fields
 *   22. Toggle / segmented controls
 *   23. Stepper
 *   24. Done strip (section-complete confirmation)
 *   25. Diagonal-purple block-out (canonical replacement for ALL red)
 *   26. System-state full-page layouts
 * ============================================================ */


/* ------------------------------------------------------------
 * 1 · Topbar + brand
 * ------------------------------------------------------------ */
.topbar {
  position: sticky; top: 0; z-index: 50;
  background: var(--topbar-bg);
  border-bottom: 1px solid var(--border);
  backdrop-filter: saturate(140%) blur(8px);
}
.topbar-inner {
  height: 56px;
  max-width: 1440px;
  margin: 0 auto;
  padding: 0 24px;
  display: flex; align-items: center; gap: 24px;
}
.brand { display: flex; align-items: center; gap: 10px; }
.brand-mark {
  width: 32px; height: 32px; border-radius: 8px;
  object-fit: contain;
  box-shadow: 0 2px 8px -2px rgba(10,14,26,0.30);
  display: block;
}
.brand-name {
  font-size: 13px; font-weight: 600;
  color: var(--text);
  letter-spacing: -0.01em;
}
.brand-sub {
  font-size: 11.5px;
  color: var(--text-muted);
  margin-top: 1px;
}
.topbar-tabs { display: flex; align-items: center; gap: 2px; }
.topbar-tab {
  display: flex; align-items: center; gap: 6px;
  height: 32px; padding: 0 12px;
  font-size: 12.5px; color: var(--text-soft);
  border-radius: 8px;
  transition: background var(--t), color var(--t);
}
.topbar-tab:hover {
  background: var(--hover);
  color: var(--text);
}
.topbar-tab.active {
  background: var(--primary-soft);
  color: var(--primary);
}
.topbar-spacer { flex: 1; }
.topbar-actions { display: flex; align-items: center; gap: 10px; }
.topbar-avatar {
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--bg-tint);
  color: var(--text);
  font-size: 11px; font-weight: 600;
  display: grid; place-items: center;
  border: 1px solid var(--border);
  overflow: hidden;
  flex-shrink: 0;
}
/* When a headshot image is rendered inside the avatar circle, swap the
 * neutral tint background for a subtle gradient ring so the image reads
 * as a premium identity chip (matches the wallet-card aesthetic). */
.topbar-avatar.has-headshot {
  background: linear-gradient(135deg, rgba(99,91,255,0.18), rgba(122,115,255,0.08));
  border-color: rgba(99,91,255,0.28);
  box-shadow: 0 1px 2px rgba(10,14,26,0.05), inset 0 0 0 1px rgba(255,255,255,0.30);
}
.topbar-avatar.has-headshot img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
}


/* ------------------------------------------------------------
 * 2 · Context bar + breadcrumbs
 *   The thin row under the topbar that names where the client is in
 *   their journey. Left: breadcrumb trail. Right: live status / time.
 * ------------------------------------------------------------ */
.context-bar {
  display: flex; align-items: center; gap: 8px;
  max-width: 1440px;
  margin: 0 auto;
  padding: 6px 24px;
  font-size: 12px; color: var(--text-muted);
  border-bottom: 1px solid var(--border);
  background: var(--bg-soft);
}
.crumb { color: var(--text-soft); }
.crumb-current {
  color: var(--text);
  font-weight: 500;
}
.crumb-sep {
  color: var(--text-faint);
  margin: 0 4px;
}
.context-bar .right {
  margin-left: auto;
  display: flex; align-items: center; gap: 10px;
}
.context-bar .ctx-time {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--text-soft);
}


/* ------------------------------------------------------------
 * 3 · Progress strip (journey phase rail)
 *   The F1->F10 phase rail. One node per phase. Past = filled indigo,
 *   current = pulsing purple, upcoming = neutral. The connecting line
 *   fills purple up to the current node. Phase-gating is driven by
 *   journey.js which toggles .done / .current / .locked per node.
 * ------------------------------------------------------------ */
.progress-strip {
  display: flex; align-items: center;
  gap: 0;
  width: 100%;
  padding: 4px 0;
}
.progress-node {
  display: flex; flex-direction: column; align-items: center;
  gap: 6px;
  position: relative;
  flex: 0 0 auto;
}
.progress-dot {
  width: 24px; height: 24px;
  border-radius: 50%;
  background: var(--bg-tint);
  border: 1.5px solid var(--border-strong);
  display: grid; place-items: center;
  font-size: 11px; font-weight: 600;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  transition: background var(--t), border-color var(--t), color var(--t), box-shadow var(--t);
  flex-shrink: 0;
}
.progress-dot .ico {
  width: 13px; height: 13px;
}
.progress-label {
  font-size: 10.5px;
  color: var(--text-muted);
  white-space: nowrap;
  letter-spacing: 0.01em;
  transition: color var(--t);
}
.progress-link {
  height: 1.5px;
  flex: 1 1 auto;
  min-width: 28px;
  background: var(--border-strong);
  margin: 0 2px;
  align-self: flex-start;
  margin-top: 11px;
  transition: background var(--t);
}
/* done phase — indigo fill, check icon */
.progress-node.done .progress-dot {
  background: var(--status-done);
  border-color: var(--status-done);
  color: #ffffff;
}
.progress-node.done .progress-label { color: var(--text-soft); }
.progress-link.done { background: var(--grad); }
/* current phase — gradient core + soft purple pulse ring */
.progress-node.current .progress-dot {
  background: var(--grad);
  border-color: transparent;
  color: #ffffff;
  box-shadow: 0 0 0 4px rgba(99,91,255,0.16);
  animation: orb-pulse var(--dur-orb-pulse) infinite ease-in-out;
}
.progress-node.current .progress-label {
  color: var(--primary);
  font-weight: 600;
}
/* locked / upcoming phase — quiet, non-clickable */
.progress-node.locked { opacity: 0.7; }
.progress-node.locked .progress-dot { cursor: default; }


/* ------------------------------------------------------------
 * 4 · Buttons
 * ------------------------------------------------------------ */
.btn {
  display: inline-flex; align-items: center; gap: 6px;
  height: 32px; padding: 0 12px;
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: 12.5px; font-weight: 500;
  transition: background var(--t), border-color var(--t), color var(--t),
              transform var(--t), box-shadow var(--t), filter var(--t);
}
.btn:hover {
  transform: translateY(-1px);
  border-color: var(--primary);
  color: var(--primary);
  box-shadow: 0 4px 10px -4px rgba(99, 91, 255, 0.18);
}
.btn:active { transform: translateY(0); }
.btn:focus-visible {
  outline: none;
  border-color: var(--border-focus);
  box-shadow: 0 0 0 4px rgba(99, 91, 255, 0.12);
}

/* Primary — gradient + white text. Hover LIFTS and BRIGHTENS, never goes pale.
 * Canonical Treasury pattern: gradient background is preserved on every state,
 * box-shadow stacks for depth, brightness(1.04) for the glow. */
.btn-primary {
  background: var(--grad);
  border: 1px solid transparent;
  color: #ffffff;
  box-shadow:
    0 1px 1px rgba(0, 0, 0, 0.04),
    inset 0 0 0 1px rgba(255, 255, 255, 0.18),
    0 2px 6px -2px rgba(99, 91, 255, 0.55);
}
.btn-primary:hover {
  background: var(--grad);
  transform: translateY(-1px);
  filter: brightness(1.04);
  color: #ffffff;
  border-color: transparent;
  box-shadow:
    0 8px 18px -6px rgba(99, 91, 255, 0.55),
    inset 0 0 0 1px rgba(255, 255, 255, 0.22);
}
.btn-primary:active {
  transform: translateY(0);
  filter: brightness(1.0);
}

.btn-ghost {
  background: transparent;
  border-color: transparent;
  color: var(--text-soft);
}
.btn-ghost:hover {
  background: var(--hover);
  color: var(--text);
  border-color: transparent;
}

.btn-lg { height: 36px; padding: 0 14px; font-size: 13px; }
.btn-xl { height: 42px; padding: 0 18px; font-size: 14px; border-radius: var(--radius-lg); }
.btn-hero {
  height: 52px; padding: 0 24px;
  font-size: 15px; font-weight: 600;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
.btn-block { width: 100%; justify-content: center; }

/* .btn-danger uses MUTED grey only — never red. Same shape as .btn, slightly
   recessed colors, hover lifts to the regular text color. */
.btn-danger {
  color: var(--text-muted);
  border-color: var(--border-strong);
}
.btn-danger:hover {
  background: var(--bg-tint);
  color: var(--text);
  border-color: var(--text-faint);
}

.btn[disabled],
.btn.is-disabled {
  opacity: 0.5;
  pointer-events: none;
}


/* ------------------------------------------------------------
 * 5 · Hold-to-confirm button (HARD RULE 9)
 *   Every irreversible commit (pay, verify, book, accept) is a hold,
 *   not a click. Press and hold 1500ms: a conic-gradient arc sweeps
 *   the ring, then a white wash floods the surface, then JS dispatches
 *   the global `apex:hold-confirmed` event (wired in sdk-bridge.js).
 *
 *   Markup contract:
 *     <button class="hold-btn" data-hold>
 *       <span class="hold-arc"></span>
 *       <span class="hold-label">Hold to confirm</span>
 *     </button>
 *   JS adds .holding on pointerdown (starts both animations) and
 *   .confirmed on completion. Releasing early removes .holding (arc
 *   resets via the transition, no event fired).
 * ------------------------------------------------------------ */
.hold-btn {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  gap: 8px;
  height: 52px; padding: 0 28px;
  min-width: 240px;
  border-radius: var(--radius-lg);
  background: var(--grad);
  border: 1px solid transparent;
  color: #ffffff;
  font-family: var(--font-sans);
  font-size: 15px; font-weight: 600;
  letter-spacing: -0.01em;
  overflow: hidden;
  isolation: isolate;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  touch-action: none;
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.18),
    0 8px 20px -8px rgba(99, 91, 255, 0.55);
  transition: transform var(--t), box-shadow var(--t), filter var(--t);
}
.hold-btn:hover { filter: brightness(1.03); }
.hold-btn:active { transform: translateY(1px); }
.hold-btn:focus-visible {
  outline: none;
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.22),
    0 0 0 4px rgba(99, 91, 255, 0.22);
}
.hold-btn .hold-label {
  position: relative; z-index: 2;
  display: inline-flex; align-items: center; gap: 8px;
}
.hold-btn .hold-label .ico { width: 16px; height: 16px; }

/* The conic-gradient progress arc. A masked ring just inside the border.
 * --hold-pct (0->1) is animated 0 to 1 over 1500ms while .holding is set;
 * the conic stop is driven off it so the arc sweeps clockwise. */
.hold-btn .hold-arc {
  position: absolute; inset: 0;
  z-index: 1;
  border-radius: inherit;
  padding: 2px;
  background: conic-gradient(
    from -90deg,
    rgba(255, 255, 255, 0.92) calc(var(--hold-pct, 0) * 360deg),
    rgba(255, 255, 255, 0.12) 0
  );
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
          mask-composite: exclude;
  opacity: 0;
  transition: opacity 120ms ease;
  pointer-events: none;
}
.hold-btn.holding .hold-arc {
  opacity: 1;
  animation: holdArc var(--dur-hold) linear forwards;
}
/* White wash that floods the surface from the left once the hold lands.
 * Lives in ::after so it sits above the gradient but below the label. */
.hold-btn::after {
  content: '';
  position: absolute; inset: 0;
  z-index: 1;
  background: linear-gradient(90deg,
    rgba(255, 255, 255, 0.95),
    rgba(255, 255, 255, 0.78));
  transform: translateX(-101%);
  opacity: 0;
  pointer-events: none;
}
.hold-btn.confirmed::after {
  opacity: 1;
  animation: washSweep var(--dur-celebration) cubic-bezier(.2,.6,.3,1) forwards;
}
.hold-btn.confirmed .hold-label { color: var(--status-done); }

/* drives --hold-pct 0 -> 1 over the hold duration */
@keyframes holdArc {
  from { --hold-pct: 0; }
  to   { --hold-pct: 1; }
}
/* fallback for engines that cannot animate the registered custom property:
 * still flag the ring as active so the visual reads as a hold-in-progress */
@supports not (background: conic-gradient(from -90deg, #000 var(--x, 0), #000 0)) {
  .hold-btn.holding .hold-arc { animation: none; opacity: 1; }
}
@keyframes washSweep {
  from { transform: translateX(-101%); }
  to   { transform: translateX(0); }
}
/* registered property so --hold-pct can be smoothly animated by holdArc */
@property --hold-pct {
  syntax: '<number>';
  inherits: false;
  initial-value: 0;
}


/* ------------------------------------------------------------
 * 6 · Chips + status chips
 * ------------------------------------------------------------ */
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  height: 22px; padding: 0 8px;
  border-radius: 99px;
  background: var(--bg-tint);
  border: 1px solid var(--border);
  font-size: 11px; color: var(--text-soft);
  font-weight: 500;
  white-space: nowrap;
}
.chip .dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.7;
}
.chip.purple-soft {
  background: var(--primary-soft);
  color: var(--primary);
  border-color: var(--status-done-bd);
}
.chip.muted {
  background: var(--bg-tint);
  color: var(--text-muted);
}
.chip.live {
  background: var(--primary-soft);
  color: var(--primary);
  border-color: var(--status-done-bd);
}
.chip.live .pulse {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--pulse-live);
  animation: livePulse 1.6s infinite ease-in-out;
}

/* Status chips — the four canonical lifecycle states. Indigo done, purple
 * working, gunmetal stuck, grey not-started. NEVER red. NEVER green. */
.status-chip {
  display: inline-flex; align-items: center; gap: 6px;
  height: 22px; padding: 0 9px;
  border-radius: 99px;
  font-size: 11px; font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
  border: 1px solid transparent;
}
.status-chip .dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: currentColor;
}
.status-chip.done {
  background: var(--status-done-bg);
  color: var(--status-done-fg);
  border-color: var(--status-done-bd);
}
.status-chip.working {
  background: var(--status-working-bg);
  color: var(--status-working-fg);
  border-color: var(--status-working-bd);
}
.status-chip.working .dot { animation: dotPulse 1.6s infinite ease-in-out; }
.status-chip.stuck {
  background: var(--status-stuck-bg);
  color: var(--status-stuck-fg);
  border-color: var(--status-stuck-bd);
}
.status-chip.notstarted {
  background: var(--status-notstarted-bg);
  color: var(--status-notstarted-fg);
  border-color: var(--status-notstarted-bd);
}


/* ------------------------------------------------------------
 * 7 · Steps-mini pills
 *   Compact sub-step indicator inside a wizard card (e.g. the three
 *   sub-steps of identity verify). Smaller than the journey strip,
 *   lives in the card header. .done / .current / .upcoming.
 * ------------------------------------------------------------ */
.steps-mini {
  display: inline-flex; align-items: center; gap: 6px;
}
.steps-mini .step-pill {
  display: inline-flex; align-items: center; gap: 5px;
  height: 22px; padding: 0 9px;
  border-radius: 99px;
  background: var(--bg-tint);
  border: 1px solid var(--border);
  font-size: 11px; font-weight: 500;
  color: var(--text-muted);
  white-space: nowrap;
  transition: background var(--t), color var(--t), border-color var(--t);
}
.steps-mini .step-pill .step-num {
  width: 15px; height: 15px;
  border-radius: 50%;
  display: grid; place-items: center;
  font-size: 9.5px; font-weight: 600;
  font-variant-numeric: tabular-nums;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  color: var(--text-muted);
}
.steps-mini .step-pill .ico { width: 12px; height: 12px; }
.steps-mini .step-pill.done {
  background: var(--status-done-bg);
  color: var(--status-done-fg);
  border-color: var(--status-done-bd);
}
.steps-mini .step-pill.done .step-num {
  background: var(--status-done);
  border-color: var(--status-done);
  color: #ffffff;
}
.steps-mini .step-pill.current {
  background: var(--primary-soft);
  color: var(--primary);
  border-color: var(--status-working-bd);
}
.steps-mini .step-pill.current .step-num {
  background: var(--grad);
  border-color: transparent;
  color: #ffffff;
}
.steps-mini .step-sep {
  width: 14px; height: 1px;
  background: var(--border-strong);
  flex-shrink: 0;
}


/* ------------------------------------------------------------
 * 8 · Sparkline
 *   (referenced gradients: #sparkGrad, #sparkAreaGrad — namespaced and
 *    defined in shared/components/svg-defs.js so flows never collide)
 * ------------------------------------------------------------ */
.spark {
  width: 100%; height: 28px;
  display: block;
}
.spark-area {
  fill: url(#sparkAreaGrad);
  opacity: 0.45;
}
.spark-line {
  fill: none;
  stroke: url(#sparkGrad);
  stroke-width: 1.6;
}
.spark-dot { fill: var(--primary); }
.spark-dot-pulse {
  animation: dotPulse 1.6s infinite ease-in-out;
  transform-origin: center;
}


/* ------------------------------------------------------------
 * 9 · Cockpit KPI tile
 *   The kinetic stat block. Live hero number + sparkline under it.
 *   Never a static report cell. Down deltas read quiet, never red.
 * ------------------------------------------------------------ */
.cockpit-kpi {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 14px 16px;
  display: flex; flex-direction: column; gap: 8px;
  transition: border-color var(--t), box-shadow var(--t);
}
.cockpit-kpi:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-xs);
}
.cockpit-kpi-head {
  display: flex; align-items: center; gap: 6px;
  font-size: 11px; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: 0.06em;
  font-weight: 500;
}
.cockpit-kpi-head .ico {
  width: 14px; height: 14px;
  opacity: 0.7;
}
.cockpit-kpi-row {
  display: flex; align-items: baseline;
  justify-content: space-between;
}
.cockpit-kpi-num {
  font-family: var(--font-sans);
  font-size: 30px; font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.cockpit-kpi-num.purple {
  background: var(--grad);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}
.cockpit-kpi-delta {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 11px; font-weight: 500;
  color: var(--text-muted);
}
.cockpit-kpi-delta.up   { color: var(--primary); }
/* .down uses faint text — NEVER red. Down deltas read as quiet, not alarming. */
.cockpit-kpi-delta.down { color: var(--text-faint); }
.cockpit-kpi .spark { margin-top: 2px; }


/* ------------------------------------------------------------
 * 10 · War room hero
 *   Manager / CEO cockpit hero strip. 5-col grid:
 *   target | divider | actual | divider | gap-close action.
 * ------------------------------------------------------------ */
.war-room {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 20px 24px;
  display: grid;
  grid-template-columns: 1fr auto 1fr auto 1fr;
  gap: 24px;
  align-items: stretch;
  box-shadow: var(--shadow-sm);
}
.war-col {
  display: flex; flex-direction: column; gap: 8px;
  min-width: 0;
}
.war-divider {
  width: 1px;
  background: var(--border);
  align-self: stretch;
}
.war-eyebrow {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 10.5px; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: 0.08em;
  font-weight: 500;
}
.war-eyebrow.live::before {
  content: '';
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--pulse-live);
  animation: livePulse 1.6s infinite;
}
.war-num {
  font-family: var(--font-sans);
  font-size: 56px; font-weight: 600;
  letter-spacing: -0.025em; line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
.war-num.purple {
  background: var(--grad);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}
.war-num-small {
  font-size: 14px; color: var(--text-muted);
  font-weight: 500;
  margin-left: 4px;
}
.war-meta-line {
  font-size: 12px;
  color: var(--text-muted);
}
.war-bar {
  height: 6px;
  background: var(--bg-tint);
  border-radius: 99px;
  overflow: hidden;
  border: 1px solid var(--border);
}
.war-bar-fill {
  height: 100%;
  background: var(--grad);
  transition: width 240ms ease-out;
}
.war-countdown {
  font-family: var(--font-mono);
  font-size: 40px; font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.war-pace {
  background: var(--bg-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 12px;
  font-size: 12px; color: var(--text-soft);
  line-height: 1.5;
}
.war-pace b.accent {
  color: var(--primary);
  font-weight: 600;
}


/* ------------------------------------------------------------
 * 11 · View tabs + body
 *   Pill-segmented tab control; .view-body is the surface below
 *   the tabs (height is set inline by the caller — usually 280/320/380).
 * ------------------------------------------------------------ */
.view-tabs {
  display: flex; gap: 2px;
  padding: 4px;
  background: var(--bg-tint);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  width: fit-content;
}
.view-tab {
  display: inline-flex; align-items: center; gap: 6px;
  height: 28px; padding: 0 10px;
  font-size: 12px; color: var(--text-soft);
  font-weight: 500;
  border-radius: 6px;
  transition: background var(--t), color var(--t);
  cursor: pointer;
}
.view-tab:hover { color: var(--text); }
.view-tab.active {
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-xs);
}
.view-body {
  margin-top: 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 16px;
  overflow: hidden;
}


/* ------------------------------------------------------------
 * 12 · Wizard card
 *   The one-action-at-a-time client surface (payment, identity, book).
 *   Centered card, header with eyebrow + title + optional steps-mini,
 *   a body, and a footer that always carries exactly one primary
 *   CTA (a .btn-primary, .btn-xl, or a .hold-btn). No dead-ends.
 * ------------------------------------------------------------ */
.wizard-card {
  width: 520px;
  max-width: calc(100vw - 48px);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  display: flex; flex-direction: column;
}
.wizard-card.wide { width: 640px; }
.wizard-head {
  padding: 24px 28px 16px;
  display: flex; flex-direction: column; gap: 8px;
  border-bottom: 1px solid var(--border);
}
.wizard-head-top {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px;
}
.wizard-eyebrow {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11px; color: var(--primary);
  text-transform: uppercase; letter-spacing: 0.08em;
  font-weight: 600;
}
.wizard-title {
  margin: 0;
  font-size: 22px; font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--text);
  line-height: 1.15;
}
.wizard-sub {
  margin: 0;
  font-size: 13.5px; color: var(--text-muted);
  line-height: 1.55;
  max-width: 46ch;
}
.wizard-body {
  padding: 22px 28px;
  display: flex; flex-direction: column; gap: 16px;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}
.wizard-foot {
  padding: 16px 28px;
  border-top: 1px solid var(--border);
  background: var(--bg-soft);
  display: flex; align-items: center; gap: 10px;
}
.wizard-foot.end { justify-content: flex-end; }
.wizard-foot.between { justify-content: space-between; }
.wizard-foot .spacer { flex: 1; }
/* a one-CTA footer stretches the single primary action full width */
.wizard-foot.solo > .btn-primary,
.wizard-foot.solo > .hold-btn { flex: 1; justify-content: center; }


/* ------------------------------------------------------------
 * 13 · Modal
 * ------------------------------------------------------------ */
.modal-bg {
  position: fixed; inset: 0;
  background: var(--modal-scrim);
  backdrop-filter: blur(4px);
  display: none;
  align-items: center; justify-content: center;
  z-index: 100;
  opacity: 0;
  transition: opacity 180ms ease;
}
.modal-bg.open {
  display: flex;
  opacity: 1;
}
.modal {
  width: 460px;
  max-width: calc(100vw - 48px);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  transform: translateY(8px);
  transition: transform 180ms ease;
}
.modal-bg.open .modal { transform: translateY(0); }
.modal-head { padding: 20px 22px 12px; }
.modal-head h3 {
  margin: 0 0 6px;
  font-size: 16px; font-weight: 600;
  letter-spacing: -0.01em;
}
.modal-head p {
  margin: 0;
  font-size: 13px; color: var(--text-muted);
  line-height: 1.5;
}
.modal-body { padding: 6px 22px 16px; }
.modal-input {
  width: 100%;
  font-family: var(--font-mono);
  letter-spacing: 0.04em;
}
.modal-foot {
  display: flex; justify-content: flex-end; gap: 8px;
  padding: 14px 22px;
  background: var(--bg-soft);
  border-top: 1px solid var(--border);
}


/* ------------------------------------------------------------
 * 14 · Drawer + drawer-scrim
 *   Right-side drawer for closer-pushed content (pricing, doc, payment
 *   payloads arriving over the push channel). The scrim uses the
 *   dedicated --drawer-scrim token so it sits lighter than the modal.
 * ------------------------------------------------------------ */
.drawer-scrim,
.drawer-bg {
  position: fixed; inset: 0;
  background: var(--drawer-scrim);
  backdrop-filter: blur(2px);
  display: none;
  z-index: 90;
  opacity: 0;
  transition: opacity 180ms ease;
}
.drawer-scrim.open,
.drawer-bg.open {
  display: block;
  opacity: 1;
}
.drawer {
  position: fixed; top: 0; right: 0; bottom: 0;
  width: 560px;
  max-width: 100vw;
  background: var(--surface);
  border-left: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column;
  transform: translateX(24px);
  transition: transform 240ms ease;
}
.drawer-scrim.open .drawer,
.drawer-bg.open .drawer { transform: translateX(0); }
.drawer-head {
  padding: 18px 22px;
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; justify-content: space-between;
}
.drawer-head h3 {
  margin: 0;
  font-size: 15px; font-weight: 600;
}
.drawer-body {
  flex: 1;
  overflow-y: auto;
  padding: 20px 22px;
}
.drawer-foot {
  padding: 14px 22px;
  border-top: 1px solid var(--border);
  background: var(--bg-soft);
  display: flex; justify-content: flex-end; gap: 8px;
}


/* ------------------------------------------------------------
 * 15 · Toast (+ push toast)
 *   Standard toasts stack bottom-right. The push toast (pp-toast) is
 *   the inbound-content notice that fires when the closer pushes a
 *   pricing / doc / payment payload (showPushPayload in sdk-bridge.js).
 *   Success uses primary purple. Warning uses muted text. NEVER red.
 * ------------------------------------------------------------ */
.apex-toasts {
  position: fixed;
  bottom: 24px; right: 24px;
  display: flex; flex-direction: column; gap: 8px;
  z-index: 110;
  pointer-events: none;
}
.toast {
  pointer-events: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 14px;
  font-size: 13px; color: var(--text);
  box-shadow: var(--shadow-md);
  display: flex; align-items: center; gap: 8px;
  min-width: 240px;
  max-width: 360px;
  transform: translateY(8px);
  opacity: 0;
  transition: transform 200ms ease, opacity 200ms ease;
}
.toast.show {
  transform: translateY(0);
  opacity: 1;
}
.toast .toast-ico {
  width: 16px; height: 16px;
  opacity: 0.7;
}
.toast.success .toast-ico {
  color: var(--primary);
  opacity: 1;
}
.toast.warning .toast-ico {
  color: var(--text-muted);
}

/* pp-toast — the closer-push notice. Slightly larger, gradient accent
 * rail on the left, has a primary action ("View"). */
.pp-toast {
  pointer-events: auto;
  position: relative;
  background: var(--surface);
  border: 1px solid var(--status-working-bd);
  border-radius: var(--radius-lg);
  padding: 12px 16px 12px 18px;
  box-shadow: var(--shadow-md);
  display: flex; align-items: center; gap: 12px;
  min-width: 300px; max-width: 380px;
  overflow: hidden;
  transform: translateY(10px);
  opacity: 0;
  transition: transform 220ms ease, opacity 220ms ease;
}
.pp-toast::before {
  content: '';
  position: absolute; left: 0; top: 0; bottom: 0;
  width: 3px;
  background: var(--grad);
}
.pp-toast.show { transform: translateY(0); opacity: 1; }
.pp-toast .pp-ico {
  width: 32px; height: 32px;
  border-radius: 8px;
  background: var(--primary-soft);
  color: var(--primary);
  display: grid; place-items: center;
  flex-shrink: 0;
}
.pp-toast .pp-ico .ico { width: 17px; height: 17px; }
.pp-toast .pp-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.pp-toast .pp-title { font-size: 12.5px; font-weight: 600; color: var(--text); }
.pp-toast .pp-sub { font-size: 11.5px; color: var(--text-muted); }
.pp-toast .pp-action { margin-left: auto; flex-shrink: 0; }


/* ------------------------------------------------------------
 * 16 · Tables
 *   grid-template-columns is set inline per page (each table is bespoke).
 *   .me / .flagged / .top all share the same purple-tint highlight.
 * ------------------------------------------------------------ */
.tbl {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.tbl-head,
.tbl-row {
  display: grid;
  align-items: center;
  padding: 10px 14px;
  font-size: 12.5px;
}
.tbl-head {
  background: var(--bg-soft);
  border-bottom: 1px solid var(--border);
  color: var(--text-muted);
  text-transform: uppercase; letter-spacing: 0.06em;
  font-size: 11px; font-weight: 500;
}
.tbl-row {
  border-bottom: 1px solid var(--border);
  transition: background var(--t);
  position: relative;
}
.tbl-row:last-child { border-bottom: 0; }
.tbl-row:hover { background: var(--hover); }
.tbl-row.me,
.tbl-row.flagged,
.tbl-row.top {
  background: linear-gradient(90deg, var(--primary-soft) 0%, transparent 40%);
}
.tbl-row.me::before,
.tbl-row.flagged::before,
.tbl-row.top::before {
  content: '';
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: var(--grad);
}
.tbl-cell.num { font-variant-numeric: tabular-nums; }


/* ------------------------------------------------------------
 * 17 · Bubbles (iMessage style — NO Slack-style channel symbols)
 *   Three row orientations: .me (right), .them (left), .apex (assistant).
 * ------------------------------------------------------------ */
.bubble-row {
  display: flex; align-items: flex-end; gap: 8px;
  margin-bottom: 14px;
}
.bubble-row.me { flex-direction: row-reverse; }
.bubble-body {
  display: flex; flex-direction: column;
  min-width: 0; max-width: 460px;
}
.bubble-row.me .bubble-body { align-items: flex-end; }
.bubble-av {
  width: 28px; height: 28px;
  border-radius: 50%;
  background: var(--bg-tint);
  color: var(--text);
  display: grid; place-items: center;
  font-size: 11px; font-weight: 600;
  border: 1px solid var(--border);
  flex-shrink: 0;
}
.bubble-row.apex .bubble-av {
  background: var(--grad);
  color: var(--surface);
  border: 0;
}
.bubble-sender {
  font-size: 11px;
  color: var(--text-muted);
  margin: 0 4px 4px;
}
.bubble {
  max-width: 420px;
  padding: 9px 13px;
  border-radius: 18px;
  background: var(--bg-tint);
  color: var(--text);
  font-size: 13.5px;
  line-height: 1.45;
  word-wrap: break-word;
}
.bubble-row.me .bubble {
  background: var(--grad);
  color: var(--surface);
  border-bottom-right-radius: 6px;
}
.bubble-row.them .bubble { border-bottom-left-radius: 6px; }
.bubble-row.apex .bubble {
  background: var(--primary-soft);
  color: var(--text);
  border: 1px solid var(--status-done-bd);
  border-bottom-left-radius: 6px;
}
.bubble-reactions {
  display: flex; gap: 4px;
  margin: 4px 4px 0;
}
.bubble-react {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 99px;
  padding: 1px 6px;
  font-size: 11px;
  color: var(--text-soft);
}
.bubble-react.mine {
  border-color: var(--status-done-bd);
  background: var(--primary-soft);
  color: var(--primary);
}
.bubble-time {
  font-size: 10.5px;
  color: var(--text-faint);
  margin: 4px 4px 0;
  text-align: right;
}
.bubble-attach {
  background: var(--bg-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 8px 10px;
  margin-top: 4px;
  font-size: 12px;
  color: var(--text-soft);
}


/* ------------------------------------------------------------
 * 18 · Apex orb (data-state driven)
 *   The canonical voice-AI hero. The REAL Apex gradient sphere (orb
 *   gradient stops from tokens) with a ring that pulses outward and
 *   mic bars in the core. The component in apex-orb.js sets
 *   data-state on the root: idle | listening | thinking | speaking |
 *   executing. Each state retunes the ring pace and bar motion.
 *   This is NEVER a CSS letter "A" — always the app-icon sphere.
 * ------------------------------------------------------------ */
.apex-orb {
  position: relative;
  width: 220px; height: 220px;
  border-radius: 50%;
  background:
    radial-gradient(circle at 32% 28%, var(--orb-1), transparent 55%),
    radial-gradient(circle at 70% 78%, var(--orb-5), transparent 60%),
    linear-gradient(135deg, var(--orb-2) 0%, var(--orb-3) 45%, var(--orb-4) 100%);
  display: grid; place-items: center;
  box-shadow: 0 20px 50px -10px var(--orb-glow);
}
.apex-orb-ring {
  position: absolute; inset: -12px;
  border-radius: 50%;
  border: 2px solid var(--primary);
  opacity: 0.6;
  animation: orbRing var(--dur-orb-pulse) infinite ease-out;
}
.apex-orb-core {
  width: 96px; height: 96px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.10);
  border: 1px solid rgba(255, 255, 255, 0.20);
  display: grid; place-items: center;
  color: var(--surface);
}
.apex-orb-bars {
  display: flex; align-items: center; gap: 3px;
  height: 40px;
}
.apex-orb-bar {
  display: inline-block;
  width: 3px;
  background: #ffffff;
  border-radius: 99px;
  height: 16px;
  animation: orbBar 0.7s infinite ease-in-out;
}
.apex-orb-bar:nth-child(2) { animation-delay: 0.10s; }
.apex-orb-bar:nth-child(3) { animation-delay: 0.20s; }
.apex-orb-bar:nth-child(4) { animation-delay: 0.30s; }
.apex-orb-bar:nth-child(5) { animation-delay: 0.40s; }

/* idle — slow breathing ring, bars at rest (no motion) */
.apex-orb[data-state="idle"] .apex-orb-ring { animation-duration: var(--dur-orb-pulse); opacity: 0.45; }
.apex-orb[data-state="idle"] .apex-orb-bar { animation: none; height: 14px; opacity: 0.85; }
/* listening — faster ring (rec-pulse cadence), bars sway gently */
.apex-orb[data-state="listening"] .apex-orb-ring {
  border-color: var(--pulse-live);
  animation: rec-pulse var(--dur-rec-pulse) infinite ease-out;
}
.apex-orb[data-state="listening"] .apex-orb-bar { animation-duration: 0.9s; }
/* thinking — ring dims and rotates-in feel, bars shimmer slow */
.apex-orb[data-state="thinking"] .apex-orb-ring { opacity: 0.35; animation-duration: 1.8s; }
.apex-orb[data-state="thinking"] .apex-orb-bar { animation-duration: 1.3s; }
/* speaking — energetic bars, tight bright ring */
.apex-orb[data-state="speaking"] .apex-orb-bar { animation-duration: 0.5s; }
.apex-orb[data-state="speaking"] .apex-orb-ring { opacity: 0.7; }
/* executing — steady indigo ring, bars locked tall (working) */
.apex-orb[data-state="executing"] .apex-orb-ring {
  border-color: var(--status-done);
  animation-duration: 1.2s;
}
.apex-orb[data-state="executing"] .apex-orb-bar { animation: none; height: 30px; }

/* small inline orb for topbar / chips (44px). Same sphere, no ring/bars. */
.apex-orb-sm {
  width: 44px; height: 44px;
  border-radius: 12px;
  background:
    radial-gradient(circle at 32% 28%, var(--orb-1), transparent 55%),
    linear-gradient(135deg, var(--orb-2) 0%, var(--orb-3) 50%, var(--orb-4) 100%);
  box-shadow: 0 6px 16px -6px var(--orb-glow);
  flex-shrink: 0;
}

@keyframes orbRing {
  0%   { transform: scale(1);    opacity: 0.6; }
  100% { transform: scale(1.25); opacity: 0;   }
}
@keyframes orbBar {
  0%, 100% { height: 12px; }
  50%      { height: 36px; }
}


/* ------------------------------------------------------------
 * 19 · Slide stage
 *   The pitch / pushed-deck surface. 16:9 canvas with a faint purple
 *   radial wash + ruled grid underlay.
 * ------------------------------------------------------------ */
.slide-stage {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  overflow: hidden;
  display: flex; flex-direction: column;
}
.slide-stage-head {
  padding: 12px 18px;
  display: flex; align-items: center; gap: 12px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-soft);
  font-size: 12px; color: var(--text-soft);
}
.slide-counter {
  margin-left: auto;
  font-family: var(--font-mono);
  color: var(--text-muted);
}
.slide-canvas {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--bg);
  overflow: hidden;
}
.slide-canvas-bg {
  position: absolute; inset: 0;
  background: radial-gradient(circle at 30% 20%, rgba(99, 91, 255, 0.10), transparent 60%);
}
.slide-canvas-grid {
  position: absolute; inset: 0;
  background-image:
    linear-gradient(var(--border) 1px, transparent 1px),
    linear-gradient(90deg, var(--border) 1px, transparent 1px);
  background-size: 64px 64px;
  opacity: 0.25;
}
.slide-canvas-inner {
  position: relative; z-index: 2;
  padding: 56px 64px;
  height: 100%;
  display: flex; flex-direction: column; gap: 12px;
  justify-content: center;
}
.slide-eyebrow {
  font-size: 12px;
  color: var(--primary);
  text-transform: uppercase; letter-spacing: 0.08em;
  font-weight: 500;
}
.slide-headline {
  font-size: 36px; font-weight: 600;
  letter-spacing: -0.02em; line-height: 1.1;
  margin: 0;
}
.slide-sub {
  font-size: 16px;
  color: var(--text-soft);
  line-height: 1.5;
  max-width: 640px;
}
.slide-stage-foot {
  padding: 10px 18px;
  display: flex; align-items: center; gap: 8px;
  border-top: 1px solid var(--border);
  background: var(--bg-soft);
}
.slide-nav-btn {
  width: 32px; height: 32px;
  display: grid; place-items: center;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-soft);
}
.slide-nav-btn:hover {
  background: var(--hover);
  color: var(--text);
}


/* ------------------------------------------------------------
 * 20 · Charts
 *   Area chart, hourly bars, heatmap, stacked bars, contrib list,
 *   audio waveform. Referenced SVG gradients live in svg-defs.js.
 * ------------------------------------------------------------ */

/* area chart */
.area-chart {
  width: 100%;
  height: 240px;
}
.area-chart .area-fill {
  fill: url(#sparkAreaGrad);
  opacity: 0.35;
}
.area-chart .area-line {
  fill: none;
  stroke: url(#sparkGrad);
  stroke-width: 1.8;
}
.area-chart .grid-line {
  stroke: var(--border);
  stroke-width: 0.5;
}
.area-chart .axis-label {
  font-size: 10px;
  fill: var(--text-faint);
}

/* hourly bars */
.hourly-bars {
  display: grid;
  grid-auto-flow: column;
  gap: 4px;
  align-items: end;
  height: 200px;
  padding: 8px 0;
}
.hourly-bar {
  background: var(--grad);
  border-radius: 4px 4px 0 0;
  min-height: 4px;
  transition: opacity var(--t);
}
.hourly-bar:hover { opacity: 0.8; }

/* heatmap */
.heatmap {
  display: grid;
  gap: 3px;
}
.heatmap-cell {
  aspect-ratio: 1;
  border-radius: 3px;
  background: var(--bg-tint);
  position: relative;
  transition: transform var(--t);
}
.heatmap-cell:hover { transform: scale(1.1); }
.heatmap-cell.t1 { background: rgba(99, 91, 255, 0.18); }
.heatmap-cell.t2 { background: rgba(99, 91, 255, 0.35); }
.heatmap-cell.t3 { background: rgba(99, 91, 255, 0.55); }
.heatmap-cell.t4 { background: rgba(99, 91, 255, 0.78); }
.heatmap-cell.t5 { background: var(--primary); }
/* blocked / off — diagonal purple stripes (NEVER red) */
.heatmap-cell.blocked {
  background-image: repeating-linear-gradient(
    45deg,
    var(--bg-tint) 0 3px,
    rgba(99, 91, 255, 0.20) 3px 6px
  );
}

/* stacked bars (status segments) */
.stacked-bars {
  display: flex; flex-direction: column;
  gap: 8px;
}
.stacked-bar-row {
  display: grid;
  grid-template-columns: 100px 1fr 60px;
  gap: 10px;
  align-items: center;
  font-size: 12px;
}
.stacked-bar-row .bar {
  display: flex;
  height: 18px;
  border-radius: 4px;
  overflow: hidden;
  border: 1px solid var(--border);
}
.stacked-bar-row .seg.done       { background: var(--status-done); }
.stacked-bar-row .seg.working    { background: var(--status-working); }
.stacked-bar-row .seg.stuck      { background: var(--status-stuck); }
.stacked-bar-row .seg.notstarted { background: var(--bg-tint); }

/* contributor list */
.contrib-list {
  display: flex; flex-direction: column;
}
.contrib-row {
  display: grid;
  grid-template-columns: 24px 1fr 80px 40px;
  gap: 10px;
  align-items: center;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
  font-size: 12.5px;
}
.contrib-row:last-child { border-bottom: 0; }
.contrib-row .bar {
  height: 6px;
  background: var(--bg-tint);
  border-radius: 99px;
  overflow: hidden;
}
.contrib-row .bar-fill {
  height: 100%;
  background: var(--grad);
}

/* audio waveform (live recording indicator — purple bars, never red) */
.audio-waveform {
  display: flex; align-items: center; gap: 2px;
  height: 32px;
}
.wf-bar {
  width: 2.5px;
  background: var(--pulse-live);
  border-radius: 99px;
  animation: wfBarPulse 0.9s infinite ease-in-out;
}
@keyframes wfBarPulse {
  0%, 100% { transform: scaleY(0.4); }
  50%      { transform: scaleY(1);   }
}


/* ------------------------------------------------------------
 * 21 · Form fields
 * ------------------------------------------------------------ */
.field {
  display: flex; flex-direction: column;
  gap: 6px;
}
.field-label {
  font-size: 12px; font-weight: 500;
  color: var(--text-soft);
  display: flex; align-items: center; gap: 6px;
}
.field-label .hint {
  font-size: 11px;
  color: var(--text-faint);
  font-weight: 400;
}
.field input,
.field select,
.field textarea {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 9px 12px;
  font-size: 13px;
  color: var(--text);
  font-family: var(--font-sans);
  transition: border-color var(--t), box-shadow var(--t);
}
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--border-focus);
  box-shadow: 0 0 0 4px rgba(99, 91, 255, 0.12);
}
.field input::placeholder,
.field textarea::placeholder { color: var(--text-faint); }
.field.span-2 { grid-column: span 2; }
.field-meta {
  font-size: 11px;
  color: var(--text-muted);
}
.hint {
  font-size: 11px;
  color: var(--text-faint);
  font-weight: 400;
}


/* ------------------------------------------------------------
 * 22 · Toggle / segmented controls
 * ------------------------------------------------------------ */
.toggle-pair {
  display: inline-flex; gap: 2px;
  padding: 3px;
  background: var(--bg-tint);
  border: 1px solid var(--border);
  border-radius: 99px;
}
.toggle-pair .seg-opt {
  height: 26px; padding: 0 14px;
  font-size: 12px;
  border-radius: 99px;
  display: grid; place-items: center;
  color: var(--text-soft);
  cursor: pointer;
  transition: background var(--t), color var(--t);
}
.toggle-pair .seg-opt.active {
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-xs);
}

.seg-group {
  display: inline-flex;
  padding: 3px;
  background: var(--bg-tint);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  gap: 2px;
}
.seg-3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
}
.seg-row {
  display: grid;
  grid-auto-flow: column;
  gap: 2px;
}
.seg-opt {
  height: 28px; padding: 0 12px;
  font-size: 12px;
  border-radius: 6px;
  display: grid; place-items: center;
  color: var(--text-soft);
  cursor: pointer;
  transition: background var(--t), color var(--t);
}
.seg-opt:hover { color: var(--text); }
.seg-opt.active {
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-xs);
}


/* ------------------------------------------------------------
 * 23 · Stepper
 * ------------------------------------------------------------ */
.stepper {
  display: inline-flex; align-items: center;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.stepper-btn {
  width: 32px; height: 32px;
  display: grid; place-items: center;
  color: var(--text-soft);
  transition: background var(--t);
}
.stepper-btn:hover {
  background: var(--hover);
  color: var(--text);
}
.stepper-value {
  padding: 0 14px;
  font-family: var(--font-mono);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  min-width: 56px;
  text-align: center;
  border-left: 1px solid var(--border);
  border-right: 1px solid var(--border);
  height: 32px;
  display: grid; place-items: center;
}


/* ------------------------------------------------------------
 * 24 · Done strip (section-complete confirmation)
 *   The quiet confirmation rail shown when a journey phase lands
 *   (payment cleared, identity verified, mission complete). Indigo
 *   done-check, a line of confirmation copy, and exactly one CTA that
 *   advances to the next phase. Never a dead-end.
 * ------------------------------------------------------------ */
.done-strip {
  display: flex; align-items: center; gap: 14px;
  padding: 14px 18px;
  background: var(--status-done-bg);
  border: 1px solid var(--status-done-bd);
  border-radius: var(--radius-lg);
}
.done-strip .done-check {
  width: 34px; height: 34px;
  border-radius: 50%;
  background: var(--status-done);
  color: #ffffff;
  display: grid; place-items: center;
  flex-shrink: 0;
  box-shadow: 0 4px 12px -4px var(--orb-glow);
}
.done-strip .done-check .ico { width: 18px; height: 18px; }
.done-strip .done-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.done-strip .done-title {
  font-size: 13.5px; font-weight: 600;
  color: var(--status-done-fg);
}
.done-strip .done-sub {
  font-size: 12px; color: var(--text-muted);
}
.done-strip .done-action { margin-left: auto; flex-shrink: 0; }


/* ------------------------------------------------------------
 * 25 · Diagonal-purple block-out (CANONICAL)
 *   The ONLY pattern used anywhere we'd otherwise reach for red:
 *   off-days, blocked time-slots, unavailable seats, ineligible
 *   options. Two utility classes with identical paint.
 * ------------------------------------------------------------ */
.block-out,
.blocked-slot {
  background-image: repeating-linear-gradient(
    45deg,
    var(--bg-tint) 0 6px,
    rgba(99, 91, 255, 0.22) 6px 12px
  );
  color: var(--text-muted);
}


/* ------------------------------------------------------------
 * 26 · System-state full-page layouts
 *   Empty / loading / not-found / network-error / permission-denied.
 *   Centered, generous whitespace, single primary action. The action
 *   ALWAYS routes somewhere real (never a dead-end / blank state).
 * ------------------------------------------------------------ */
.sys-state {
  min-height: calc(100vh - 56px);
  display: grid; place-items: center;
  padding: 60px 24px;
}
.sys-state-inner {
  max-width: 440px;
  text-align: center;
  display: flex; flex-direction: column; align-items: center;
  gap: 14px;
}
.sys-state-icon {
  width: 56px; height: 56px;
  color: var(--text-faint);
}
.sys-state-title {
  font-size: 20px; font-weight: 600;
  letter-spacing: -0.01em;
  margin: 0;
}
.sys-state-accent {
  font-size: 14px;
  color: var(--primary);
  font-weight: 500;
}
.sys-state-sub {
  font-size: 13px;
  color: var(--text-muted);
  line-height: 1.55;
}
.sys-state-actions {
  display: flex; gap: 8px;
  margin-top: 6px;
}


/* ------------------------------------------------------------
 * Reduced motion — honor the OS preference. Pulses, arcs, and
 * waveforms hold their resting frame so nothing strobes.
 * ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .apex-orb-ring,
  .apex-orb-bar,
  .progress-node.current .progress-dot,
  .chip.live .pulse,
  .war-eyebrow.live::before,
  .status-chip.working .dot,
  .spark-dot-pulse,
  .wf-bar,
  .hold-btn.holding .hold-arc,
  .hold-btn.confirmed::after {
    animation: none !important;
  }
}
