/* ============================================================
   LEVR Facilitator (iOS) — capture app
   Phone-primary, 393 × 852, portrait only. Built against
   facilitator-ios-DESIGN-PLAN.md. Tokens are COPIED from
   flywheel-v2/src/styles.css, not re-derived: the :root block
   below is byte-identical to the one that ships there.
   ============================================================ */

/* ---- Design tokens ---- */
:root {
  /* Brand blue (SGA #2D6FB7 — HSL 210/60/45, under 80% sat cap) */
  --blue-50:  #EEF4FB;
  --blue-100: #D9E7F5;
  --blue-200: #AECBEA;
  --blue-300: #7FAADD;
  --blue-400: #5189CB;
  --blue-500: #2D6FB7;
  --blue-600: #245C9B;
  --blue-700: #1C4A7E;
  --focus-ring: rgba(45,111,183,0.18);
  /* Monochrome focus halo — LEVR platform UI is B&W (change-brief-6) */
  --focus-ink: rgba(14,23,38,0.14);

  /* Neutrals — single cool/slate family */
  --ink-950: #0E1726;
  --ink-900: #152033;
  --ink-800: #1B2740;
  --ink-700: #334155;
  --ink-600: #475569;
  --ink-500: #64748B;
  --ink-400: #94A3B8;
  --ink-300: #CBD5E1;
  --ink-200: #E3E8EF;
  --ink-100: #EEF1F5;
  --ink-50:  #F6F8FA;
  --surface: #FFFFFF;
  --page-bg: #EEF1F4;

  /* Semantic */
  --success: #2E9A6B;
  --error:   #C2463C;
  --warn:    #B7791F;

  /* Radii — varied by context (change-brief-3 §1: doubled card, proportional inner) */
  --radius-card: 48px;
  --radius-image: 30px;
  --radius-button: 12px;
  --radius-pill: 9999px;
  --radius-badge: 12px;
  --radius-search: 20px;

  /* Shadows — soft, layered, blue-tinted (#102A48) */
  --shadow-card-rest:  0 1px 2px rgba(16,42,72,.04), 0 6px 20px rgba(16,42,72,.06);
  --shadow-card-hover: 0 2px 6px rgba(16,42,72,.06), 0 18px 44px rgba(16,42,72,.14);
  --shadow-pill:       0 1px 2px rgba(16,42,72,.10), 0 2px 8px rgba(16,42,72,.08);
  --shadow-search:     0 1px 2px rgba(16,42,72,.04), 0 4px 18px rgba(16,42,72,.07);
  --shadow-badge:      0 1px 3px rgba(16,42,72,.12);

  /* Alert accent — the one sanctioned non-monochrome chrome color, reserved
     strictly for the review-count notification badge (change-brief-9 rev). */
  --alert:     #E5484D;
  --alert-ink: #FFFFFF;

  /* Motion tokens */
  --dur-fast: 120ms;
  --dur-base: 220ms;
  --dur-slow: 320ms;
  --dur-video: 450ms;
  --dur-rise: 470ms;                 /* gentle hover rise + slow zoom (change-brief-2 #3) */
  --ease-smooth: cubic-bezier(.4,0,.2,1);
  --ease-out-soft: cubic-bezier(.16,1,.3,1);
  --ease-press: cubic-bezier(.2,0,0,1);

  /* Type */
  --font-ui: "Geist", -apple-system, "Segoe UI", system-ui, sans-serif;
  --font-mono: "Geist Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;
}

/* ---- App-local geometry. Not new design values — the §8.3 measurements
   given a name so the layout math is checkable in one place. ---- */
:root {
  --dev-w: 393px;
  --dev-h: 852px;
  --safe-top: 59px;                  /* status bar / notch */
  --safe-bottom: 34px;               /* home indicator */
  --inset: 24px;                     /* login + engagements screen inset */
  --inset-stack: 33px;               /* workshop inset → 19px peek each side */
  --card-w: 327px;
  --card-h: 470px;
  --card-gap: 14px;
  /* amplitude, 0.15 → 1.0. Written every frame by app.js; drives the bars
     AND the live rail capsule off one number (§4.2, §7.2). */
  --cap-amp: .34;
}

/* ---- Reset / base ---- */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--font-ui);
  background: var(--page-bg);
  color: var(--ink-700);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  min-height: 100vh;
  display: grid;
  place-items: center;
  overflow: hidden;
}
button {
  font-family: inherit; cursor: pointer; border: 0; background: none;
  color: inherit; padding: 0; -webkit-tap-highlight-color: transparent;
}
input { font-family: inherit; }

/* ============================================================
   DEVICE FRAME
   Realistic but restrained. A rounded bezel, a status bar in the
   59px safe area, a home indicator in the bottom 34px. Nothing
   else — this is a phone, not a product shot.
   ============================================================ */
.phone {
  padding: 12px;
  border-radius: 68px;
  background: linear-gradient(160deg, #2A2F38 0%, #14181F 42%, #23282F 100%);
  box-shadow:
    0 0 0 1px rgba(255,255,255,.10) inset,
    0 2px 6px rgba(16,42,72,.10),
    0 34px 90px rgba(16,42,72,.34);
}
.device {
  position: relative;
  width: var(--dev-w);
  height: var(--dev-h);
  border-radius: 56px;
  background: var(--page-bg);
  overflow: hidden;
  isolation: isolate;
}

/* ---- status bar. Sits ABOVE the scrims, as it does on the device, and
   flips to white when a dark overlay is up. ---- */
.statusbar {
  position: absolute; inset: 0 0 auto 0; z-index: 125;
  height: var(--safe-top);
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 32px; padding-top: 8px;
  color: var(--ink-950); pointer-events: none;
  transition: color var(--dur-base) var(--ease-smooth);
}
.device.is-overlay .statusbar,
.device.is-overlay .home-ind { color: #fff; }
.device.is-overlay .statusbar__signal { pointer-events: none; }
.statusbar__time {
  font-family: var(--font-ui); font-size: 16px; font-weight: 600;
  letter-spacing: -.01em; font-variant-numeric: tabular-nums;
  width: 62px;
}
.statusbar__island {
  width: 122px; height: 34px; border-radius: 9999px; background: #0A0C10;
}
.statusbar__icons { display: flex; align-items: flex-end; gap: 6px; width: 62px; justify-content: flex-end; }
.statusbar__signal {
  display: inline-flex; align-items: flex-end; gap: 2px;
  pointer-events: auto; padding: 6px 0;
}
.statusbar__signal i { width: 3px; border-radius: 1px; background: currentColor; }
.statusbar.is-offline .statusbar__signal i { opacity: .22; }
.statusbar.is-offline .statusbar__wifi { opacity: .22; }
.statusbar__wifi { display: block; margin-bottom: 0; }
.statusbar__batt {
  position: relative; width: 25px; height: 12px; display: block; padding: 1.5px;
}
.statusbar__batt::before {
  content: ""; position: absolute; inset: 0; border-radius: 3.5px;
  border: 1px solid currentColor; opacity: .38;
}
.statusbar__batt::after {
  content: ""; position: absolute; right: -3.5px; top: 50%; transform: translateY(-50%);
  width: 2px; height: 4px; border-radius: 0 1px 1px 0; background: currentColor; opacity: .38;
}
.statusbar__batt i { display: block; height: 100%; width: 74%; border-radius: 2px; background: currentColor; }

/* ---- home indicator ---- */
.home-ind {
  position: absolute; inset: auto 0 0 0; z-index: 125;
  height: var(--safe-bottom); display: grid; place-items: center; pointer-events: none;
  color: var(--ink-950);
  transition: color var(--dur-base) var(--ease-smooth);
}
.home-ind span { width: 139px; height: 5px; border-radius: 9999px; background: currentColor; opacity: .30; }

/* ============================================================
   SCREENS — three, and only three.
   ============================================================ */
.screen {
  position: absolute; inset: 0; z-index: 10;
  padding-top: var(--safe-top);
  padding-bottom: var(--safe-bottom);
  display: flex; flex-direction: column;
  opacity: 0; visibility: hidden;
  transform: translateX(14px);
  transition: opacity var(--dur-slow) var(--ease-out-soft),
              transform var(--dur-slow) var(--ease-out-soft),
              visibility 0s linear var(--dur-slow);
}
.screen.is-active {
  opacity: 1; visibility: visible; transform: none;
  transition: opacity var(--dur-slow) var(--ease-out-soft),
              transform var(--dur-slow) var(--ease-out-soft),
              visibility 0s;
}
.screen.is-back { transform: translateX(-14px); }

/* ============================================================
   §1.1 LOGIN — two steps, one field each
   ============================================================ */
.screen--login { padding-inline: var(--inset); }
.login__kicker {
  margin: 180px 0 0;
  font-family: var(--font-mono); font-size: 11px; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase; color: var(--ink-400);
}
.login__slot { margin-top: 22px; }
.field {
  width: 100%; height: 60px;
  padding: 0 22px;
  border: 1px solid var(--ink-200); border-radius: var(--radius-search);
  background: var(--surface); box-shadow: var(--shadow-search);
  font-size: 17px; font-weight: 500; letter-spacing: -.01em; color: var(--ink-950);
  transition: border-color var(--dur-base) var(--ease-smooth),
              box-shadow var(--dur-base) var(--ease-smooth);
}
.field::placeholder { color: var(--ink-400); }
.field:focus {
  outline: none; border-color: var(--ink-700);
  box-shadow: var(--shadow-search), 0 0 0 3px var(--focus-ink);
}
/* step 2 — the field is REPLACED, not stacked. Mono, tracked wide. */
.field--code {
  font-family: var(--font-mono); font-size: 24px; font-weight: 600;
  letter-spacing: .28em; text-align: center; padding: 0 8px 0 22px;
}
.login__go { margin-top: 14px; }
.login__alt {
  margin: 20px auto 0;
  font-family: var(--font-mono); font-size: 11px; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase; color: var(--ink-400);
  min-height: 56px; padding: 0 12px;
}

/* ============================================================
   §1.2 UPCOMING ENGAGEMENTS — company + date, nothing else
   ============================================================ */
.screen--engagements { padding-inline: var(--inset); overflow-y: auto; }
.eng__kicker {
  margin: 12px 0 20px;
  font-family: var(--font-mono); font-size: 11px; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase; color: var(--ink-400);
}
.eng__list { display: flex; flex-direction: column; gap: 16px; }
.eng-row {
  position: relative;
  display: flex; flex-direction: column; justify-content: center; gap: 7px;
  width: 100%; height: 104px; padding: 0 24px;
  border-radius: var(--radius-image);     /* 30px — the PROPORTIONAL inner radius.
                                             48px on a 104px row reads as a lozenge. */
  background: var(--surface); box-shadow: var(--shadow-card-rest);
  text-align: left;
  transition: transform var(--dur-fast) var(--ease-press),
              box-shadow var(--dur-base) var(--ease-smooth),
              background var(--dur-base) var(--ease-smooth);
}
.eng-row:active { transform: scale(.985); }
.eng-row__co { font-size: 22px; font-weight: 600; letter-spacing: -.018em; color: var(--ink-950); }
.eng-row__when {
  display: flex; align-items: center; gap: 9px;
  font-family: var(--font-mono); font-size: 12.5px; font-weight: 500;
  letter-spacing: .06em; text-transform: uppercase; color: var(--ink-500);
}
/* THE ONE BLACK ROW — today's engagement, the strategy treatment.
   At three feet the thing Jed is about to run is unmistakable. */
.eng-row.is-today { background: var(--ink-950); box-shadow: var(--shadow-card-hover); }
.eng-row.is-today::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.10);
}
.eng-row.is-today:active { background: #060B14; }
.eng-row.is-today .eng-row__co { color: #fff; }
.eng-row.is-today .eng-row__when { color: rgba(255,255,255,.55); }
/* recording recovery path: the row keeps the black treatment and gains the
   live bars + session timer in place of the date (§1.2) */
.eng-row .cap-levels { color: rgba(255,255,255,.85); }
.eng__signout {
  align-self: flex-end;
  margin: 6px 0 24px; min-height: 56px; padding: 0 4px;
  font-family: var(--font-mono); font-size: 11px; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase; color: var(--ink-400);
}

/* ============================================================
   §1.3 WORKSHOP — session bar · card stack · segment rail
   Vertical budget at 852: 59 safe + 12 + 64 bar + 102 + 470 card
   + 20 + 4 rail + 87 + 34 safe = 852.
   ============================================================ */
.screen--workshop { overflow: hidden; }

/* ---- §3.1 SESSION BAR — one object, three redundant channels ---- */
.sess-slot {
  position: relative; flex: none;
  height: 64px; margin: 12px auto 0; width: 345px;
}
/* before capture starts there is no session bar — only a bare back chevron */
.sess-back {
  position: absolute; left: -6px; top: 0;
  width: 56px; height: 56px; display: grid; place-items: center;
  color: var(--ink-500); border-radius: var(--radius-pill);
  transition: opacity var(--dur-base) var(--ease-smooth);
}
.sess-back:active { color: var(--ink-950); }
.sess-slot.is-live .sess-back { opacity: 0; pointer-events: none; }

.sess-bar {
  position: absolute; inset: 0;
  display: flex; align-items: center; gap: 4px;
  padding: 0 8px 0 4px;
  border-radius: var(--radius-pill);
  background: var(--ink-950); box-shadow: var(--shadow-card-hover);
  color: #fff; cursor: pointer;
  opacity: 0; transform: translateY(-8px); pointer-events: none;
  transition: opacity var(--dur-slow) var(--ease-out-soft),
              transform var(--dur-slow) var(--ease-out-soft),
              background var(--dur-base) var(--ease-smooth),
              box-shadow var(--dur-base) var(--ease-smooth);
}
.sess-slot.is-live .sess-bar { opacity: 1; transform: none; pointer-events: auto; }
.sess-bar:active { background: #060B14; }
.sess-bar__chev {
  flex: none; width: 56px; height: 56px; display: grid; place-items: center;
  color: rgba(255,255,255,.55); border-radius: var(--radius-pill);
  transition: color var(--dur-base) var(--ease-smooth);
}
.sess-bar__body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.sess-bar__row { display: flex; align-items: center; gap: 11px; }
.sess-bar__timer {
  font-family: var(--font-mono); font-size: 15px; font-weight: 600;
  font-variant-numeric: tabular-nums; color: #fff; letter-spacing: .01em;
  transition: color var(--dur-base) var(--ease-smooth);
}
.sess-bar__label {
  font-family: var(--font-mono); font-size: 11px; font-weight: 600;
  letter-spacing: .10em; text-transform: uppercase; color: rgba(255,255,255,.55);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: opacity var(--dur-base) var(--ease-smooth);
}
.sess-bar__label.is-swapping { opacity: 0; }
.sess-bar__caret { flex: none; color: rgba(255,255,255,.42); display: grid; place-items: center; width: 24px; }
/* the reduced-motion substitute channel — hidden unless (prefers-reduced-motion) */
.sess-bar__rec { display: none; align-items: center; gap: 7px;
  font-family: var(--font-mono); font-size: 11px; font-weight: 600; letter-spacing: .10em; color: #fff; }
.sess-bar__rec b { width: 8px; height: 8px; border-radius: 50%; background: #fff; }

/* §3.2 you have swiped away from the live card. The chevron becomes a
   return-to-live control and the bar gains an outline it does not
   otherwise have — so "which one is recording" is never inferred. */
.sess-bar.is-away { box-shadow: var(--shadow-card-hover), inset 0 0 0 1px rgba(255,255,255,.28); }
.sess-bar.is-away .sess-bar__chev { color: #fff; }

/* §3.4 PAUSED must look wrong. Hollow, dead, stopped. Nothing pulses,
   nothing nags, no toast. It simply looks broken, which is correct. */
.sess-bar.is-paused {
  background: rgba(14,23,38,.72); box-shadow: inset 0 0 0 1.5px rgba(255,255,255,.55);
}
.sess-bar.is-paused .sess-bar__timer { color: rgba(255,255,255,.42); }

/* ---- §7.1 THE CARD STACK ---- */
.stack-wrap { flex: none; margin-top: 102px; }
.stack {
  display: flex; align-items: flex-start; gap: var(--card-gap);
  padding-inline: var(--inset-stack);
  height: var(--card-h);
  overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--inset-stack);
  scrollbar-width: none;
  touch-action: pan-y;
  cursor: grab;
  user-select: none; -webkit-user-select: none;
}
.stack::-webkit-scrollbar { display: none; }
.stack.is-dragging { cursor: grabbing; scroll-snap-type: none; }
.stack.is-animating { scroll-snap-type: none; }
.stack__cell {
  flex: none; width: var(--card-w); height: var(--card-h);
  scroll-snap-align: center;
  transform-origin: center center;
  /* scale + opacity are interpolated on scroll by app.js; neighbours rest
     at scale(.96) / 70% so the series is always visible in the periphery */
  will-change: transform, opacity;
}

/* ---- THE CAPTURE CARD — .card--strategy applied whole (§8.4) ---- */
.cap-card {
  position: relative; width: 100%; height: 100%;
  border-radius: var(--radius-card);
  background: var(--ink-950);
  box-shadow: var(--shadow-card-hover);
  transition: transform var(--dur-fast) var(--ease-press),
              background var(--dur-base) var(--ease-smooth),
              box-shadow var(--dur-base) var(--ease-smooth);
  outline: none;
}
.cap-card::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none; z-index: 4;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.10);
  transition: box-shadow var(--dur-base) var(--ease-smooth);
}
.cap-card__clip {
  position: absolute; inset: 0; border-radius: inherit; overflow: hidden;
  display: flex; flex-direction: column;
}
.cap-card__field {
  flex: 1 1 auto; display: flex; flex-direction: column;
  padding: 28px; color: #fff;
  background: radial-gradient(130% 90% at 16% -8%, rgba(255,255,255,.06) 0%, rgba(255,255,255,0) 56%);
}
.cap-card__top { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.cap-card__kicker {
  font-family: var(--font-mono); font-size: 11px; font-weight: 600; letter-spacing: .10em;
  text-transform: uppercase; color: rgba(255,255,255,.55);
}
.cap-card__dur {
  font-family: var(--font-mono); font-size: 11px; font-weight: 600; letter-spacing: .10em;
  text-transform: uppercase; color: rgba(255,255,255,.42); text-align: right; flex: none;
}
/* the glyph and the check share ONE grid cell — one object in the field
   at a time, and the check lands exactly where the bars were */
.cap-card__glyph {
  flex: 1 1 auto; display: grid; place-items: center;
}
.cap-card__glyph > * { grid-area: 1 / 1; }
/* pressed state on black surfaces — #060B14 replaces desktop hover.
   (@media (hover: hover) blocks are omitted entirely; there is no hover
   on this device.) */
.cap-card.is-pressed { background: #060B14; transform: scale(.985); }
.cap-card.is-pressed .cap-card__footer { background: #060B14; }

/* ---- footer: title 26 → 8 → state line → 20 → 56px pill ---- */
.cap-card__footer {
  flex: none; position: relative; z-index: 3;
  padding: 26px 28px 30px;
  background: var(--ink-950); border-top: 1px solid rgba(255,255,255,.10);
  transition: background var(--dur-base) var(--ease-smooth);
}
.cap-card__title {
  margin: 0; font-size: 26px; font-weight: 600; letter-spacing: -.020em; color: #fff;
}
.cap-card__state {
  margin: 8px 0 0;
  font-family: var(--font-mono); font-size: 11px; font-weight: 600; letter-spacing: .10em;
  text-transform: uppercase; color: rgba(255,255,255,.55); font-variant-numeric: tabular-nums;
}
.cap-card__action { margin-top: 20px; }
.cap-card__hint {
  display: block; margin-top: 18px; text-align: center;
  font-family: var(--font-mono); font-size: 10.5px; font-weight: 600; letter-spacing: .12em;
  text-transform: uppercase; color: rgba(255,255,255,.42);
}
/* zero-or-one control per state. ABSENT, never disabled (§2). */
.cap-card__action[hidden], .cap-card__hint[hidden] { display: none; }

/* ---- §7.3 LOCKED: recessive, control-free, states a dependency as a fact ---- */
.cap-card.is-locked { background: var(--ink-900); box-shadow: var(--shadow-card-rest); }
.cap-card.is-locked::after { box-shadow: inset 0 0 0 1px rgba(255,255,255,.06); }
.cap-card.is-locked .cap-card__footer { background: var(--ink-900); border-top-color: rgba(255,255,255,.06); }
.cap-card.is-locked .cap-card__clip { opacity: .55; }
/* tapping a locked card SETTLES — a physical "not yet". No toast, no modal. */
@keyframes cap-settle { 0% { transform: none; } 45% { transform: translateY(2px); } 100% { transform: none; } }
.cap-card.is-settling { animation: cap-settle 180ms var(--ease-out-soft); }

/* ---- §2.1 SEND FAILED — the one card hairline that uses --alert (§8.5 #3) ---- */
.cap-card.is-failed::after { box-shadow: inset 0 0 0 1px var(--alert); }

/* ---- §4.3 the sweeping hairline ---- */
.cap-card__sweep {
  position: absolute; left: 0; right: 0; top: 0; height: 1px; z-index: 5;
  background: rgba(255,255,255,.50); opacity: 0; pointer-events: none;
  transform: translateY(0);
}
.cap-card.is-sweeping .cap-card__sweep {
  animation: cap-sweep 520ms var(--ease-out-soft) forwards;
}
@keyframes cap-sweep {
  0%   { opacity: 0;  transform: translateY(0); }
  12%  { opacity: 1; }
  88%  { opacity: 1; }
  100% { opacity: 0;  transform: translateY(470px); }
}

/* ---- §6.1 the long-press ring ---- */
.cap-card__ring {
  position: absolute; inset: 0; z-index: 6; pointer-events: none;
  width: 100%; height: 100%; opacity: 0;
  transition: opacity var(--dur-fast) linear;
}
.cap-card.is-ringing .cap-card__ring { opacity: 1; }
.cap-card.is-ring-full .cap-card__ring rect { stroke: #fff; }

/* ============================================================
   §4 .cap-levels — the capture glyph.
   A phone-scale extension of .wt-levels. NOT a new idea, the same
   idea larger. Never a microphone icon.
   ============================================================ */
.cap-levels {
  display: inline-flex; align-items: flex-end; gap: 3px;
  height: 20px; color: inherit; flex: none;
}
.cap-levels i {
  display: block; width: 3px; height: 100%; border-radius: 2px;
  background: currentColor;
  transform-origin: center bottom;
  /* the fixed silhouette coefficient — same varied character as
     .strat-home__glyph, so it looks like the family even when frozen */
  transform: scaleY(calc(var(--cap-amp) * var(--bar-k)));
  transition: transform 90ms linear;
}
.cap-levels i:nth-child(1) { --bar-k: .50; }
.cap-levels i:nth-child(2) { --bar-k: .82; }
.cap-levels i:nth-child(3) { --bar-k: .62; }
.cap-levels i:nth-child(4) { --bar-k: 1.0; }
.cap-levels i:nth-child(5) { --bar-k: .75; }
.cap-levels i:nth-child(6) { --bar-k: .90; }
.cap-levels i:nth-child(7) { --bar-k: .66; }

/* card glyph — 72px tall, 9px bars, 10px gap → 123px wide */
.cap-levels--card {
  height: 72px; gap: 10px; color: rgba(255,255,255,.92);
  transition: opacity var(--dur-base) var(--ease-smooth);
}
.cap-levels--card i { width: 9px; border-radius: 5px; }
/* session bar / engagement row glyph */
.cap-levels--bar { height: 13px; gap: 3px; color: rgba(255,255,255,.85); }
.cap-levels--bar i { width: 3px; border-radius: 2px; }

/* the card glyph is absent entirely on LOCKED, and hidden while the check
   is on screen — one object in the field at a time */
.cap-card.is-locked .cap-levels--card { opacity: 0; }
.cap-card.is-checked .cap-levels--card { opacity: 0; }

/* §3.4 PAUSED: bars freeze at a flat, EVEN silhouette — a dead waveform.
   Not the --bar-k character; the point is that it stops looking alive. */
.cap-levels.is-flat i { transform: scaleY(.22); }

/* ---- §4.3 the drawn check ---- */
.cap-check {
  opacity: 0;
  transition: opacity var(--dur-fast) linear;
}
.cap-check polyline {
  stroke-dasharray: var(--check-len, 40);
  stroke-dashoffset: var(--check-len, 40);
}
.cap-card.is-checked .cap-check { opacity: 1; }
.cap-card.is-checked .cap-check polyline {
  animation: cap-check-draw 360ms var(--ease-out-soft) forwards;
}
@keyframes cap-check-draw { to { stroke-dashoffset: 0; } }

/* ============================================================
   §7.2 SEGMENT RAIL — five 44×4 capsules, 6px gap → 244px
   ============================================================ */
.rail {
  flex: none; margin: 20px auto 0;
  display: flex; gap: 6px; justify-content: center;
}
.rail__cap {
  width: 44px; height: 4px; border-radius: 9999px;
  background: var(--ink-300);
  transition: background var(--dur-base) var(--ease-smooth), opacity 90ms linear;
  /* 56px tap target without 56px of ink */
  position: relative;
}
.rail__cap::before { content: ""; position: absolute; inset: -26px -3px; }
.rail__cap.is-done { background: var(--ink-950); }
/* the live capsule breathes with the SAME amplitude variable driving the
   bars — a fourth, peripheral confirmation, costing zero extra chrome */
.rail__cap.is-live {
  background: var(--ink-950);
  opacity: calc(.55 + .45 * var(--cap-amp));
}

/* ============================================================
   CONTROLS — every tap target ≥ 56px. Not 44. Jed is reaching
   across a table without looking.
   ============================================================ */
.pill {
  display: block; width: 100%; height: 56px;
  border-radius: var(--radius-pill);
  font-size: 17px; font-weight: 600; letter-spacing: -.010em;
  transition: transform var(--dur-fast) var(--ease-press),
              background var(--dur-base) var(--ease-smooth),
              border-color var(--dur-base) var(--ease-smooth);
}
.pill:active { transform: scale(.98); }
.pill--dark { background: var(--ink-950); color: #fff; box-shadow: var(--shadow-pill); }
.pill--dark:active { background: #060B14; }
/* white pill on a black card */
.pill--light { background: #fff; color: var(--ink-950); }
.pill--light:active { background: rgba(255,255,255,.86); }
.pill--ghost { background: transparent; color: var(--ink-950); border: 1px solid var(--ink-200); }
.pill--ghost:active { background: var(--ink-50); }

.ghost-text {
  display: block; width: 100%; min-height: 56px; margin-top: 4px;
  font-size: 15px; font-weight: 500; color: var(--ink-500);
}
.ghost-text:active { color: var(--ink-700); }

/* the --alert text label. Not a filled button. Visually the lightest thing
   in the sheet and the hardest thing to do. (§8.5 uses #1 and #2.) */
.alert-text {
  display: block; width: 100%; min-height: 56px;
  font-size: 15px; font-weight: 600; color: var(--alert);
  letter-spacing: -.005em;
}

/* ---- hold-to-confirm (§5.2 900ms · §5.3 700ms) ---- */
.hold { position: relative; display: flex; flex-direction: column; align-items: center; }
.hold__btn { touch-action: none; user-select: none; -webkit-user-select: none; }
.hold__track {
  display: block; width: 168px; height: 2px; border-radius: 1px;
  background: rgba(229,72,77,.16); overflow: hidden; margin-top: -8px;
}
.hold__fill {
  display: block; width: 0%; height: 100%; background: var(--alert);
  /* LINEAR is honest about remaining time; eased would lie. */
  transition: width 180ms var(--ease-out-soft);
}
.hold.is-holding .hold__fill { transition-timing-function: linear; }
/* reduced-motion substitute: a stepped 3-segment underline */
.hold__steps { display: none; gap: 4px; margin-top: -8px; }
.hold__steps i { display: block; width: 53px; height: 2px; border-radius: 1px; background: rgba(229,72,77,.16); }
.hold__steps i.is-on { background: var(--alert); }
.hold__risk {
  margin: 12px 0 0;
  font-family: var(--font-mono); font-size: 12px; font-weight: 500;
  letter-spacing: .06em; text-transform: uppercase; color: var(--ink-500);
  text-align: center;
}

/* ============================================================
   §5 THE TWO CONFIRMATIONS — they must not feel alike.
   Different geometry, entry, scrim, dismissal, physical effort.
   ============================================================ */
.scrim {
  position: absolute; inset: 0; z-index: 100;
  opacity: 0; visibility: hidden;
  transition: opacity var(--dur-slow) var(--ease-smooth), visibility 0s linear var(--dur-slow);
}
.scrim.is-open { opacity: 1; visibility: visible; transition: opacity var(--dur-slow) var(--ease-smooth), visibility 0s; }
/* .strat-backdrop values */
.scrim--sheet { background: rgba(16,42,72,.46); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px); }
/* noticeably darker — the room behind it goes away */
.scrim--modal { background: rgba(6,11,20,.72); -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px); z-index: 110; }

/* ---- 5.1 / 6.2 bottom sheet: rises from the bottom edge. Light, fast,
   forgiving. Dismissible by backdrop tap AND swipe-down. ---- */
.sheet {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 105;
  padding: 14px 28px calc(var(--safe-bottom) + 22px);
  border-radius: var(--radius-card) var(--radius-card) 0 0;
  background: var(--surface);
  transform: translateY(100%); visibility: hidden;
  transition: transform var(--dur-slow) var(--ease-out-soft), visibility 0s linear var(--dur-slow);
}
.sheet.is-open { transform: translateY(0); visibility: visible; transition: transform var(--dur-slow) var(--ease-out-soft), visibility 0s; }
.sheet.is-dragging { transition: none; }
.sheet__grab { display: block; width: 36px; height: 4px; border-radius: 2px; background: var(--ink-300); margin: 0 auto 22px; }
.sheet__kicker {
  margin: 0;
  font-family: var(--font-mono); font-size: 11px; font-weight: 600; letter-spacing: .12em;
  text-transform: uppercase; color: var(--ink-400);
}
.sheet__head {
  margin: 14px 0 0; font-size: 26px; font-weight: 600; letter-spacing: -.020em;
  line-height: 1.18; color: var(--ink-950);
}
.sheet__title { margin: 10px 0 0; font-size: 22px; font-weight: 600; letter-spacing: -.018em; color: var(--ink-950); }
.sheet__meta {
  margin: 14px 0 24px;
  font-family: var(--font-mono); font-size: 12px; font-weight: 500; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-500);
}
.sheet__acts { display: flex; flex-direction: column; gap: 16px; }
.sheet .hold { margin-top: 4px; }

/* ---- 5.2 centered modal: appears IN FRONT OF YOU rather than rising
   from the furniture. Does not dismiss on backdrop tap or swipe. ---- */
.modal {
  position: absolute; left: 50%; top: 50%; z-index: 115;
  width: 313px; padding: 34px 28px 30px;
  border-radius: var(--radius-card); background: var(--surface);
  box-shadow: 0 10px 30px rgba(16,42,72,.16), 0 40px 80px rgba(16,42,72,.28);
  transform: translate(-50%, -50%) scale(.94); opacity: 0; visibility: hidden;
  transition: transform 260ms var(--ease-out-soft), opacity 260ms var(--ease-out-soft),
              visibility 0s linear 260ms;
}
.modal.is-open {
  transform: translate(-50%, -50%) scale(1); opacity: 1; visibility: visible;
  transition: transform 260ms var(--ease-out-soft), opacity 260ms var(--ease-out-soft), visibility 0s;
}
.modal__head {
  margin: 14px 0 0; font-size: 30px; font-weight: 600; letter-spacing: -.022em;
  line-height: 1.14; color: var(--ink-950);
}
.modal__body { margin: 14px 0 0; font-size: 15px; font-weight: 400; line-height: 1.5; color: var(--ink-600); }
.modal .sheet__meta { margin: 18px 0 22px; }
.modal .hold { margin-top: 10px; }

/* ============================================================
   §4.4 REDUCED MOTION
   Motion can no longer carry "we are recording", so a non-motion
   channel substitutes. The record dot is WHITE, not --alert: the
   one sanctioned accent is reserved for the destructive stop path.
   If red means "recording" it cannot also mean "danger", and
   danger is the more important job.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
  /* bars render as the static varied silhouette from the --bar-k
     coefficients, exactly as the existing .wt-levels rule does */
  .cap-levels i { animation: none !important; transition: none !important; }
  .cap-levels i:nth-child(1) { transform: scaleY(.50); }
  .cap-levels i:nth-child(2) { transform: scaleY(.82); }
  .cap-levels i:nth-child(3) { transform: scaleY(.62); }
  .cap-levels i:nth-child(4) { transform: scaleY(1); }
  .cap-levels i:nth-child(5) { transform: scaleY(.75); }
  .cap-levels i:nth-child(6) { transform: scaleY(.90); }
  .cap-levels i:nth-child(7) { transform: scaleY(.66); }

  /* the non-motion substitute channel in the session bar */
  .sess-bar__rec { display: inline-flex; }
  .sess-bar.is-paused .sess-bar__rec { display: none; }
  .sess-slot .cap-levels--bar { display: none; }
  .sess-bar.is-paused .cap-levels--bar { display: inline-flex; }

  /* PAUSED still has to look wrong under reduced motion — the flat, even
     silhouette outranks the varied one above */
  .cap-levels.is-flat i:nth-child(n) { transform: scaleY(.22); }

  /* live rail capsule: solid, with an outline ring. No oscillation. */
  .rail__cap.is-live { opacity: 1; box-shadow: 0 0 0 1.5px var(--ink-950); }

  /* submit choreography degrades to opacity crossfades at 120ms;
     the check appears already drawn; the 400ms hold is PRESERVED —
     it is comprehension, not decoration (handled in app.js). */
  .cap-card.is-checked .cap-check polyline { animation: none; stroke-dashoffset: 0; }
  .cap-card.is-sweeping .cap-card__sweep { animation: none; opacity: 0; }
  .cap-card.is-settling { animation: none; }

  /* hold-to-confirm becomes a stepped 3-segment underline */
  .hold__track { display: none; }
  .hold__steps { display: flex; }

  /* screens and overlays appear/disappear without travel */
  .screen { transform: none !important; transition-duration: 1ms, 1ms, 0s; }
  .sheet, .modal, .scrim, .sess-bar, .cap-card, .stack__cell { transition-duration: 1ms !important; }
  .sheet.is-open, .sheet:not(.is-open) { transition-duration: 1ms !important; }
}
