/* ==========================================================================
   CHAINED TIMERS — Editorial Athletic Brutalism
   ========================================================================== */

:root {
  /* warm-toned near-black palette */
  --bg:           #0E0D0B;
  --bg-2:         #14120F;
  --surface:      #1A1714;
  --surface-2:    #221E19;
  --surface-3:    #2B2620;
  --rule:         #2C2823;
  --rule-strong:  #3D372F;

  /* text */
  --ink:          #F2EDE2;     /* primary */
  --ink-soft:     #C9C2B3;
  --ink-dim:      #8A8273;
  --ink-faint:    #5A5448;

  /* accents */
  --accent:       #F5B042;     /* amber — running */
  --accent-warm:  #F2A02A;
  --accent-deep:  #B5751B;
  --warn:         #E2483A;     /* crimson — final seconds */
  --good:         #9BB089;     /* sage — complete */
  --link:         #E9CFA0;

  /* chain palette (for color tags) */
  --c-amber:  #F5B042;
  --c-rust:   #C97847;
  --c-rose:   #D88BA0;
  --c-violet: #9D8BD8;
  --c-indigo: #7B7BC9;
  --c-teal:   #5DAC9D;
  --c-sage:   #9BB089;
  --c-bone:   #D4CDBA;

  /* radii */
  --r-xs: 6px;
  --r-sm: 10px;
  --r-md: 16px;
  --r-lg: 22px;
  --r-xl: 32px;

  /* shadow */
  --sh-soft: 0 1px 0 rgba(255,255,255,0.03), 0 18px 36px -24px rgba(0,0,0,0.55);
  --sh-card: 0 1px 0 rgba(255,255,255,0.04), 0 28px 48px -28px rgba(0,0,0,0.7);

  /* type */
  --f-display: 'Anton', 'Big Shoulders Display', 'Helvetica Neue', sans-serif;
  --f-serif:   'Fraunces', 'Times New Roman', serif;
  --f-mono:    'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;
  --f-body:    'Manrope', system-ui, -apple-system, sans-serif;

  /* layout */
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bot: env(safe-area-inset-bottom, 0px);
  --tabbar-h: 76px;
}

* { box-sizing: border-box; margin: 0; padding: 0; -webkit-tap-highlight-color: transparent; }
html, body { height: 100%; overflow: hidden; }
/* v1.4.8 — kill Android WebView's overscroll navigation. Without
   this, a horizontal drag inside the app pulls in the previous page
   from history; since the SPA has no history, the WebView surfaces
   the swipe to the OS which minimises the app. */
html, body { overscroll-behavior: none; }
html { font-size: 16px; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--f-body);
  font-weight: 400;
  font-feature-settings: 'ss01', 'cv11';
  letter-spacing: 0.005em;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* warm grain background */
  background-image:
    radial-gradient(ellipse 80% 50% at 50% -10%, rgba(245,176,66,0.06), transparent 60%),
    radial-gradient(ellipse 60% 40% at 100% 100%, rgba(125,90,40,0.04), transparent 70%);
}

button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
input, textarea, select { font: inherit; color: inherit; }
a { color: var(--link); text-decoration-thickness: 1px; text-underline-offset: 2px; }

::selection { background: var(--accent); color: var(--bg); }

/* hidden */
[hidden] { display: none !important; }

/* ==========================================================================
   APP SHELL & VIEWS
   ========================================================================== */

.app {
  position: relative;
  height: 100dvh;
  width: 100vw;
  max-width: 560px;
  margin: 0 auto;
  overflow: hidden;
}

@media (min-width: 720px) {
  .app {
    border-left: 1px solid var(--rule);
    border-right: 1px solid var(--rule);
  }
}

.view {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  animation: viewFade 280ms cubic-bezier(.2,.7,.25,1);
}

@keyframes viewFade {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ==========================================================================
   TOP BAR (shared)
   ========================================================================== */

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: calc(14px + var(--safe-top)) 18px 12px;
  border-bottom: 1px solid var(--rule);
  background: var(--bg);
  position: relative;
  z-index: 2;
}

.topbar-left { display: flex; flex-direction: column; gap: 2px; }

/* v1.4.9 — the select-mode topbar now packs trash + play as two icons
   on the right. This wrapper keeps them tight together. */
.topbar-actions {
  display: flex;
  align-items: center;
  gap: 6px;
}

.wordmark {
  font-family: var(--f-display);
  font-size: 30px;
  line-height: 0.86;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  color: var(--ink);
  display: flex;
  flex-direction: column;
}

.wordmark-line:first-child { color: var(--ink); }
.wordmark-line:last-child  { color: var(--accent); }

.tagline {
  font-family: var(--f-serif);
  font-size: 13px;
  font-style: italic;
  color: var(--ink-dim);
  margin-top: 4px;
  letter-spacing: 0.01em;
  font-weight: 400;
}

.topbar-title {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: 1;
  text-align: center;
}

.topbar-eyebrow {
  font-family: var(--f-mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-dim);
  margin-bottom: 2px;
}

.topbar-h {
  font-family: var(--f-display);
  font-size: 26px;
  font-weight: 400;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  line-height: 1;
}

.icon-btn {
  width: 42px; height: 42px;
  display: inline-grid;
  place-items: center;
  border-radius: 50%;
  color: var(--ink);
  transition: background 160ms;
  flex-shrink: 0;
}
.icon-btn:hover, .icon-btn:focus-visible { background: var(--surface-2); outline: none; }
.icon-btn:active { transform: scale(0.94); }

.icon-btn-ghost { visibility: hidden; }

/* Primary-variant icon button (used as the selection-mode Start button
   in the library topbar). Filled amber gradient, dark fill icon. */
.icon-btn-primary {
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-warm) 100%);
  color: #1A0F00;
  box-shadow: 0 6px 16px -8px rgba(245,176,66,0.55);
}
.icon-btn-primary:hover { filter: brightness(1.06); background: linear-gradient(135deg, var(--accent) 0%, var(--accent-warm) 100%); }
.icon-btn-primary:disabled,
.icon-btn-primary[disabled] {
  background: var(--surface-3);
  color: var(--ink-faint);
  box-shadow: none;
  cursor: default;
}

/* ====================================================================
   LIBRARY SELECTION MODE
   ====================================================================

   The default and the selection-mode topbars share the same slot — JS
   toggles visibility based on `data-select-mode` on the .view-library.
   Chain rows pick up the selected state via `.is-selected`; a circular
   tick badge replaces the play-icon on the right side of each card
   while in selection mode. */
.view-library[data-select-mode="true"] .chain-card-play {
  display: none;
}
.view-library[data-select-mode="true"] .chain-card-body { padding-right: 14px; }
.view-library[data-select-mode="true"] .chain-card {
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
}
/* Selection-mode badge that replaces the play button. Hidden until the
   library is in select mode. Shows a position-based glyph:
     - unselected: dim plus (tap to add)
     - 1st selected (will be focused / on top of the run view): up arrow
     - 2nd selected (will be the background chip / on bottom): down arrow
   The icon is set by UI._setTickContent based on selectedIds order. */
.chain-card-select-tick {
  display: none;
  width: 64px;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  background: transparent;
  color: var(--ink-faint);
  border-left: 1px solid var(--rule);
  transition: color 140ms, background 140ms, border-color 140ms;
}
.view-library[data-select-mode="true"] .chain-card-select-tick { display: flex; }
.chain-card-select-tick svg { width: 28px; height: 28px; }
.chain-card-select-tick-lbl {
  font-family: var(--f-mono);
  font-size: 8px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  line-height: 1;
}

/* v1.4.13 — reorder grip. Hidden until select mode, then it claims a
   column left of the colour stripe (see the grid override below). */
.chain-card-grip {
  display: none;
  align-items: center;
  justify-content: center;
  width: 40px;
  color: var(--ink-faint);
  background: transparent;
  border-right: 1px solid var(--rule);
  cursor: grab;
  touch-action: none;          /* the grip owns vertical drags */
  -webkit-tap-highlight-color: transparent;
  transition: color 140ms, background 140ms;
}
.view-library[data-select-mode="true"] .chain-card-grip { display: flex; }
/* Grid gains a leading column for the grip only in select mode, so the
   default (non-select) layout is byte-identical to before. */
.view-library[data-select-mode="true"] .chain-card {
  grid-template-columns: 40px 6px 1fr auto;
}
.chain-card-grip:active { cursor: grabbing; color: var(--accent); background: rgba(245,176,66,0.10); }

/* The row being dragged floats above its neighbours and stops
   transitioning its own transform (the pointer drives it directly). */
.chain-card.is-reordering,
.chain-status-card.is-reordering {
  position: relative;
  z-index: 3;
  transition: none !important;
  box-shadow: 0 22px 40px -18px rgba(0,0,0,0.75);
  cursor: grabbing;
}
.chain-card.is-reordering { border-color: var(--accent); }
/* Suppress text selection + hover flicker while a reorder is in flight. */
body.is-reordering-chains { user-select: none; -webkit-user-select: none; }
body.is-reordering-chains .chain-card:hover { border-color: var(--rule); background: var(--surface); }

/* v1.4.14 — brief flash on a freshly created chain. New chains are
   appended to the bottom of the list, so revealChain() scrolls to the
   new row; this makes the landing spot obvious once the scroll ends,
   instead of leaving the user to work out which row is new. */
.chain-card.is-new {
  animation: newChainFlash 1.6s ease-out;
}
@keyframes newChainFlash {
  0%, 55% { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent), 0 0 22px -4px rgba(245,176,66,0.55); }
  100%    { border-color: var(--rule);   box-shadow: var(--sh-soft); }
}
@media (prefers-reduced-motion: reduce) {
  .chain-card.is-new { animation: none; border-color: var(--accent); }
}

.chain-card.is-selected {
  /* 2px-effective amber outline via combined border + outer shadow.
     box-shadow doesn't reflow, so there's no layout shift on toggle. */
  border-color: var(--accent);
  background: rgba(245,176,66,0.12);
  box-shadow: 0 0 0 1px var(--accent), 0 18px 36px -24px rgba(0,0,0,0.55);
}
.chain-card.is-selected .chain-card-select-tick {
  color: var(--accent);
  background: rgba(245,176,66,0.10);
  border-left-color: var(--accent);
}

/* Visual cue that a chain is currently running — small amber dot on the
   card. Persists across selection mode so the user can see at a glance
   which chains are already alive. */
.chain-card.is-running .chain-card-name::after {
  content: '';
  display: inline-block;
  width: 7px; height: 7px;
  margin-left: 8px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 8px rgba(245,176,66,0.7);
  vertical-align: middle;
  animation: runningPulse 1.4s ease-in-out infinite;
}
@keyframes runningPulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.4; transform: scale(0.82); }
}

/* ====================================================================
   RUN CHIPS (v1.4 — multi-chain switcher in the run view)
   ==================================================================== */

.run-chips {
  display: flex;
  gap: 8px;
  justify-content: center;
  padding: 4px 18px 0;
  flex-wrap: wrap;
}
.run-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--rule);
  font-family: var(--f-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  transition: border-color 140ms, background 140ms, color 140ms;
  max-width: 45vw;
  min-width: 0;
}
.run-chip:hover { border-color: var(--rule-strong); background: var(--surface-3); }
.run-chip.is-focused {
  border-color: var(--accent);
  background: rgba(245,176,66,0.10);
  color: var(--ink);
}
.run-chip-dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--ink-faint);
  flex-shrink: 0;
}
.run-chip.is-focused .run-chip-dot {
  background: var(--accent);
  box-shadow: 0 0 6px rgba(245,176,66,0.6);
}
.run-chip.is-paused .run-chip-dot { background: var(--good); }
.run-chip-name {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  min-width: 0;
}
.run-chip-clock {
  font-variant-numeric: tabular-nums;
  color: var(--accent);
  flex-shrink: 0;
}
.run-chip.is-paused .run-chip-clock { color: var(--good); }

/* v1.4.23 — chip for a chain held at a ringing gate. The freeze rides on
   the pause plumbing, so without this the ringing chain read as "paused"
   in the strip — no way to tell which of two chains was the one going
   off. Same warn colour and pulse as the run view it belongs to. */
.run-chip.is-ringing .run-chip-dot {
  background: var(--warn);
  box-shadow: 0 0 6px rgba(226,72,58,0.7);
  animation: pendingBlink 0.95s ease-in-out infinite;
}
.run-chip.is-ringing .run-chip-clock { color: var(--warn); }

/* v1.4.11 — chip for a chain counting down inline (prestart while
   another chain is running). Blinking dot = "about to start". */
.run-chip.is-pending .run-chip-dot {
  background: var(--accent);
  animation: pendingBlink 1s ease-in-out infinite;
}
@keyframes pendingBlink {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.3; }
}

/* ====================================================================
   LIBRARY INLINE STATUS CARD (v1.4.5)
   One card per active run, rendered as a sibling <li> directly below
   its parent chain-card so the two visually attach. Tap → focus + open
   run view. Swipe left/right → confirm-and-stop that run.
   ==================================================================== */

.chain-status-card {
  display: grid;
  grid-template-columns: 4px 1fr auto;
  gap: 10px;
  align-items: stretch;
  padding: 10px 12px;
  /* Sit right under the parent chain-card. The margin-top negates the
     gap of the chain-list flex column, so the two cards visually touch. */
  margin: -6px 0 4px;
  border: 1px solid var(--rule);
  border-top: 0;
  border-radius: 0 0 var(--r-md) var(--r-md);
  background: linear-gradient(180deg,
    rgba(245,176,66,0.10) 0%,
    rgba(245,176,66,0.04) 100%);
  color: var(--ink);
  cursor: pointer;
  transition: background 140ms, transform 140ms;
  min-height: 52px;
  text-align: left;
  font-family: var(--f-body);
  user-select: none;
  -webkit-user-select: none;
  /* Reset default <li> styling so it matches the surrounding chain-cards */
  list-style: none;
  position: relative;
  overflow: hidden;
}
.chain-status-card:hover { background: linear-gradient(180deg,
    rgba(245,176,66,0.14) 0%,
    rgba(245,176,66,0.06) 100%); }
.chain-status-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.chain-status-card.is-paused .status-clock { color: var(--good); }
.chain-status-card.is-paused .chain-status-stripe { background: var(--good); }

/* Swipe-to-stop backdrop: shown behind the sliding row so the user sees
   a red "release to stop" band while dragging. Height matches the card. */
.chain-status-card.is-swiping { background: transparent; }
.chain-status-card.is-swipe-armed { }

.chain-status-stripe {
  background: var(--accent);
  border-radius: 2px;
  align-self: stretch;
}

.chain-status-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  justify-content: center;
}

.chain-status-line1 {
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: flex;
  align-items: center;
  gap: 6px;
}
.chain-status-line1 .status-icon {
  color: var(--accent);
  font-size: 11px;
  line-height: 1;
}
.chain-status-line1 .status-seg {
  text-transform: uppercase;
  letter-spacing: 0.10em;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
}

.chain-status-line2 {
  font-family: var(--f-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  color: var(--ink-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.chain-status-line2 .status-sep {
  padding: 0 6px;
  color: var(--ink-faint);
}
.chain-status-line2 .status-next {
  font-style: italic;
  font-family: var(--f-serif);
  font-size: 11px;
  color: var(--ink-soft);
}

.status-clock {
  align-self: center;
  font-family: var(--f-mono);
  font-variant-numeric: tabular-nums;
  font-size: 22px;
  font-weight: 600;
  color: var(--accent);
  letter-spacing: 0.02em;
  min-width: 60px;
  text-align: right;
}

/* When a chain card is followed by its status card, drop its bottom
   corners so the two visually merge into one taller unit. */
.chain-card.is-running { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }

/* Swipe-to-stop feedback (v1.4.5). Applied to the parent .chain-card as
   the user drags horizontally — reveals a red "release to stop" band. */
.chain-card.is-swipe-stop-armed {
  box-shadow: 0 0 0 2px var(--warn) inset;
}
.chain-card.is-swiping {
  transition: none !important;
}

/* ====================================================================
   EDITOR LOCKED BANNER (v1.4)
   ==================================================================== */

.editor-locked-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 16px;
  margin: 0;
  background: rgba(245,176,66,0.10);
  border-bottom: 1px solid var(--accent);
  color: var(--ink);
  font-family: var(--f-body);
  font-size: 13px;
  line-height: 1.4;
}
.editor-locked-text strong { color: var(--accent); font-weight: 700; margin-right: 4px; }
.editor-locked-text { flex: 1; min-width: 0; }
.view-editor[data-locked="true"] .editor-scroll {
  pointer-events: none;
  opacity: 0.55;
}
/* v1.4.7 — carve out the chain name input from the "locked" veneer so
   users can still rename a running chain. The rest of the editor stays
   inert (segments/loops/colors would be unsafe to mutate mid-run). */
.view-editor[data-locked="true"] .editor-name-fields {
  pointer-events: auto;
  opacity: 1;
}
.view-editor[data-locked="true"] .editor-footer { display: none; }

/* ==========================================================================
   RIBBON (library count strip)
   ========================================================================== */

.ribbon {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 18px;
  border-bottom: 1px solid var(--rule);
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.ribbon-mark {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: 16px;
  color: var(--accent);
  text-transform: none;
}
.ribbon-rule { flex: 1; height: 1px; background: var(--rule); }
.ribbon-meta { color: var(--ink-soft); }

/* ==========================================================================
   LIBRARY — chain cards
   ========================================================================== */

.library-scroll {
  flex: 1;
  overflow-y: auto;
  padding: 10px 16px calc(var(--tabbar-h) + 16px + var(--safe-bot));
  -webkit-overflow-scrolling: touch;
}

.chain-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-top: 8px;
  /* v1.4.12 — anchor for the absolutely-positioned swipe underlay. */
  position: relative;
}

/* ====================================================================
   SWIPE-TO-DELETE (v1.4.12)
   ==================================================================== */

/* Red band revealed behind a card as it's dragged left — inserted by JS
   only for the duration of the gesture, sized to the card it backs. */
.swipe-underlay {
  position: absolute;
  left: 0; right: 0;
  border-radius: var(--r-md);
  background: var(--warn);
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding-right: 24px;
  pointer-events: none;
}
.swipe-underlay-icon {
  width: 24px; height: 24px;
  color: #fff;
  opacity: 0.9;
  transition: transform 140ms cubic-bezier(.2,.7,.25,1.4);
}
/* Past the commit threshold the icon pops, mirroring the stock gesture's
   point-of-no-return cue (paired with a haptic tick in JS). */
.swipe-underlay.is-armed .swipe-underlay-icon {
  transform: scale(1.25);
  opacity: 1;
}
/* Referenced-elsewhere rows: neutral band + link icon — nothing red,
   nothing that promises a delete. */
.swipe-underlay.is-blocked {
  background: var(--surface-2);
  border: 1px solid var(--rule);
}
.swipe-underlay.is-blocked .swipe-underlay-icon {
  color: var(--ink-dim);
}

.chain-card {
  position: relative;
  display: grid;
  grid-template-columns: 6px 1fr auto;
  align-items: stretch;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  overflow: hidden;
  cursor: pointer;
  transition: transform 160ms cubic-bezier(.2,.7,.25,1), border-color 160ms, background 160ms;
  box-shadow: var(--sh-soft);
  /* v1.4.12 — vertical panning stays native; horizontal drags belong to
     the swipe gestures (delete on idle rows, stop on running ones), so
     the browser must not turn them into scrolls + pointercancel. */
  touch-action: pan-y;
}
.chain-card:active { transform: scale(0.985); }
.chain-card:hover { border-color: var(--rule-strong); background: var(--surface-2); }

.chain-card-stripe {
  background: var(--c-amber);
  width: 6px;
}

.chain-card-body {
  padding: 14px 14px 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.chain-card-row1 {
  display: flex;
  align-items: baseline;
  gap: 10px;
  min-width: 0;
}

.chain-card-name {
  font-family: var(--f-display);
  font-size: 22px;
  letter-spacing: 0.015em;
  text-transform: uppercase;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1;
  min-width: 0;
  line-height: 1;
}

.chain-card-total {
  font-family: var(--f-mono);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
  letter-spacing: 0.04em;
  white-space: nowrap;
}

.chain-card-segments {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: nowrap;
  overflow: hidden;
  height: 18px;
  margin-top: 2px;
}
.seg-chip {
  height: 4px;
  border-radius: 2px;
  background: var(--accent);
  flex-shrink: 0;
}
.seg-chip.is-sub { background: var(--c-violet); }

.chain-card-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--f-mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.chain-card-meta .dot { width: 3px; height: 3px; border-radius: 50%; background: var(--ink-faint); }

.chain-card-play {
  display: grid;
  place-items: center;
  width: 64px;
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-warm) 100%);
  color: #1A0F00;
  transition: filter 160ms;
}
.chain-card-play:hover { filter: brightness(1.08); }
.chain-card-play svg { width: 24px; height: 24px; }

/* ==========================================================================
   EMPTY STATE
   ========================================================================== */

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 56px 24px;
  gap: 14px;
}

.empty-art {
  position: relative;
  width: 92px; height: 92px;
  display: grid;
  place-items: center;
  margin-bottom: 8px;
}
.empty-art .ring {
  position: absolute;
  inset: 0;
  border: 1px solid var(--rule-strong);
  border-radius: 50%;
  animation: ringPulse 4s ease-in-out infinite;
}
.empty-art .ring:nth-child(2) { inset: 12px; animation-delay: 0.6s; border-color: var(--accent); opacity: 0.5; }
.empty-art .ring:nth-child(3) { inset: 26px; animation-delay: 1.2s; border-color: var(--accent); opacity: 0.8; }
@keyframes ringPulse {
  0%, 100% { transform: scale(1); opacity: 0.4; }
  50%      { transform: scale(1.05); opacity: 0.8; }
}

.empty-title {
  font-family: var(--f-display);
  font-size: 32px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  font-weight: 400;
  color: var(--ink);
}

.empty-body {
  font-family: var(--f-body);
  font-size: 15px;
  color: var(--ink-soft);
  max-width: 320px;
  margin-bottom: 14px;
  line-height: 1.55;
}

/* ==========================================================================
   BOTTOM TABBAR
   ========================================================================== */

.tabbar {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  height: calc(var(--tabbar-h) + var(--safe-bot));
  padding-bottom: var(--safe-bot);
  display: flex;
  align-items: center;
  justify-content: space-around;
  background: rgba(14, 13, 11, 0.92);
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
  border-top: 1px solid var(--rule);
  z-index: 5;
}

.tab {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 10px 16px;
  border-radius: var(--r-sm);
  font-family: var(--f-mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-dim);
  transition: color 160ms;
  flex: 1;
  min-width: 0;
}
.tab.is-active { color: var(--accent); }
.tab:hover { color: var(--ink); }

.tab-fab {
  flex: 0 0 auto;
  width: 56px; height: 56px;
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-warm) 100%);
  color: #1A0F00;
  border-radius: 50%;
  margin-top: -22px;
  box-shadow: 0 8px 18px -4px rgba(245,176,66,0.4), 0 0 0 4px var(--bg);
  transition: transform 200ms cubic-bezier(.2,.7,.25,1);
  padding: 0;
  /* Override flex-direction:column inherited from .tab so the single SVG
     child is centred both axes (the column default of justify-content:
     flex-start was leaving the + glued to the top of the circle). */
  justify-content: center;
  gap: 0;
}
.tab-fab > svg { width: 30px; height: 30px; stroke-width: 2.2; }
.tab-fab:hover  { color: #1A0F00; transform: scale(1.06); }
.tab-fab:active { transform: scale(0.94); }

/* ==========================================================================
   TEMPLATES VIEW
   ========================================================================== */

.templates-scroll {
  flex: 1;
  overflow-y: auto;
  padding: 16px 16px calc(40px + var(--safe-bot));
}

.templates-blurb {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: 15px;
  color: var(--ink-dim);
  margin-bottom: 18px;
  line-height: 1.5;
}

.template-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.template-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px 16px 14px;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  position: relative;
  cursor: pointer;
  transition: border-color 160ms, background 160ms;
}
.template-card:hover { border-color: var(--rule-strong); background: var(--surface-2); }
.template-card:active { transform: scale(0.985); }

.template-card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}
.template-card-title {
  font-family: var(--f-display);
  font-size: 22px;
  letter-spacing: 0.015em;
  text-transform: uppercase;
  font-weight: 400;
  line-height: 1;
}
.template-card-time {
  font-family: var(--f-mono);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
  letter-spacing: 0.04em;
}
.template-card-desc {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: 14px;
  color: var(--ink-soft);
  line-height: 1.5;
}
.template-card-segments {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 4px;
}
.template-pill {
  font-family: var(--f-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 4px 8px;
  border-radius: 4px;
  background: var(--surface-3);
  color: var(--ink-soft);
  border: 1px solid var(--rule);
}

/* ==========================================================================
   EDITOR VIEW
   ========================================================================== */

.editor-scroll {
  flex: 1;
  overflow-y: auto;
  padding: 16px 16px 30px;
}

.editor-name-block {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 6px 0 18px;
  border-bottom: 1px solid var(--rule);
}

.field-label {
  font-family: var(--f-mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

.editor-name-input {
  background: transparent;
  border: 0;
  outline: 0;
  font-family: var(--f-display);
  font-size: 36px;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  color: var(--ink);
  padding: 0;
  width: 100%;
  line-height: 1;
}
.editor-name-input::placeholder { color: var(--ink-faint); }

.editor-color-row {
  display: flex;
  gap: 10px;
  margin-top: 6px;
  flex-wrap: wrap;
}
.color-dot {
  width: 22px; height: 22px;
  border-radius: 50%;
  border: 2px solid transparent;
  cursor: pointer;
  transition: transform 140ms;
}
.color-dot:hover { transform: scale(1.1); }
.color-dot.is-active { border-color: var(--ink); transform: scale(1.1); }

.editor-stats {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 1px;
  background: var(--rule);
  border-radius: var(--r-sm);
  overflow: hidden;
  margin: 16px 0;
  border: 1px solid var(--rule);
}
.stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 12px 8px;
  background: var(--surface);
}
/* v1.4.7 — TOTAL and SEGMENTS are computed from the segment list,
   not editable. Give them a darker background + softer text so users
   don't tap them expecting an input. Loops (with its stepper) keeps
   the regular surface treatment. */
.stat-readonly {
  background: var(--surface-2);
}
.stat-readonly .stat-label { color: var(--ink-faint); }
.stat-readonly .stat-value { color: var(--ink-dim); }
.stat-label {
  font-family: var(--f-mono);
  font-size: 9px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.stat-value {
  font-family: var(--f-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  font-size: 18px;
  color: var(--ink);
  letter-spacing: 0.02em;
}

.stepper {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.stepper-btn {
  width: 22px; height: 22px;
  display: grid; place-items: center;
  background: var(--surface-3);
  border-radius: 50%;
  font-size: 14px;
  color: var(--ink);
  transition: background 140ms;
}
.stepper-btn:hover { background: var(--accent); color: var(--bg); }
.stepper-value { min-width: 14px; text-align: center; }

/* ===== Segment list ===== */

.segment-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
  position: relative;
  margin-bottom: 16px;
}

.segment-row {
  position: relative;
  display: grid;
  /* 5 columns: handle · body · duration-or-loops · voice · remove.
     The voice slot collapses to zero when no SpeechSynthesis is present
     (no voice button appended → empty cell, gap auto-folds via the
     auto column tracks sizing to content). */
  grid-template-columns: 28px 1fr auto auto auto;
  align-items: center;
  gap: 10px;
  padding: 12px 12px 12px 6px;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  transition: border-color 140ms, background 140ms, transform 140ms;
}
.segment-row.is-sub {
  background: linear-gradient(180deg, var(--surface) 0%, var(--surface-2) 100%);
  border-style: dashed;
  border-color: var(--rule-strong);
}
.segment-row.is-dragging {
  opacity: 0.5;
  transform: scale(0.97);
}
.segment-row.is-drop-target { border-color: var(--accent); }

.segment-handle {
  display: grid; place-items: center;
  width: 28px; height: 38px;
  color: var(--ink-faint);
  cursor: grab;
  touch-action: none;
}
.segment-handle:hover { color: var(--ink-dim); }
.segment-handle:active { cursor: grabbing; }

.segment-num {
  font-family: var(--f-mono);
  font-size: 10px;
  color: var(--ink-faint);
  letter-spacing: 0.08em;
  margin-bottom: 2px;
  display: block;
}

.segment-body {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.segment-name-input {
  background: transparent;
  border: 0;
  outline: 0;
  font-family: var(--f-body);
  font-size: 16px;
  font-weight: 600;
  color: var(--ink);
  padding: 0;
  width: 100%;
}
.segment-name-input::placeholder { color: var(--ink-faint); font-weight: 400; }

.segment-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--f-mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.segment-meta .seg-color-btn {
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--accent);
  border: 1px solid rgba(255,255,255,0.06);
  padding: 0;
  cursor: pointer;
  transition: transform 140ms;
}
.segment-meta .seg-color-btn:hover { transform: scale(1.18); }

.segment-duration {
  font-family: var(--f-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  font-size: 20px;
  color: var(--ink);
  letter-spacing: 0.02em;
  padding: 6px 10px;
  border-radius: 8px;
  border: 1px solid var(--rule);
  cursor: pointer;
  transition: border-color 140ms, color 140ms, background 140ms;
  text-align: right;
  /* Enough width to hold "01h 05m 30s" in the display font. Segments
     without hours/minutes still take up the full width, so every row's
     unit letters line up at the right. */
  min-width: 130px;
  white-space: nowrap;
}
.segment-duration:hover { border-color: var(--accent); color: var(--accent); }
/* Three column slots inside .segment-duration. Each slot is a fixed
   width so the "s" / "m" / "h" letters land at the same x-coordinate
   across every row, regardless of which parts are populated. */
.segment-duration .sd-h,
.segment-duration .sd-m,
.segment-duration .sd-s {
  display: inline-block;
  text-align: right;
  min-width: 34px;   /* "00h" fits, "00m" fits, "00s" fits, empty fits */
}
/* Small gap between slots so the "10s" case doesn't hug the border. */
.segment-duration .sd-m,
.segment-duration .sd-s { margin-left: 4px; }

.segment-remove {
  width: 32px; height: 32px;
  display: grid; place-items: center;
  border-radius: 50%;
  color: var(--ink-faint);
  transition: background 140ms, color 140ms;
}
.segment-remove:hover { background: rgba(226,72,58,0.1); color: var(--warn); }

/* Cue-override bell. Used at chain level (editor header) and segment
   level (segment row, left of trash). The accent dot lights up when at
   least one cue at that scope has been explicitly overridden. */
.cue-bell {
  position: relative;
  width: 36px; height: 36px;
  display: grid; place-items: center;
  border-radius: 50%;
  color: var(--ink-dim);
  transition: background 140ms, color 140ms;
  background: transparent;
}
.cue-bell:hover { background: rgba(245,176,66,0.10); color: var(--accent); }
.cue-bell.has-overrides { color: var(--accent); }
.cue-bell-dot {
  position: absolute;
  top: 6px; right: 6px;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid var(--surface);
}

/* Segment-row cue bell sizing — smaller chrome to match the 32px trash. */
.segment-cues {
  width: 32px; height: 32px;
}
.segment-cues .cue-bell-dot { top: 4px; right: 4px; width: 7px; height: 7px; }

/* Chain editor header: name fields on the left, bell on the right. */
.editor-name-row {
  display: flex;
  align-items: center;
  gap: 12px;
}
.editor-name-fields { flex: 1; min-width: 0; }

/* Cue override sheet — one card per cue with a tri-state pill control. */
.cues-sheet-hint {
  font-family: var(--f-serif);
  font-size: 13px;
  font-style: italic;
  color: var(--ink-dim);
  margin: 0 0 12px;
  line-height: 1.4;
}
.cues-list { display: flex; flex-direction: column; gap: 10px; }
.cue-row {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 12px;
  background: var(--surface-2);
  border-radius: var(--r-md);
  border: 1px solid var(--rule);
}
.cue-row.is-nested {
  margin-left: 14px;
  border-left-width: 3px;
  border-left-color: var(--rule-strong);
}
.cue-row-head {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.cue-row-title {
  font-family: var(--f-body);
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
}
.cue-row-hint {
  font-family: var(--f-serif);
  font-size: 12.5px;
  font-style: italic;
  color: var(--ink-dim);
}

/* Tri-state pill: Default / On / Off. Selected segment gets accent. */
.cue-pill {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  background: var(--surface-3);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 3px;
  gap: 2px;
}
.cue-pill button {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--ink-dim);
  font-family: var(--f-body);
  font-size: 13px;
  font-weight: 600;
  padding: 7px 10px;
  border-radius: 999px;
  cursor: pointer;
  transition: background 140ms, color 140ms;
  letter-spacing: 0.01em;
}
.cue-pill button[aria-pressed="true"] {
  background: var(--accent);
  color: var(--bg);
}
.cue-pill button:not([aria-pressed="true"]):hover {
  background: rgba(255,255,255,0.05);
  color: var(--ink);
}
.cue-pill button .pill-default-inherit {
  display: block;
  font-size: 10px;
  font-weight: 400;
  font-family: var(--f-mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  opacity: 0.72;
  margin-top: 1px;
}

/* sub-chain row variant */
.segment-sub {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.segment-sub-name {
  font-family: var(--f-display);
  font-size: 18px;
  letter-spacing: 0.015em;
  text-transform: uppercase;
  color: var(--c-violet);
  line-height: 1;
}
.segment-sub-meta {
  font-family: var(--f-mono);
  font-size: 10px;
  color: var(--ink-dim);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.segment-sub-loops {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--surface-3);
  padding: 4px 8px;
  border-radius: 6px;
  font-family: var(--f-mono);
  font-size: 11px;
  font-weight: 500;
  color: var(--ink);
  border: 1px solid var(--rule);
}
.segment-sub-loops button {
  width: 18px; height: 18px;
  display: grid; place-items: center;
  border-radius: 50%;
  color: var(--ink);
}
.segment-sub-loops button:hover { background: var(--accent); color: var(--bg); }

/* connector lines */
.segment-list::before {
  content: '';
  position: absolute;
  left: 19px;
  top: 12px;
  bottom: 12px;
  width: 1px;
  background: linear-gradient(to bottom,
    transparent 0%, var(--rule-strong) 8px,
    var(--rule-strong) calc(100% - 8px), transparent 100%);
  z-index: -1;
  pointer-events: none;
}

/* Add row */

.add-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-bottom: 16px;
}

.btn-add {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 14px 12px;
  background: var(--surface);
  border: 1px dashed var(--rule-strong);
  border-radius: var(--r-md);
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink);
  transition: border-color 140ms, color 140ms, background 140ms;
}
.btn-add:hover { border-color: var(--accent); color: var(--accent); background: var(--surface-2); }
.btn-add .plus { font-size: 14px; line-height: 1; color: var(--accent); }

.btn-add-ghost { color: var(--c-violet); }
.btn-add-ghost .plus { color: var(--c-violet); }
.btn-add-ghost:hover { border-color: var(--c-violet); color: var(--c-violet); }

.hint {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: 13px;
  color: var(--ink-faint);
  text-align: center;
  padding: 8px 0 4px;
}
/* v1.4.13 — while the duration pointer is up, the tip line says what to
   do rather than listing power-user gestures, and brightens so the two
   read as one instruction. */
.hint.is-pointing { color: var(--accent); font-style: normal; }

/* First-run pointer at the duration control: a breathing amber ring.
   Deliberately an outline pulse rather than a filled highlight — it has
   to read as "look here", not as an already-active state. */
.segment-duration.is-hinted {
  border-color: var(--accent);
  color: var(--accent);
  animation: durationHintPulse 1.9s ease-in-out infinite;
}
@keyframes durationHintPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(245,176,66,0.45); }
  50%      { box-shadow: 0 0 0 8px rgba(245,176,66,0); }
}
/* Respect a reduced-motion preference: keep the amber emphasis, drop
   the animation. */
@media (prefers-reduced-motion: reduce) {
  .segment-duration.is-hinted { animation: none; box-shadow: 0 0 0 2px rgba(245,176,66,0.35); }
}

.editor-footer {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 10px;
  padding: 14px 16px calc(14px + var(--safe-bot));
  border-top: 1px solid var(--rule);
  background: rgba(14, 13, 11, 0.92);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
}

/* ==========================================================================
   BUTTONS
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 18px;
  border-radius: var(--r-sm);
  font-family: var(--f-body);
  font-weight: 600;
  font-size: 14px;
  line-height: 1;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: transform 140ms, background 140ms, color 140ms, border-color 140ms;
  border: 1px solid transparent;
}
.btn:active { transform: scale(0.97); }

.btn-primary {
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-warm) 100%);
  color: #1A0F00;
  font-weight: 700;
  box-shadow: 0 6px 16px -8px rgba(245,176,66,0.6);
}
.btn-primary:hover { filter: brightness(1.06); }

.btn-secondary {
  background: var(--surface-2);
  border-color: var(--rule-strong);
  color: var(--ink);
}
.btn-secondary:hover { background: var(--surface-3); }

.btn-ghost {
  background: transparent;
  color: var(--ink);
  border-color: var(--rule-strong);
}
.btn-ghost:hover { background: var(--surface-2); border-color: var(--accent); color: var(--accent); }

.btn-large { padding: 16px 22px; font-size: 16px; }
.btn-block { display: flex; width: 100%; }
.btn-tiny  { padding: 6px 10px; font-size: 12px; }
.btn-small { padding: 9px 14px; font-size: 13px; }

/* ==========================================================================
   RUN VIEW — cinematic
   ========================================================================== */

.view-run {
  background: var(--bg);
  position: absolute; inset: 0;
  /* v1.4.9 — tell the Android WebView we own horizontal touches.
     Without this, `touch-action: auto` lets the browser interpret a
     horizontal drag as a chrome-style history navigation gesture and
     never dispatch pointer/touch events to our swipe-back handler
     — which is why v1.4.8's "swipe left = back" fix didn't fire on
     device even though the code path was correct. */
  touch-action: pan-y;
}

.run-bg {
  position: absolute; inset: 0;
  background: radial-gradient(ellipse 70% 50% at 50% 25%, rgba(245,176,66,0.16), transparent 65%);
  transition: background 700ms cubic-bezier(.2,.7,.25,1);
  pointer-events: none;
}
.view-run.is-warning .run-bg {
  background: radial-gradient(ellipse 80% 60% at 50% 30%, rgba(226,72,58,0.28), transparent 60%);
}
.view-run.is-paused .run-bg {
  background: radial-gradient(ellipse 70% 50% at 50% 25%, rgba(155,176,137,0.10), transparent 65%);
}

.run-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: calc(14px + var(--safe-top)) 16px 8px;
  position: relative;
  z-index: 2;
}
.run-topbar-left {
  display: flex;
  align-items: center;
  gap: 4px;
}
/* The run-view cue bell borrows .cue-bell for its dot + accent, but keeps
   the 42px .icon-btn box so it balances the back/stop pair opposite it. */
.run-cues { width: 42px; height: 42px; color: var(--ink); }
.run-cues .cue-bell-dot { top: 8px; right: 8px; border-color: var(--bg); }
.run-back svg { opacity: 0.85; }
/* When the user is swiping left-to-go-back, apply a real-time drag so the
   view feels physical. Removed as soon as the swipe ends. */
.view-run.is-swiping .run-main,
.view-run.is-swiping .run-controls,
.view-run.is-swiping .run-topbar,
.view-run.is-swiping .run-chips,
.view-run.is-swiping .run-chain-strip {
  transition: none;
}

.run-chain-meta {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  flex: 1;
}
.run-chain-name {
  font-family: var(--f-display);
  font-size: 16px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
  max-width: 70vw;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  /* v1.4.9 — the element is a <button> now (see index.html). Strip the
     default button chrome so it still LOOKS like a title, but stays
     keyboard-focusable and screen-reader announces "rename chain". */
  background: transparent;
  border: 0;
  padding: 2px 6px;
  border-radius: 6px;
  cursor: pointer;
  transition: background 140ms;
  -webkit-tap-highlight-color: transparent;
}
.run-chain-name:hover,
.run-chain-name:focus-visible { background: var(--surface-2); outline: none; }
/* Inline rename input — swaps in on tap. Same footprint as the button
   so nothing shifts around it. */
.run-chain-name-input {
  font-family: var(--f-display);
  font-size: 16px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
  background: var(--surface-2);
  border: 1px solid var(--accent);
  border-radius: 6px;
  padding: 2px 6px;
  max-width: 70vw;
  text-align: center;
  outline: none;
}
.run-chain-pos {
  font-family: var(--f-mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  color: var(--ink-dim);
}

.run-chain-strip {
  display: flex;
  align-items: center;
  gap: 3px;
  padding: 6px 18px 0;
  height: 18px;
  overflow: hidden;
}
.run-chain-strip-tick {
  height: 4px;
  border-radius: 2px;
  flex: 1 1 0;
  min-width: 4px;
  background: var(--rule);
  transition: background 200ms, height 200ms;
}
.run-chain-strip-tick.is-done    { background: var(--ink-faint); }
.run-chain-strip-tick.is-active  { background: var(--accent); height: 8px; box-shadow: 0 0 8px rgba(245,176,66,0.5); }

.run-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 6px 24px 10px;
  text-align: center;
  position: relative;
  z-index: 1;
  min-height: 0;
}

.run-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 8px;
}
.is-warning .run-eyebrow { color: var(--warn); }
.is-paused .run-eyebrow { color: var(--good); }
.run-segment-divider { color: var(--ink-faint); }
.run-segment-of { color: var(--ink-dim); }

.run-segment-name {
  font-family: var(--f-display);
  font-size: clamp(28px, 7vw, 40px);
  letter-spacing: 0.015em;
  text-transform: uppercase;
  font-weight: 400;
  color: var(--ink);
  margin-bottom: 18px;
  max-width: 100%;
  line-height: 1;
  word-break: break-word;
  /* v1.4.12 — the element is a <button> now (see index.html). Strip the
     default button chrome so it still reads as the big title, but stays
     tappable / keyboard-focusable for the inline rename. */
  background: transparent;
  border: 0;
  padding: 2px 10px;
  border-radius: 8px;
  cursor: pointer;
  transition: background 140ms;
  -webkit-tap-highlight-color: transparent;
}
.run-segment-name:hover,
.run-segment-name:focus-visible { background: var(--surface-2); outline: none; }
/* Inline rename input — swaps in on tap, same typography as the title
   so nothing around it shifts. */
.run-segment-name-input {
  font-family: var(--f-display);
  font-size: clamp(28px, 7vw, 40px);
  letter-spacing: 0.015em;
  text-transform: uppercase;
  font-weight: 400;
  color: var(--ink);
  background: var(--surface-2);
  border: 1px solid var(--accent);
  border-radius: 8px;
  padding: 2px 10px;
  margin-bottom: 18px;
  max-width: 88vw;
  width: min(88vw, 480px);
  line-height: 1;
  text-align: center;
  outline: none;
}

.run-clock-wrap {
  position: relative;
  width: min(78vw, 320px);
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  margin-bottom: 18px;
}

.run-ring {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
}
.run-ring-track {
  fill: none;
  stroke: var(--rule-strong);
  stroke-width: 4;
  opacity: 0.6;
}
.run-ring-fill {
  fill: none;
  stroke: var(--accent);
  stroke-width: 8;
  stroke-linecap: round;
  stroke-dasharray: 578;     /* 2 * PI * 92 ≈ 578 */
  stroke-dashoffset: 578;
  filter: drop-shadow(0 0 12px rgba(245,176,66,0.55));
  transition: stroke 300ms, stroke-dashoffset 90ms linear;
}
.is-warning .run-ring-fill { stroke: var(--warn); filter: drop-shadow(0 0 12px rgba(226,72,58,0.6)); }
.is-paused .run-ring-fill { stroke: var(--good); filter: none; opacity: 0.7; }

.run-clock {
  font-family: var(--f-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  /* v1.4.17 — size the clock from how many characters it has to show.
     The old clamp() was tuned for "MM:SS"; the moment a chain ran past
     an hour the string became "HH:MM:SS" and ran off the screen.

     --clock-chars is set by UI._setClockText whenever the length
     changes. 0.55 is this monospace face's measured per-character
     advance (0.5398em) rounded UP, so the result under-shoots the
     available width rather than overflowing it. That width is the APP
     COLUMN, not the viewport: .app is capped at 560px, so plain 100vw
     would overflow it in a wide window. */
  --clock-chars: 5;
  --clock-gutter: 20px;
  --clock-advance: 0.55;
  font-size: min(
    96px,
    calc((min(100vw, 560px) - 2 * var(--clock-gutter)) / (var(--clock-chars) * var(--clock-advance)))
  );
  letter-spacing: -0.01em;
  color: var(--ink);
  line-height: 1;
  /* Absolutely centred on the ring rather than laid out inside it.
     As a grid item the clock could be WIDER than the 320px ring track,
     and Chrome resolves overflow on a centred grid item with *safe*
     alignment — it falls back to start, so the text spilled off the
     right edge instead of overflowing evenly. Centring on the wrap
     keeps it symmetric at any width; the wrap centre is the column
     centre. NOTE: clockPulse must carry this translate too, since a
     keyframe transform would otherwise replace it. */
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: max-content;
  z-index: 1;
  /* Stay on one line and stay centred even if some future format is
     wider than the formula anticipated. */
  white-space: nowrap;
  text-align: center;
  max-width: calc(min(100vw, 560px) - 2 * var(--clock-gutter));
}
.is-warning .run-clock { color: var(--warn); animation: clockPulse 0.95s ease-in-out infinite; }
/* v1.4.11 — inline prestart: the 3-2-1 renders in the clock itself
   (full-screen overlay reserved for single-chain starts). */
.run-clock.is-prestart { color: var(--accent); animation: clockPulse 0.95s ease-in-out infinite; }

/* ====================================================================
   RING UNTIL DISMISSED (v1.4.13)
   ==================================================================== */

/* While a gate is held the whole view reads as "waiting on you": the
   ring and clock go warn-coloured and pulse, matching the alarm. */
.view-run.is-alarm .run-clock { color: var(--warn); animation: clockPulse 0.95s ease-in-out infinite; }
.view-run.is-alarm .run-ring-fill { stroke: var(--warn); filter: drop-shadow(0 0 14px rgba(226,72,58,0.7)); }

/* Replaces the transport row while ringing — one unmissable target,
   sized like the controls it stands in for so nothing jumps. */
.run-dismiss-bar {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 14px 18px calc(18px + var(--safe-bot));
}
.run-dismiss-label {
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--warn);
}
.run-dismiss-btn {
  min-width: min(70vw, 280px);
  padding: 16px 24px;
  font-size: 16px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  animation: dismissPulse 1.5s ease-in-out infinite;
}
@keyframes dismissPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(226,72,58,0.55); }
  50%      { box-shadow: 0 0 0 14px rgba(226,72,58,0); }
}

/* Two-choice pill (segment-only binary cues like ring-until-dismissed):
   same track, just without the inherited "Default" slot. */
.cue-pill.is-binary { grid-template-columns: 1fr 1fr; }
@keyframes clockPulse {
  /* Includes the centring translate: a transform here REPLACES the
     rule-level one, which would otherwise knock the clock off centre
     for the whole animation. */
  0%, 100% { transform: translate(-50%, -50%) scale(1); }
  50%      { transform: translate(-50%, -50%) scale(1.04); }
}

.run-progress {
  width: min(78vw, 320px);
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 18px;
}
.run-progress-bar {
  height: 3px;
  background: var(--rule);
  border-radius: 2px;
  overflow: hidden;
}
.run-progress-fill {
  height: 100%;
  background: var(--accent);
  width: 0%;
  transition: width 600ms cubic-bezier(.4,0,.2,1);
}
.run-progress-meta {
  display: flex;
  justify-content: space-between;
  font-family: var(--f-mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

.run-next {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--surface);
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
  max-width: 90vw;
}
.run-next-label {
  text-transform: uppercase;
  color: var(--ink-dim);
  letter-spacing: 0.16em;
  font-size: 10px;
}
.run-next-arrow { color: var(--accent); }
.run-next-name {
  text-transform: uppercase;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 38vw;
  letter-spacing: 0.06em;
}
.run-next-dur { color: var(--accent); font-variant-numeric: tabular-nums; }

.run-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 24px;
  padding: 10px 0 calc(28px + var(--safe-bot));
  z-index: 2;
}

.run-ctrl {
  display: grid; place-items: center;
  border-radius: 50%;
  transition: transform 140ms, background 140ms, border-color 140ms;
  color: var(--ink);
}
.run-ctrl:active { transform: scale(0.93); }

.run-ctrl-secondary {
  width: 56px; height: 56px;
  background: var(--surface);
  border: 1px solid var(--rule);
}
.run-ctrl-secondary:hover { border-color: var(--rule-strong); background: var(--surface-2); }

.run-ctrl-play {
  width: 88px; height: 88px;
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-warm) 100%);
  color: #1A0F00;
  box-shadow: 0 8px 28px -10px rgba(245,176,66,0.65), 0 0 0 6px rgba(245,176,66,0.06);
}
.run-ctrl-play:hover { filter: brightness(1.06); }
.is-paused .run-ctrl-play {
  background: linear-gradient(135deg, var(--good) 0%, #87a075 100%);
  box-shadow: 0 8px 28px -10px rgba(155,176,137,0.5);
}

/* Pre-start & complete overlays */

.run-overlay {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  background: rgba(14, 13, 11, 0.92);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  z-index: 10;
  animation: viewFade 260ms ease-out;
}

/* v1.4.5: prestart overlay leaves the topbar area uncovered so the
   user can tap < to go back to the library (letting the chain start
   silently in the background) or X to abort the launch. The completion
   overlay still covers the full run view — nothing time-critical about
   its top-of-view controls. */
.run-overlay#run-prestart {
  top: calc(58px + var(--safe-top));
  border-top: 1px solid var(--rule);
}

.run-overlay-text {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  text-align: center;
  padding: 20px;
}

.run-overlay-eyebrow {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: 18px;
  color: var(--accent);
}

.run-overlay-num {
  font-family: var(--f-display);
  font-size: clamp(140px, 40vw, 240px);
  line-height: 1;
  letter-spacing: 0;
  color: var(--ink);
  animation: prestartPop 1s cubic-bezier(.2,.7,.25,1);
}
@keyframes prestartPop {
  from { transform: scale(0.6); opacity: 0; }
  to   { transform: scale(1);   opacity: 1; }
}

.run-overlay-title {
  font-family: var(--f-display);
  font-size: 56px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  font-weight: 400;
  color: var(--ink);
  margin: 4px 0 18px;
}

.run-overlay-stats {
  display: flex;
  gap: 36px;
  margin-bottom: 22px;
}
.run-overlay-stats > div {
  display: flex;
  flex-direction: column;
  gap: 2px;
  align-items: center;
}
.ov-num {
  font-family: var(--f-mono);
  font-variant-numeric: tabular-nums;
  font-size: 28px;
  font-weight: 500;
  color: var(--accent);
}
.ov-lbl {
  font-family: var(--f-mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

.run-overlay-actions {
  display: flex;
  gap: 10px;
}

/* ==========================================================================
   SHEETS (modals)
   ========================================================================== */

.sheet {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  animation: sheetFade 200ms ease;
}
@keyframes sheetFade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.sheet-scrim {
  position: absolute; inset: 0;
  background: rgba(0,0,0,0.5);
  backdrop-filter: blur(4px);
}

.sheet-card {
  position: relative;
  width: 100%;
  max-width: 560px;
  background: var(--surface);
  border-top-left-radius: var(--r-xl);
  border-top-right-radius: var(--r-xl);
  border: 1px solid var(--rule);
  border-bottom: 0;
  padding: 14px 18px calc(20px + var(--safe-bot));
  max-height: 88vh;
  overflow-y: auto;
  animation: sheetSlide 280ms cubic-bezier(.2,.7,.25,1);
  box-shadow: var(--sh-card);
}
@keyframes sheetSlide {
  from { transform: translateY(100%); }
  to   { transform: translateY(0); }
}

.sheet-card-tall { min-height: 50vh; }

.sheet-handle {
  width: 40px; height: 4px;
  background: var(--rule-strong);
  border-radius: 2px;
  margin: 0 auto 12px;
}

.sheet-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--rule);
  margin-bottom: 16px;
}

.sheet-title {
  font-family: var(--f-display);
  font-size: 24px;
  letter-spacing: 0.015em;
  text-transform: uppercase;
  font-weight: 400;
}

.sheet-body {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.setting-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 6px 0;
  cursor: pointer;
}
.setting-row span {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 1;
  min-width: 0;
}
.setting-row strong {
  font-family: var(--f-body);
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
}
.setting-row small {
  font-family: var(--f-serif);
  font-size: 13px;
  font-style: italic;
  color: var(--ink-dim);
  line-height: 1.4;
}

/* iOS-style toggle */
.setting-row input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 44px; height: 26px;
  border-radius: 13px;
  background: var(--surface-3);
  border: 1px solid var(--rule);
  position: relative;
  cursor: pointer;
  transition: background 200ms;
  flex-shrink: 0;
}
.setting-row input[type="checkbox"]::after {
  content: '';
  position: absolute;
  top: 2px; left: 2px;
  width: 20px; height: 20px;
  border-radius: 50%;
  background: var(--ink-soft);
  transition: transform 200ms cubic-bezier(.2,.7,.25,1), background 200ms;
}
.setting-row input[type="checkbox"]:checked {
  background: var(--accent);
}
.setting-row input[type="checkbox"]:checked::after {
  transform: translateX(18px);
  background: var(--bg);
}

.setting-rule { border: 0; border-top: 1px solid var(--rule); margin: 4px 0; }

/* Settings section heading — separates Defaults from Other. */
.setting-section-head {
  font-family: var(--f-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 18px 0 4px;
  font-weight: 600;
}
.setting-section-head:first-child { margin-top: 0; }
.setting-section-hint {
  font-family: var(--f-serif);
  font-size: 12.5px;
  font-style: italic;
  color: var(--ink-dim);
  margin: 0 0 6px;
  line-height: 1.4;
}
/* Sub-row indent for settings nested under a parent (e.g. Final 3
   seconds tick under Sound cues). The bell rule on the left edge gives
   a clean "branches from above" feel without an actual tree-view UI. */
.setting-row-sub {
  padding-left: 14px;
  border-left: 1px solid var(--rule);
  margin-left: 4px;
}
/* Stack the head + pill control vertically instead of the default
   label-on-the-left / toggle-on-the-right two-column layout. Used for
   settings that need a 3-way pill control. */
.setting-row-column {
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  cursor: default;
}
.setting-row-column .setting-row-head { display: block; }

/* Native bridge panel (only visible when running inside Capacitor) */
.native-panel {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px;
  background: var(--surface-2);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  margin: 4px 0 8px;
}
.native-panel-head {
  display: flex;
  align-items: center;
  gap: 10px;
}
.native-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--ink-faint);
  flex-shrink: 0;
  box-shadow: 0 0 0 0 transparent;
  transition: background 200ms, box-shadow 200ms;
}
.native-dot.is-on { background: var(--good); box-shadow: 0 0 8px rgba(155,176,137,0.6); }
.native-dot.is-warn { background: var(--warn); }
.native-panel-head strong {
  flex: 1;
  font-family: var(--f-body);
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
}
.native-panel .badge {
  font-size: 9px;
  letter-spacing: 0.14em;
  padding: 4px 8px;
}
.native-panel-body {
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
  line-height: 1.5;
}
.native-panel-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.native-panel-hint {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: 12px;
  color: var(--ink-dim);
  line-height: 1.5;
}
.native-panel-hint em { color: var(--accent); font-style: italic; }

.setting-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.setting-credit {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: 13px;
  color: var(--ink-dim);
  text-align: center;
  padding: 8px 0 4px;
  line-height: 1.5;
}
.setting-version {
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
  text-align: center;
  padding: 6px 0 0;
  margin: 0;
}
.setting-version .setting-version-update {
  color: var(--accent);
  font-weight: 500;
  cursor: pointer;
  text-decoration: none;
  margin-left: 8px;
}
.setting-version .setting-version-update:hover { text-decoration: underline; }

/* ====================================================================
   UPDATE-AVAILABLE MODAL (v1.4.4)
   ==================================================================== */

.update-modal {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  place-items: center;
  padding: 20px;
  animation: viewFade 220ms ease-out;
}
.update-modal[hidden] { display: none; }
.update-modal-scrim {
  position: absolute;
  inset: 0;
  background: rgba(6, 5, 4, 0.75);
  backdrop-filter: blur(3px);
}
.update-modal-card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--rule-strong);
  border-radius: var(--r-lg);
  padding: 26px 22px 22px;
  max-width: 380px;
  width: 100%;
  text-align: center;
  box-shadow: 0 30px 60px -20px rgba(0,0,0,0.7);
}
.update-modal-icon {
  width: 56px; height: 56px;
  margin: 0 auto 12px;
  border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(245,176,66,0.10);
  border: 1px solid rgba(245,176,66,0.35);
  color: var(--accent);
}
.update-modal-title {
  font-family: var(--f-display);
  font-size: 24px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ink);
  margin: 0 0 8px;
}
.update-modal-body {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-soft);
  margin: 0 0 14px;
}
.update-modal-versions {
  font-family: var(--f-mono);
  font-size: 13px;
  color: var(--ink);
  letter-spacing: 0.06em;
  margin: 0 0 18px;
}
.update-modal-versions .from { color: var(--ink-dim); }
.update-modal-versions .arrow { color: var(--accent); margin: 0 8px; }
.update-modal-versions .to { color: var(--accent); font-weight: 600; }
.update-modal-actions {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-bottom: 6px;
}
.update-modal-hint {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: 12px;
  color: var(--ink-dim);
  margin: 8px 0 0;
  line-height: 1.5;
}

/* Action rows */
.action-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 4px;
  text-align: left;
  border-radius: var(--r-sm);
  transition: background 140ms;
  width: 100%;
}
.action-row:hover { background: var(--surface-2); }
.action-row svg { color: var(--ink); flex-shrink: 0; }
.action-row span {
  display: flex;
  flex-direction: column;
  gap: 3px;
  flex: 1;
  min-width: 0;
}
.action-row strong {
  font-family: var(--f-body);
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
}
.action-row small {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: 13px;
  color: var(--ink-dim);
  line-height: 1.4;
}
.action-row-danger { color: var(--warn); }
.action-row-danger strong { color: var(--warn); }
.action-row-danger svg { color: var(--warn); }
.action-row-danger:hover { background: rgba(226, 72, 58, 0.08); }

/* Picker list */
.picker-blurb {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: 14px;
  color: var(--ink-soft);
  margin-bottom: 8px;
  line-height: 1.5;
}
.picker-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.picker-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 14px;
  background: var(--surface-2);
  border: 1px solid var(--rule);
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: border-color 140ms, background 140ms;
}
.picker-item:hover { border-color: var(--accent); background: var(--surface-3); }
.picker-item-name {
  font-family: var(--f-display);
  font-size: 18px;
  letter-spacing: 0.015em;
  text-transform: uppercase;
}
.picker-item-meta {
  font-family: var(--f-mono);
  font-size: 11px;
  color: var(--ink-dim);
  letter-spacing: 0.06em;
}

/* ===== Duration picker ===== */
/* v1.4.7 — Pixel-Clock-style numpad. Big display + on-screen 3×4
   digit pad. No system keyboard, no letters. Digits shift left from
   the seconds-ones slot on each keypress. */

.dpick-display {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 2px;
  padding: 16px 0 6px;
  font-family: var(--f-mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  user-select: none;
  -webkit-user-select: none;
}
.dpick-part {
  display: inline-flex;
  align-items: baseline;
  gap: 3px;
  padding: 0 6px;
}
.dpick-num {
  font-size: 44px;
  font-weight: 500;
  line-height: 1;
  color: var(--ink);
  transition: color 140ms;
}
.dpick-suf {
  font-size: 20px;
  font-weight: 500;
  color: var(--ink-dim);
}
/* Zero parts dim slightly so the non-zero portion pops. Populated
   parts stay full-brightness. */
.dpick-part.is-zero .dpick-num,
.dpick-part.is-zero .dpick-suf {
  color: var(--ink-faint);
}
/* Highlight the active-cursor slot (rightmost non-zero slot). Purely
   cosmetic — helps the user see where the next digit will land. */
.dpick-part.is-cursor .dpick-num { color: var(--accent); }

.dpick-quick {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  padding: 10px 0 14px;
  justify-content: center;
}

.dpick-pad {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  padding: 4px 0 14px;
}
.dpick-key {
  display: grid;
  place-items: center;
  height: 54px;
  background: var(--surface-2);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  font-family: var(--f-mono);
  font-variant-numeric: tabular-nums;
  font-size: 26px;
  font-weight: 500;
  color: var(--ink);
  cursor: pointer;
  transition: background 100ms, border-color 100ms, transform 80ms;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  -webkit-user-select: none;
}
.dpick-key:hover  { background: var(--surface-3); border-color: var(--rule-strong); }
.dpick-key:active { background: var(--surface-3); transform: scale(0.96); }
.dpick-key-back svg { color: var(--ink-dim); }
.dpick-key-back:hover svg { color: var(--warn); }
.dpick-key.is-disabled,
.dpick-key:disabled {
  color: var(--ink-faint);
  cursor: not-allowed;
  opacity: 0.5;
}

.dpick-quick {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  padding: 12px 0 18px;
  justify-content: center;
}
.chip {
  padding: 8px 14px;
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--rule);
  font-family: var(--f-mono);
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-soft);
  transition: border-color 140ms, color 140ms, background 140ms;
}
.chip:hover { border-color: var(--accent); color: var(--accent); background: var(--surface-3); }

/* ==========================================================================
   TOAST
   ========================================================================== */

.toast-stack {
  position: fixed;
  bottom: calc(80px + var(--safe-bot));
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: 8px;
  z-index: 100;
  pointer-events: none;
  width: max-content;
  max-width: 90vw;
}

.toast {
  background: rgba(34, 30, 25, 0.96);
  border: 1px solid var(--rule-strong);
  color: var(--ink);
  padding: 12px 18px;
  border-radius: 999px;
  font-family: var(--f-body);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.01em;
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  pointer-events: auto;
  animation: toastIn 240ms cubic-bezier(.2,.7,.25,1);
  box-shadow: var(--sh-card);
  display: flex;
  align-items: center;
  gap: 8px;
}
.toast.is-out { animation: toastOut 240ms ease-in forwards; }
.toast .t-mark {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--accent);
}
.toast.is-warn .t-mark { background: var(--warn); }
.toast.is-good .t-mark { background: var(--good); }
/* v1.4.12 — snackbar variant with an action button (Undo, etc.). */
.toast .t-msg {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.toast.has-action { max-width: 92vw; }
/* Wrapping variant for longer notices (e.g. "used by A, B, C +2 more"):
   the message breaks across lines instead of ellipsis-clipping, and the
   pill radius relaxes so multi-line doesn't look swollen. */
.toast.has-action.is-wrap { border-radius: 18px; }
.toast.has-action.is-wrap .t-msg {
  white-space: normal;
  overflow-wrap: anywhere;
  line-height: 1.45;
  text-align: left;
}
.toast-action-btn {
  flex-shrink: 0;
  margin-left: 4px;
  padding: 4px 10px;
  border-radius: 999px;
  border: none;
  background: transparent;
  color: var(--accent);
  font-family: var(--f-mono);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
}
.toast-action-btn:active { background: rgba(245,176,66,0.15); }
@keyframes toastIn {
  from { opacity: 0; transform: translateY(8px) scale(0.96); }
  to   { opacity: 1; transform: translateY(0)    scale(1); }
}
@keyframes toastOut {
  from { opacity: 1; transform: translateY(0); }
  to   { opacity: 0; transform: translateY(-8px); }
}

/* ==========================================================================
   INSTALL HINT
   ========================================================================== */

.install-hint {
  position: fixed;
  bottom: calc(80px + var(--safe-bot));
  left: 16px; right: 16px;
  max-width: 528px;
  margin: 0 auto;
  padding: 12px 16px;
  background: rgba(34, 30, 25, 0.96);
  border: 1px solid var(--rule-strong);
  border-radius: var(--r-md);
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: var(--ink);
  backdrop-filter: blur(14px);
  z-index: 40;
  box-shadow: var(--sh-card);
  animation: toastIn 300ms cubic-bezier(.2,.7,.25,1);
}
.install-hint em { font-family: var(--f-serif); color: var(--ink-dim); }
.install-hint span { flex: 1; line-height: 1.4; }
.install-close {
  width: 28px; height: 28px;
  display: grid; place-items: center;
  font-size: 18px;
  color: var(--ink-dim);
  border-radius: 50%;
}

/* ==========================================================================
   SMALL TWEAKS / a11y
   ========================================================================== */

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

button:focus-visible,
input:focus-visible,
.color-dot:focus-visible,
.tab:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* small screens: reduce sizes a touch */
@media (max-width: 360px) {
  .wordmark { font-size: 26px; }
  .editor-name-input { font-size: 30px; }
  .empty-title { font-size: 26px; }
}

/* large screens: cap and frame */
@media (min-width: 720px) {
  body {
    background-image:
      radial-gradient(ellipse 80% 50% at 50% -10%, rgba(245,176,66,0.05), transparent 60%),
      radial-gradient(ellipse 60% 40% at 100% 100%, rgba(125,90,40,0.04), transparent 70%);
  }
}

/* ====================================================================
   FEEDBACK PROMPT (v1.4.16)
   ==================================================================== */

/* Short sheet — one question, two answers, no scroll. */
.sheet-card-compact { padding-bottom: calc(18px + var(--safe-bot)); }
.feedback-body {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: 14px;
  color: var(--ink-soft);
  padding: 0 18px 18px;
  text-align: center;
}
/* Equal weight either way. The negative answer is not hidden or made
   harder to reach — that asymmetry is exactly what review gating is. */
.feedback-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  padding: 0 18px 6px;
}
.feedback-actions .btn { width: 100%; }
