/* Brew timeline — component + scene styles, ported from public/brew-timeline-mockups.html
   and scoped under .brew-timeline. Scene tokens map to the app theme where it defines
   them (--color-*), with the mock's warm-editorial hex as fallback. */
.brew-timeline{
  --bg:        var(--color-bg, #f5f1e8);
  --surface:   var(--color-surface, #ffffff);
  --surface2:  var(--color-surface-2, #efe9d7);
  --border:    var(--color-border, #e6dfcc);
  --ink:       var(--color-ink, #2f1f19);
  --ink-soft:  var(--color-ink-soft, #6e5d54);
  --accent:    var(--color-accent, #d97757);
  --accent-2:  var(--color-accent-2, #c25a38);
  /* scene-only palette (no app equivalent) */
  --coffee:#8a5a33; --coffee-dark:#4e2f1c; --blond:#d9a05e; --water:#7fa8b8;
  --milk:#e3cba4; --foam:#f4ecdc; --chocolate:#3a2313;
  /* The scale's LCD: literal, not theme-aliased. --ink/--bg flip in .dark
     (see application.css), which would invert this into a white slab on a
     dark card. A real scale's display doesn't relight itself for the room —
     it's always a dark plate with warm-lit digits. */
  --lcd-bg:#20241f; --lcd-fg:#f2c879;
  --bt-shadow:0 1px 2px rgba(47,31,25,.05), 0 8px 24px rgba(47,31,25,.07);
  color:var(--ink);
}

/* ── Overview strip: every step's scene looping at a glance ── */
.brew-timeline .bt-overview{display:grid;grid-template-columns:repeat(var(--ov-cols,4),minmax(0,1fr));
  gap:16px 28px;margin-bottom:8px;list-style:none;padding:0}
.brew-timeline .bt-ov-tile{margin:0;min-width:0;position:relative}
.brew-timeline .bt-ov-btn{display:block;width:100%;text-align:left;background:none;border:0;padding:0;
  cursor:pointer;color:inherit;font:inherit}
.brew-timeline .bt-ov-btn:hover .bt-ov-scene{border-color:var(--accent)}
.brew-timeline .bt-ov-btn:hover .bt-ov-cap{color:var(--accent)}
/* the connector lives in the column gap; the last tile of a row has none */
.brew-timeline .bt-ov-tile:not(.is-row-end):not(:last-child)::after{
  content:"";position:absolute;right:-22px;top:calc(50% - 14px);width:16px;
  border-top:1px dashed var(--border)}
@media (max-width:640px){
  .brew-timeline .bt-overview{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px 20px}
  .brew-timeline .bt-ov-tile::after{display:none}
}
.brew-timeline .bt-ov-scene{display:block;position:relative;aspect-ratio:440/300;background:var(--surface2);border:1px dashed var(--border);border-radius:6px;overflow:hidden}
.brew-timeline .bt-ov-cap{display:flex;align-items:center;gap:7px;margin-top:7px;font:600 12.5px/1.2 "Inter";color:var(--ink)}
.brew-timeline .bt-ov-n{display:grid;place-items:center;width:18px;height:18px;border-radius:999px;background:var(--accent);color:#fff;font:700 10px/1 "JetBrains Mono",monospace;flex:none}

/* ── "Behind every step": animation + the why, one row per step ── */
.brew-timeline .bt-notes{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:18px}
.brew-timeline .bt-note{display:grid;grid-template-columns:190px 1fr;gap:18px;align-items:center}
.brew-timeline .bt-note-scene{flex:none}
.brew-timeline .bt-note-body{min-width:0}
.brew-timeline .bt-note-title{display:flex;align-items:center;gap:8px;margin:0 0 6px;
  font-family:"Source Serif 4",serif;font-weight:700;font-size:17px;color:var(--ink)}
.brew-timeline .bt-note-text{margin:0;color:var(--ink-soft);font-size:14.5px;line-height:1.6;max-width:62ch}
@media (max-width:640px){
  .brew-timeline .bt-note{grid-template-columns:1fr;gap:10px}
  .brew-timeline .bt-note-scene{max-width:260px}
}

/* ── Summary tiles + grinder select ── */
.brew-timeline .bt-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:10px;margin-bottom:18px}
.brew-timeline .tile{background:var(--surface);border:1px dashed var(--border);border-radius:6px;padding:12px 14px;box-shadow:var(--bt-shadow)}
.brew-timeline .tile .lbl{font:600 10px/1 "JetBrains Mono",monospace;letter-spacing:.18em;text-transform:uppercase;color:var(--ink-soft)}
.brew-timeline .tile .val{font-family:"Source Serif 4",serif;font-weight:600;font-size:21px;margin-top:5px}
.brew-timeline .tile .clk{font:600 11px/1 "JetBrains Mono",monospace;color:var(--accent);margin-top:4px;min-height:11px}
.brew-timeline .grind-sel{appearance:none;margin-top:5px;width:100%;max-width:190px;background:var(--surface);
  border:1px dashed var(--border);border-radius:4px;font:500 12.5px "Inter";color:var(--ink);padding:6px 8px;cursor:pointer}
.brew-timeline .grind-sel:hover{border-color:var(--accent)}

/* ── Card (blueprint ruler on paper) ── */
.brew-timeline.card{background:var(--surface);border:1px dashed var(--border);border-radius:8px;box-shadow:var(--bt-shadow);
  padding:clamp(14px,2.5vw,24px);
  background-image:linear-gradient(rgba(47,31,25,.05) 1px,transparent 1px),linear-gradient(90deg,rgba(47,31,25,.05) 1px,transparent 1px);
  background-size:20px 20px}
.brew-timeline .card-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin-bottom:14px}
.brew-timeline .card-head h2{font:400 19px/1 "JetBrains Mono",monospace;letter-spacing:.06em;color:var(--ink);margin:0}
.brew-timeline .card-head .hint{font:400 11.5px "JetBrains Mono",monospace;color:var(--ink-soft)}

/* ── Timeline bar ── */
.brew-timeline .tl-bar{position:relative;height:64px;margin-top:24px;border:1.5px dashed rgba(47,31,25,.6);background:var(--surface)}
.brew-timeline .tl-seg{position:absolute;top:0;bottom:0;border-right:1px dashed rgba(47,31,25,.35);pointer-events:none;overflow:hidden}
.brew-timeline .tl-seg:last-of-type{border-right:0}
.brew-timeline .tl-hatch{position:absolute;inset:0;width:0%;background:repeating-linear-gradient(45deg,rgba(47,31,25,.22) 0 2px,transparent 2px 7px)}
.brew-timeline .tl-seg.now .tl-hatch{background:repeating-linear-gradient(45deg,rgba(217,119,87,.50) 0 2px,transparent 2px 7px)}
.brew-timeline .tl-seglbl{position:absolute;top:7px;left:9px;font:400 11px/1 "JetBrains Mono",monospace;letter-spacing:.16em;
  text-transform:uppercase;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:calc(100% - 16px)}
.brew-timeline .tl-seg.now .tl-seglbl{color:var(--accent-2)}
.brew-timeline .tl-cursor{position:absolute;top:-10px;bottom:-10px;left:0%;width:2px;background:var(--accent);pointer-events:none;z-index:3}
.brew-timeline .tl-cursor::after{content:"";position:absolute;top:-1px;left:-4px;width:10px;height:10px;border-radius:50%;background:var(--accent)}
.brew-timeline .tl-cursor .tag{position:absolute;top:-25px;left:50%;transform:translateX(-50%);background:var(--accent);color:#fff;
  font:700 10px/1 "JetBrains Mono",monospace;padding:3px 7px;border-radius:2px;white-space:nowrap;font-variant-numeric:tabular-nums}
.brew-timeline .tl-ticks{position:relative;height:18px;margin-top:8px}
.brew-timeline .tl-ticks span{position:absolute;transform:translateX(-50%);font:400 10.5px/1 "JetBrains Mono",monospace;color:var(--ink-soft)}
.brew-timeline .tl-ticks span::before{content:"";position:absolute;left:50%;top:-6px;width:1px;height:5px;background:rgba(47,31,25,.35)}
.brew-timeline .tl-ticks span.minor::before{height:3px;top:-4px}

/* ── Stage ── */
.brew-timeline .stage{display:grid;grid-template-columns:1fr 2fr;gap:clamp(14px,2.5vw,26px);align-items:center;
  margin-top:16px;padding-top:16px;border-top:1px dashed rgba(47,31,25,.12)}
.brew-timeline .stage-visual{position:relative;aspect-ratio:440/300;background:var(--surface2);border:1px dashed var(--border);border-radius:6px;overflow:hidden}
.brew-timeline .scene{position:absolute;inset:0;width:100%;height:100%;opacity:0;visibility:hidden;transition:opacity .28s ease}
.brew-timeline .scene.is-active{opacity:1;visibility:visible}
.brew-timeline .stage-side{display:flex;flex-direction:column;justify-content:center;min-width:0}
.brew-timeline .step-kicker{font:600 11px/1 "JetBrains Mono",monospace;letter-spacing:.22em;text-transform:uppercase;color:var(--accent)}
.brew-timeline .clock{font:700 clamp(30px,4vw,42px)/1.05 "JetBrains Mono",monospace;font-variant-numeric:tabular-nums;margin:10px 0 2px}
.brew-timeline .clock small{font-size:.5em;color:var(--ink-soft);font-weight:600}
.brew-timeline .clock-cap{font:600 10px/1 "JetBrains Mono",monospace;letter-spacing:.18em;text-transform:uppercase;color:var(--ink-soft);opacity:.75}
.brew-timeline .step-name{font-family:"Source Serif 4",serif;font-weight:700;font-size:clamp(20px,2.4vw,26px);margin:12px 0 4px}
.brew-timeline .step-text{color:var(--ink-soft);font-size:14px;max-width:34ch}
.brew-timeline .step-progress{height:4px;background:var(--surface2);border-radius:99px;margin-top:16px;overflow:hidden}
.brew-timeline .step-progress i{display:block;height:100%;width:0%;background:var(--accent);border-radius:99px}

/* ── The scale's readout, below its weighing surface ── */
.brew-timeline .stage-surface{min-width:0}
.brew-timeline .bt-scale{margin-top:10px;border:1px dashed var(--border);border-radius:6px;
  background:var(--surface);padding:8px;transition:opacity .25s ease}
.brew-timeline .bt-scale.is-off{opacity:.45}
.brew-timeline .bt-scale-lcd{display:grid;grid-template-columns:repeat(3,1fr);gap:2px;
  background:var(--lcd-bg);border-radius:4px;padding:8px 6px}
.brew-timeline .bt-scale-field{display:flex;flex-direction:column;align-items:center;gap:3px;min-width:0}
.brew-timeline .bt-scale-num{font:700 17px/1 "JetBrains Mono",monospace;font-variant-numeric:tabular-nums;
  color:var(--lcd-fg);white-space:nowrap}
.brew-timeline .bt-scale-lbl{font:600 8px/1 "JetBrains Mono",monospace;letter-spacing:.16em;
  text-transform:uppercase;color:var(--lcd-fg);opacity:.55}
.brew-timeline .bt-scale-ratio{margin-top:6px;text-align:center;
  font:600 12px/1 "JetBrains Mono",monospace;font-variant-numeric:tabular-nums;color:var(--ink-soft)}
@media (max-width:640px){
  .brew-timeline .bt-scale-num{font-size:15px}
}

/* ── Controls ── */
.brew-timeline .controls{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:16px}
.brew-timeline .bt-btn{appearance:none;cursor:pointer;font:600 13.5px/1 "Inter";border-radius:999px;padding:11px 20px;transition:all .15s;border:1px dashed transparent;display:inline-flex;align-items:center;gap:7px}
.brew-timeline .bt-btn svg{width:14px;height:14px;flex:none}
.brew-timeline .bt-btn-primary{background:var(--ink);color:var(--bg)}
.brew-timeline .bt-btn-primary:hover{background:var(--accent-2)}
.brew-timeline .bt-btn-ghost{background:var(--surface);border-color:var(--border);color:var(--ink)}
.brew-timeline .bt-btn-ghost:hover{border-color:var(--accent);color:var(--accent)}
.brew-timeline .keys{margin-top:22px;font:500 12px/1.8 "JetBrains Mono",monospace;color:var(--ink-soft)}
.brew-timeline .keys b{color:var(--ink);border:1px dashed var(--border);border-radius:3px;padding:1px 7px;background:var(--surface);font-weight:600}

/* ── SVG scene shared ── */
.brew-timeline .scene .ln{stroke:var(--ink);stroke-width:2.5;fill:none;stroke-linecap:round;stroke-linejoin:round}
.brew-timeline .scene .lbl-svg{font:600 10px/1 "JetBrains Mono",monospace;letter-spacing:.14em;text-transform:uppercase;fill:var(--ink-soft)}
.brew-timeline .scene .num-svg{font:700 26px/1 "JetBrains Mono",monospace;fill:var(--ink);font-variant-numeric:tabular-nums}
.brew-timeline .scene .cap-svg{font:500 11px/1 "Inter";fill:var(--ink-soft)}
.brew-timeline .scene:not(.is-active) .ambient{animation-play-state:paused}
.brew-timeline .spin{transform-box:fill-box;transform-origin:center;animation:bt-spin 1.1s linear infinite}
.brew-timeline .spin-slow{transform-box:fill-box;transform-origin:center;animation:bt-spin 5s linear infinite}
.brew-timeline .flow{stroke-dasharray:7 6;animation:bt-flowdash .45s linear infinite}
.brew-timeline .grain{animation:bt-fall .75s linear infinite}
.brew-timeline .pulse{transform-box:fill-box;transform-origin:center;animation:bt-pulse 1.6s ease-out infinite}
.brew-timeline .settle{animation:bt-settle .5s ease-out}
.brew-timeline .steam{animation:bt-steam 2.2s ease-in-out infinite}
.brew-timeline .orbit{animation:bt-orbit 2.4s ease-in-out infinite}
@keyframes bt-orbit{0%{transform:translate(0,-2px)}25%{transform:translate(8px,1px)}50%{transform:translate(0,4px)}75%{transform:translate(-8px,1px)}100%{transform:translate(0,-2px)}}
@keyframes bt-spin{to{transform:rotate(360deg)}}
@keyframes bt-flowdash{to{stroke-dashoffset:-24}}
@keyframes bt-fall{0%{transform:translateY(-4px);opacity:0}18%{opacity:1}88%{opacity:1}100%{transform:translateY(44px);opacity:0}}
@keyframes bt-pulse{0%{transform:scale(.92);opacity:.75}100%{transform:scale(1.18);opacity:0}}
@keyframes bt-settle{0%{transform:translateY(0)}35%{transform:translateY(1.6px)}70%{transform:translateY(-.6px)}100%{transform:translateY(0)}}
@keyframes bt-steam{0%{transform:translateY(5px);opacity:0}30%{opacity:.65}100%{transform:translateY(-16px);opacity:0}}

@media (prefers-reduced-motion:reduce){
  .brew-timeline .ambient,.brew-timeline .grain,.brew-timeline .flow,.brew-timeline .spin,
  .brew-timeline .spin-slow,.brew-timeline .orbit,.brew-timeline .pulse,.brew-timeline .settle,.brew-timeline .steam{animation:none !important}
  .brew-timeline .scene{transition:none}
}

/* the ruler, legible again: each segment named and sized to its step's real
   duration, so you can see the shape of the brew and where you are in it. The
   8px version was tidier and told you nothing. Deliberately placed ahead of
   the Responsive section below: media queries add no specificity, so an
   equal-specificity override declared later in the file wins the cascade tie
   — above this point, this rule would always win instead, regardless of
   viewport, silently defeating every mobile override that touches it. */
/* The ruler, in two parts. The track is thin and exactly proportional — every
   step's real duration and nothing written on it — and the names sit below it
   as chips that wrap onto as many lines as they need. Keeping the two apart is
   what lets every name show in full: no clipping, no shortening, no sideways
   scrolling at any width. Both halves seek, and both show where you are. */
.brew-timeline .tl-strip{margin-bottom:12px}
/* The phase legend: what each part of the brew is and how long it runs. A
   swatch carries the phase's colour, matching its band on the track below. */
.brew-timeline .tl-phases{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 16px;margin-bottom:6px}
.brew-timeline .tl-phase{display:inline-flex;align-items:baseline;gap:5px;white-space:nowrap;
  font:600 9.5px/1.3 "JetBrains Mono",monospace;letter-spacing:.1em;text-transform:uppercase}
.brew-timeline .tl-phase::before{content:"";align-self:center;width:14px;height:5px;border-radius:2px;
  background:currentColor;opacity:.45}
.brew-timeline .tl-phase b{font-weight:600;opacity:.85}
.brew-timeline .tl-phase i{font-style:normal;font-variant-numeric:tabular-nums;opacity:.65}
.brew-timeline .tl-phase.g-prep{color:var(--ink-soft)}
.brew-timeline .tl-phase.g-brew{color:var(--accent-2)}
.brew-timeline .tl-phase.g-milk{color:#8a6a41}
.brew-timeline .tl-phase.g-serve{color:var(--coffee)}
.brew-timeline .tl-track{position:relative;height:9px;border-radius:3px;
  background:var(--surface2);border:1px dashed var(--border)}
.brew-timeline .tl-strip .tl-seg{position:absolute;top:0;bottom:0;overflow:hidden;
  border-right:1px dashed var(--border);pointer-events:none}
.brew-timeline .tl-strip .tl-seg:last-of-type{border-right:0}
/* elapsed: a quiet tint, warming to the accent on the step that is running */
.brew-timeline .tl-strip .tl-hatch{position:absolute;left:0;top:0;bottom:0;width:0;
  background:rgba(47,31,25,.22)}
.brew-timeline .tl-strip .tl-seg.now .tl-hatch{background:var(--accent)}
.brew-timeline .tl-strip .tl-cursor{top:-4px;bottom:-4px;width:2px;z-index:3}
/* the track is only 9px tall, so the playhead needs a head to be findable */
.brew-timeline .tl-strip .tl-cursor::after{display:block;top:-5px;left:-3px;width:8px;height:8px}

/* the names, wrapping */
.brew-timeline .tl-steps{display:flex;flex-wrap:wrap;gap:6px;margin-top:11px}
.brew-timeline .tl-chip{display:inline-flex;align-items:center;gap:6px;min-height:26px;
  padding:4px 10px;border-radius:999px;border:1px dashed var(--border);background:var(--surface);
  color:var(--ink-soft);cursor:pointer;font:inherit;transition:border-color .15s ease,color .15s ease}
.brew-timeline .tl-chip:hover{border-color:var(--accent);color:var(--ink)}
.brew-timeline .tl-chip:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.brew-timeline .tl-chip-n{font:600 9px/1 "JetBrains Mono",monospace;opacity:.6}
.brew-timeline .tl-chip-lbl{font:500 12px/1 "Inter",sans-serif;white-space:nowrap}
.brew-timeline .tl-chip.done{background:var(--surface2);color:var(--ink)}
.brew-timeline .tl-chip.done .tl-chip-n{color:var(--accent);opacity:1}
.brew-timeline .tl-chip.now,
.brew-timeline .tl-chip.g-prep.now,
.brew-timeline .tl-chip.g-brew.now,
.brew-timeline .tl-chip.g-milk.now,
.brew-timeline .tl-chip.g-serve.now{border:1.5px solid var(--accent);color:var(--accent-2);
  box-shadow:0 0 0 3px rgba(217,119,87,.12)}
.brew-timeline .tl-chip.now .tl-chip-lbl{font-weight:700}
.brew-timeline .tl-chip.now .tl-chip-n{color:var(--accent-2);opacity:1}

/* Phases. A brew reads as setup → the brew itself → serving, and the steps
   inside one phase belong together: a V60's bloom and its pours are a single
   drip, which is what the recipe's 1:16 actually describes. One hue per phase,
   on both the track and the names, so that grouping is visible at a glance
   rather than inferred from reading eleven labels. */
/* A chip wears its phase's own colour — the same tint as that phase's band on
   the track above, so the two read as one thing rather than two colour schemes.
   Done deepens the same hue; it never changes it. */
.brew-timeline .tl-chip .tl-chip-n{opacity:1}
/* prep's tint is warm, not grey: a neutral black-alpha over white reads cold
   next to the track's beige band, which sits on --surface2 */
.brew-timeline .tl-chip.g-prep{background:#f3eee1;border-color:rgba(120,100,72,.30)}
.brew-timeline .tl-chip.g-prep .tl-chip-n{color:var(--ink-soft)}
.brew-timeline .tl-chip.g-prep.done{background:#e4dcc4;border-color:rgba(120,100,72,.48)}
.brew-timeline .tl-chip.g-brew{background:rgba(217,119,87,.16);border-color:rgba(217,119,87,.42)}
.brew-timeline .tl-chip.g-brew .tl-chip-n{color:var(--accent-2)}
.brew-timeline .tl-chip.g-brew.done{background:rgba(217,119,87,.34);border-color:rgba(217,119,87,.62)}
.brew-timeline .tl-chip.g-milk{background:rgba(169,130,82,.16);border-color:rgba(169,130,82,.42)}
.brew-timeline .tl-chip.g-milk .tl-chip-n{color:#8a6a41}
.brew-timeline .tl-chip.g-milk.done{background:rgba(169,130,82,.34);border-color:rgba(169,130,82,.62)}
.brew-timeline .tl-chip.g-serve{background:rgba(138,90,51,.14);border-color:rgba(138,90,51,.38)}
.brew-timeline .tl-chip.g-serve .tl-chip-n{color:var(--coffee)}
.brew-timeline .tl-chip.g-serve.done{background:rgba(138,90,51,.30);border-color:rgba(138,90,51,.58)}
/* The track carries its phases whole, not just behind the playhead: the shape
   of the brew — how much of it is setup, how much is the drip — should be
   readable before you press play. The elapsed fill is the same hue, stronger. */
.brew-timeline .tl-strip .tl-seg.g-prep{background:rgba(47,31,25,.07)}
.brew-timeline .tl-strip .tl-seg.g-brew{background:rgba(217,119,87,.16)}
.brew-timeline .tl-strip .tl-seg.g-milk{background:rgba(169,130,82,.16)}
.brew-timeline .tl-strip .tl-seg.g-serve{background:rgba(138,90,51,.14)}
.brew-timeline .tl-strip .tl-seg.g-prep .tl-hatch{background:rgba(47,31,25,.22)}
.brew-timeline .tl-strip .tl-seg.g-brew .tl-hatch{background:rgba(217,119,87,.55)}
.brew-timeline .tl-strip .tl-seg.g-milk .tl-hatch{background:rgba(169,130,82,.45)}
.brew-timeline .tl-strip .tl-seg.g-serve .tl-hatch{background:rgba(138,90,51,.45)}
.brew-timeline .tl-strip .tl-seg.now .tl-hatch{background:var(--accent)}
/* phase boundaries: a solid tick where the brew changes gear, dashed within */
.brew-timeline .tl-strip .tl-seg.is-phase-end{border-right:1px solid var(--ink-soft)}

/* ── Responsive ── */
@media (max-width:760px){
  /* One column, apparatus first: the animation is the point of the card, and
     with the controls first it landed a full screen below the fold. */
  .brew-timeline .stage{grid-template-columns:1fr}
  /* .stage-visual used to be the grid's first child directly; now it's wrapped
     in .stage-surface (so the strip travels with it), which is the actual
     grid child that needs to lead on phones. */
  .brew-timeline .stage-surface{order:-1}
  /* The bar is ~330px wide here and eleven names need far more than that, so
     the strip scrolls rather than hiding or shortening any of them. Segments
     tighten up a little; the 44px height keeps each one past the 24px tap
     minimum (WCAG 2.5.8) on its own. */
  .brew-timeline .tl-steps{gap:5px;margin-top:9px}
  .brew-timeline .tl-chip{padding:4px 8px;gap:5px}
  .brew-timeline .tl-chip-lbl{font-size:11.5px}
}

/* Phone portrait. The bar is ~330px wide here, so a 5-second step is a 20px
   segment — anything drawn inside one is unreadable, and the chrome around it
   has to stop competing for the same row. */
@media (max-width:640px){
  .brew-timeline .card-head{flex-direction:column;align-items:flex-start;gap:2px;margin-bottom:10px}
  .brew-timeline .card-head h2{font-size:16px}
  .brew-timeline .card-head .hint{font-size:10.5px;line-height:1.45}
  .brew-timeline .tl-bar{height:44px;margin-top:18px}
  .brew-timeline .tl-ticks span{font-size:9.5px}
  /* The cursor's time chip is centred on the playhead, so at 0:00 half of it
     sits outside the card — and the same figure is already in the clock right
     below. Drop it and keep the playhead line. */
  .brew-timeline .tl-cursor .tag{display:none}
  /* The grinder picker gets the full row — in a half-width tile the
     placeholder is cut mid-word. */
  .brew-timeline .bt-tiles{grid-template-columns:repeat(auto-fit,minmax(108px,1fr))}
  .brew-timeline .bt-tiles .tile:has(> [data-controller="combobox"]),
  .brew-timeline .bt-tiles .tile:last-child:nth-child(odd){grid-column:1/-1}
  .brew-timeline .grind-sel{max-width:none}
  .brew-timeline .stage{gap:14px}
  .brew-timeline .controls{gap:8px}
  .brew-timeline .bt-btn{padding:9px 16px;font-size:12.5px}
}

/* No keyboard to press: the shortcut legend is noise on a touch device. */
@media (hover:none) and (pointer:coarse){
  .brew-timeline .keys{display:none}
}

/* Compact landscape (horizontal phone): shrink everything so the whole
   step-by-step card fits in one short viewport. */
@media (max-height:540px) and (orientation:landscape){
  .brew-timeline.card{padding:8px 14px 10px}
  .brew-timeline .bt-tiles{display:flex;gap:6px;margin-bottom:6px;overflow-x:auto}
  .brew-timeline .tile{padding:5px 9px;flex:none;min-width:0}
  .brew-timeline .tile .lbl{font-size:8px}
  .brew-timeline .tile .val{font-size:13px;margin-top:2px;white-space:nowrap}
  .brew-timeline .tile .clk{display:none}
  .brew-timeline .grind-sel{margin-top:2px;padding:3px 6px;font-size:11px}
  .brew-timeline .card-head{margin-bottom:2px}
  .brew-timeline .card-head h2{font-size:13px}
  .brew-timeline .card-head .hint{display:none}
  /* The ruler is .tl-strip (#tlBar in the DOM) — .tl-bar and .tl-ticks are
     mockup-era selectors with no matching element in the app, so these two
     rules never fired; retargeted onto the real track + its dropped
     margin-bottom (there is no separate ticks row to compact — the strip's
     own labels carry that job, sized down just below). */
  .brew-timeline .tl-strip{margin-bottom:6px}
  /* this query has no width bound, and this is one of the pair the review
     flagged — landscape phones commonly exceed 760px wide (e.g. 844×390),
     so the ≤760px query below doesn't fire and this one still has to win
     the shrink-and-reposition on its own. Scoped to match the base
     .tl-strip rules' specificity so it does. */
  /* A 390px-tall landscape phone has no vertical room for a second row of
     names, and pushing the Play controls below the fold is worse than a
     sideways nudge — so here alone the names stay on one line and scroll.
     Still every name in full: scrolled is not clipped, and the running step
     is scrolled into view for you (see keepChipInView). */
  .brew-timeline .tl-track{height:6px}
  .brew-timeline .tl-phases{gap:2px 10px;margin-bottom:3px}
  .brew-timeline .tl-phase{font-size:8.5px;gap:4px}
  .brew-timeline .tl-phase::before{width:10px;height:4px}
  .brew-timeline .tl-strip{margin-bottom:4px}
  .brew-timeline .tl-steps{flex-wrap:nowrap;overflow-x:auto;overscroll-behavior-x:contain;
    gap:4px;margin-top:5px;scrollbar-width:none}
  .brew-timeline .tl-steps::-webkit-scrollbar{display:none}
  .brew-timeline .tl-chip{flex:0 0 auto;min-height:24px;padding:3px 7px;gap:4px}
  .brew-timeline .tl-chip-lbl{font-size:11px}
  /* Same as portrait: the chip lands on the heading once the bar is this
     close to it, and the clock below already reads the time. */
  .brew-timeline .tl-cursor .tag{display:none}
  .brew-timeline .stage{margin-top:4px;padding-top:4px;gap:16px;grid-template-columns:minmax(150px,.8fr) 2fr}
  .brew-timeline .stage-side{order:0}
  .brew-timeline .stage-visual{max-height:150px}
  /* The scale strip stacks under stage-visual in the same narrow column, so
     its full size pushes the row (and everything below it) taller than the
     540px this query targets — the Play controls landed below the fold at
     844×390 because of it. */
  .brew-timeline .bt-scale{margin-top:4px;padding:4px 6px}
  .brew-timeline .bt-scale-lcd{padding:4px 5px;gap:1px}
  .brew-timeline .bt-scale-num{font-size:12px}
  .brew-timeline .bt-scale-lbl{font-size:7px}
  .brew-timeline .bt-scale-ratio{margin-top:2px;font-size:10px}
  .brew-timeline .step-kicker{font-size:9px}
  .brew-timeline .clock{font-size:21px;margin:2px 0 0}
  .brew-timeline .step-name{font-size:16px;margin:4px 0 1px}
  .brew-timeline .step-text{font-size:11.5px;max-width:none}
  .brew-timeline .step-progress{margin-top:6px}
  .brew-timeline .controls{margin-top:4px;gap:6px}
  .brew-timeline .bt-btn{padding:6px 12px;font-size:11px;gap:5px}
  .brew-timeline .bt-btn svg{width:12px;height:12px}
  .brew-timeline .keys{display:none}
}

/* ── Player chrome ── */
.brew-timeline .bt-topbar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:14px}
/* The recipe's figures ride in the topbar, between the grinder and the actions.
   Smaller here than they were as a standalone row — they sit beside a control,
   not under a heading — but still chips, still obviously touchable for when the
   tuner makes them inputs. */
.brew-timeline .bt-topbar .bt-facts{flex:1 1 auto;margin:0;justify-content:flex-end;gap:6px}
.brew-timeline .bt-topbar .bt-fact{padding:5px 9px;min-width:0}
.brew-timeline .bt-topbar .bt-fact-value{font-size:14px}
.brew-timeline .bt-topbar .bt-fact-label{font-size:8px;letter-spacing:.14em}
@media (max-width:900px){
  .brew-timeline .bt-topbar .bt-facts{justify-content:flex-start;flex-basis:100%}
}
.brew-timeline .bt-grinder{display:flex;align-items:center;gap:8px;min-width:0}
/* On a phone the picker takes the row to itself: its dropdown is only as wide
   as the input, and "Saint Anthony Industries Millwright" needs every pixel. */
@media (max-width:640px){
  .brew-timeline .bt-grinder{flex-wrap:wrap;flex:1 1 100%}
  .brew-timeline .bt-grinder [data-controller="combobox"]{flex:1 1 100%;min-width:0}
}
.brew-timeline .bt-topbar-lbl{font:600 10px/1 "JetBrains Mono",monospace;letter-spacing:.18em;
  text-transform:uppercase;color:var(--ink-soft);flex:none}
.brew-timeline .bt-clicks{font:600 11px/1 "JetBrains Mono",monospace;color:var(--accent);white-space:nowrap}
.brew-timeline .bt-actions{display:flex;align-items:center;gap:8px;flex:none}
.brew-timeline .bt-meta{display:flex;align-items:baseline;gap:12px;margin-bottom:2px}
.brew-timeline .bt-meta .clock{font:700 15px/1 "JetBrains Mono",monospace;font-variant-numeric:tabular-nums;
  color:var(--ink-soft);margin:0}
.brew-timeline .hidden{display:none}
.brew-timeline .bt-icon-btn{padding:9px 11px}
.brew-timeline .bt-more{position:relative}
.brew-timeline .bt-more-panel{position:absolute;right:0;bottom:calc(100% + 6px);z-index:20;min-width:150px;
  display:flex;flex-direction:column;background:var(--surface);border:1px dashed var(--border);
  border-radius:6px;box-shadow:var(--bt-shadow);padding:4px}
.brew-timeline .bt-more-panel button{appearance:none;background:none;border:0;text-align:left;cursor:pointer;
  padding:8px 10px;border-radius:4px;font:500 13px "Inter";color:var(--ink)}
.brew-timeline .bt-more-panel button:hover{background:var(--surface2)}

/* ── Embed widget: fills the host's 16:9 frame, never resizes it ── */
.bt-embed{position:relative;height:100vh;display:flex;flex-direction:column;justify-content:center;
  padding:14px 16px;overflow:hidden}
.bt-embed .brew-timeline.card{margin:0;border:0;box-shadow:none;background-image:none;padding:0}
.bt-embed .stage-visual{max-height:52vh}
.bt-embed .step-text{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.bt-embed-brand{position:absolute;right:12px;bottom:10px;font:600 10px/1 "JetBrains Mono",monospace;
  letter-spacing:.14em;text-transform:uppercase;color:var(--color-ink-soft);text-decoration:none}
.bt-embed-brand:hover{color:var(--color-accent)}

.brew-timeline .bt-share{position:relative}
.brew-timeline .bt-share-panel{position:absolute;right:0;top:calc(100% + 6px);z-index:20;min-width:190px;
  display:flex;flex-direction:column;gap:2px;background:var(--surface);border:1px dashed var(--border);
  border-radius:6px;box-shadow:var(--bt-shadow);padding:4px}
.brew-timeline .bt-share-panel button{appearance:none;background:none;border:0;text-align:left;cursor:pointer;
  padding:8px 10px;border-radius:4px;font:500 13px "Inter";color:var(--ink)}
.brew-timeline .bt-share-panel button:hover{background:var(--surface2)}
.brew-timeline .bt-share-fallback{width:calc(100% - 20px);margin:2px 10px;padding:6px 8px;
  font:500 12px "JetBrains Mono",monospace;color:var(--ink);background:var(--surface2);
  border:1px dashed var(--border);border-radius:4px}
.brew-timeline .bt-share-feedback{padding:2px 10px 6px;font:600 11px "JetBrains Mono",monospace;color:var(--accent);min-height:14px}
/* the player owns the whole screen in fullscreen, so give it room */
.brew-timeline:fullscreen{padding:4vh 6vw;display:flex;flex-direction:column;justify-content:center;background:var(--bg)}
.brew-timeline:fullscreen .stage-visual{max-height:62vh}

/* Guide me is a peer of Play, not a lesser action — same weight,
   different fill so the pair reads as a choice. */
.brew-timeline .bt-btn-alt{background:var(--surface);color:var(--ink);border:1px solid var(--ink)}
.brew-timeline .bt-btn-alt:hover{background:var(--surface2)}

/* Recipe figures. Bigger than the 13px sentence they replace, far smaller than
   the six-tile block before that — and bordered, so it is obvious they can be
   touched once they become controls. Rendered above the .brew-timeline card,
   so these use the app's global --color-* tokens directly rather than the
   .brew-timeline-scoped aliases. */
.bt-facts{display:flex;flex-wrap:wrap;gap:8px;list-style:none;margin:0 0 24px;padding:0}
.bt-fact{display:flex;flex-direction:column;gap:2px;padding:7px 12px;border-radius:6px;
  border:1px dashed var(--color-border);background:var(--color-surface);min-width:74px}
.bt-fact-label{font:600 9px/1 "JetBrains Mono",monospace;letter-spacing:.16em;
  text-transform:uppercase;color:var(--color-ink-soft)}
.bt-fact-value{font:600 20px/1.1 "JetBrains Mono",monospace;font-variant-numeric:tabular-nums;
  color:var(--color-ink)}
@media (max-width:640px){
  .bt-facts{gap:6px}
  .bt-fact{padding:6px 10px;min-width:0;flex:1 1 auto}
  .bt-fact-value{font-size:17px}
}
