/* 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);
  /* Phase hues — one source for the blocks on the ruler, the chips under it
     and the legend above it, so the three can never drift into three colour
     schemes. Warm-editorial throughout: brew owns the accent because it is
     the part of a brew that matters, and the others step away from it in
     lightness rather than hue.

     Deliberately NOT a CVD-validated categorical palette. Running the four
     through the palette validator, every combination that clears the
     normal-vision separation floor needs a teal and a violet — hues this site
     does not have and a coffee timeline should not invent. The check exists
     for charts where colour IS the encoding; here it never is: every block is
     named by a numbered chip directly beneath it, and the legend spells out
     each phase in words with its duration. Colour groups; the text
     identifies. */
  --ph-prep:#8c7d6f; --ph-brew:#d97757; --ph-milk:#b98a4e; --ph-serve:#8a5a33;
  /* 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);
}

/* Dark mode gets its own steps, not an automatic flip: #8a5a33 on a #1b1512
   card is nearly invisible, and #8c7d6f loses the little separation it has
   from the surface. Same hues, lighter and a shade more saturated. */
.dark .brew-timeline{
  --ph-prep:#b3a294; --ph-brew:#e8946f; --ph-milk:#d6a865; --ph-serve:#c08a5e;
}

/* ── 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}
.brew-timeline .bt-note-heading{display:flex;align-items:center;gap:8px;margin:0;
  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}
/* Task 4: a step's per-param notes, small lines under its explainer — same
   ink-soft idiom as .bt-note-text, one size down since these are asides on
   a single figure, not the step's own teaching copy. */
.brew-timeline .bt-note-params{list-style:none;margin:8px 0 0;padding:0;display:flex;flex-direction:column;gap:2px;max-width:62ch}
.brew-timeline .bt-note-params li{color:var(--ink-soft);font-size:12.5px;line-height:1.5}
.brew-timeline .bt-note-param-label{font-weight:600;color:var(--ink)}
@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 ──
   A plain surface, no graph-paper grid. The panel inside it is an instrument
   face now — bordered cells, steppers, an edited cell in accent — and a ruled
   background behind all of that was one texture too many. The page's own
   dot-grid still shows around the card, so it stays a sheet with an
   instrument set down on it. --surface, not literal white: this has to darken
   with the rest of the page in dark mode. */
.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)}
.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 ── */
/* Two columns, two rows — the weighing surface over its readout on the left,
   the ruler and the step over the controls on the right. The rows are what
   the layout is actually for: Play sits level with the LCD because they share
   row 2, not because anything was nudged into place. .stage-surface keeps its
   wrapper (the strip has to match the surface's width, and a test pins the
   nesting) and adopts the parent's rows with subgrid, so its two children land
   on the same lines the right-hand column uses. Without subgrid support it
   degrades to its own two-row stack: still correct, just not aligned across.

   The apparatus is also capped: 1fr of a 1900px card drew a 740px-wide scale
   with a 500px-tall column of white space beside it. */
.brew-timeline .stage{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.4fr);
  grid-template-rows:auto auto;gap:clamp(14px,2.5vw,26px);row-gap:10px;
  margin-top:8px;padding-top:12px;border-top:1px dashed rgba(47,31,25,.12)}
/* No gap between the weighing surface and its readout: they are one
   instrument, and a 10px channel between them made the plate read as a
   separate widget parked underneath. The adjoining corners square off for the
   same reason — see .stage-visual and .bt-scale-lcd below. */
.brew-timeline .stage-surface{grid-column:1;grid-row:1 / 3;display:grid;
  grid-template-rows:subgrid;row-gap:0;min-width:0;max-width:560px}
/* Inside row 1: the ruler and the step travel together, centred against the
   weighing surface across the way. They are one block — the bar says where
   you are, the step says what you are doing — so pinning the bar to the top
   and floating the step below it split a single thought in two. */
.brew-timeline .stage-side{grid-column:2;grid-row:1;display:flex;flex-direction:column;
  justify-content:center;min-width:0}
.brew-timeline .controls{grid-column:2;grid-row:2;align-self:center}
.brew-timeline .stage-visual{position:relative;aspect-ratio:440/300;background:var(--surface2);
  border:1px dashed var(--border);border-radius:6px 6px 0 0;border-bottom:0;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 .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}
/* 34ch broke "Weigh out the beans — fresh, not pre-ground." across two lines
   in a column with room for four times that. 56ch is still a measure — long
   prose does not run the full width of the card — but it stops the text
   wrapping mid-thought while the space beside it sits empty. */
.brew-timeline .step-text{color:var(--ink-soft);font-size:14.5px;line-height:1.55;max-width:56ch}
/* Task 4: this step's own param_notes, filled/cleared per step in
   brew_timeline_controller#activate — :empty hides the gap entirely on a
   step (or a whole recipe) that carries none. */
.brew-timeline .step-param-notes{margin-top:6px;display:flex;flex-direction:column;gap:2px;max-width:56ch}
.brew-timeline .step-param-notes p{margin:0;color:var(--ink-soft);font-size:12.5px;line-height:1.5}
.brew-timeline .step-param-notes:empty{display:none}
.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 ── */
/* No box of its own: the readout is the same instrument as the surface above
   it, so the plate runs to exactly the same edges. The dashed border and 8px
   padding it used to carry inset the LCD on both sides and framed it as a
   separate widget sitting underneath. */
.brew-timeline .bt-scale{align-self:start;border:0;padding:0;background:none}
/* Asleep, a real scale keeps its dark plate and lets the digits go out — it
   does not turn itself grey. Fading the whole element to 45% over a white card
   is exactly what made the plate read as a grey slab, so the opacity moves off
   the plate and onto what it displays. */
.brew-timeline .bt-scale-lcd{display:grid;grid-template-columns:repeat(3,1fr);gap:2px;
  background:var(--lcd-bg);border-radius:0 0 6px 6px;padding:10px 8px 11px}
.brew-timeline .bt-scale .bt-scale-field,
.brew-timeline .bt-scale .bt-scale-ratio{transition:opacity .25s ease}
.brew-timeline .bt-scale.is-off .bt-scale-field,
.brew-timeline .bt-scale.is-off .bt-scale-ratio{opacity:.32}
.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}
/* spans the three fields as the plate's second line, lit like the rest of it */
.brew-timeline .bt-scale-ratio{grid-column:1 / -1;margin-top:7px;text-align:center;
  font:600 12px/1 "JetBrains Mono",monospace;font-variant-numeric:tabular-nums;
  color:var(--lcd-fg);opacity:.75}
@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}
.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:16px;height:6px;border-radius:2px;
  background:currentColor;opacity:.9}
.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(--ph-prep)}
.brew-timeline .tl-phase.g-brew{color:var(--ph-brew)}
.brew-timeline .tl-phase.g-milk{color:var(--ph-milk)}
.brew-timeline .tl-phase.g-serve{color:var(--ph-serve)}
/* The plot: each step is a block standing on the axis, exactly as wide as it
   lasts. Not a single filled bar — a bar says "this much of the brew is
   behind you", blocks say "these are the steps, and this is how long each of
   them takes", which is the thing a ruler is for. */
.brew-timeline .tl-track{position:relative;height:22px}
/* A transparent right border with background-clip:padding-box leaves a real
   gap between neighbouring blocks without moving either of them off the time
   it actually occupies — the alternative, insetting each block's own left and
   right, would make every block read a little shorter than it is. The fill
   below is positioned against the padding box, so it stops at the gap too. */
.brew-timeline .tl-strip .tl-seg{position:absolute;top:0;bottom:0;overflow:hidden;
  border:0;border-right:2px solid transparent;background-clip:padding-box;
  border-radius:2px;pointer-events:none;background-color:var(--surface2)}
/* one hue per phase, the same the legend and the chips use. The ring is what
   makes a block an object on the axis rather than a wash of colour. */
.brew-timeline .tl-strip .tl-seg.g-prep{background-color:color-mix(in oklab,var(--ph-prep) 26%,transparent);
  box-shadow:inset 0 0 0 1px color-mix(in oklab,var(--ph-prep) 52%,transparent)}
.brew-timeline .tl-strip .tl-seg.g-brew{background-color:color-mix(in oklab,var(--ph-brew) 26%,transparent);
  box-shadow:inset 0 0 0 1px color-mix(in oklab,var(--ph-brew) 55%,transparent)}
.brew-timeline .tl-strip .tl-seg.g-milk{background-color:color-mix(in oklab,var(--ph-milk) 26%,transparent);
  box-shadow:inset 0 0 0 1px color-mix(in oklab,var(--ph-milk) 55%,transparent)}
.brew-timeline .tl-strip .tl-seg.g-serve{background-color:color-mix(in oklab,var(--ph-serve) 24%,transparent);
  box-shadow:inset 0 0 0 1px color-mix(in oklab,var(--ph-serve) 50%,transparent)}
/* elapsed: the block fills in with its own hue at full strength */
.brew-timeline .tl-strip .tl-hatch{position:absolute;left:0;top:0;bottom:0;width:0;
  background:var(--ph-prep);opacity:.85}
.brew-timeline .tl-strip .tl-seg.g-brew .tl-hatch{background:var(--ph-brew);opacity:.95}
.brew-timeline .tl-strip .tl-seg.g-milk .tl-hatch{background:var(--ph-milk);opacity:.9}
.brew-timeline .tl-strip .tl-seg.g-serve .tl-hatch{background:var(--ph-serve);opacity:.9}
.brew-timeline .tl-strip .tl-seg.now .tl-hatch{background:var(--accent);opacity:.95}
.brew-timeline .tl-strip .tl-seg.g-prep.now,
.brew-timeline .tl-strip .tl-seg.g-brew.now,
.brew-timeline .tl-strip .tl-seg.g-milk.now,
.brew-timeline .tl-strip .tl-seg.g-serve.now{box-shadow:inset 0 0 0 1.5px var(--accent)}
.brew-timeline .tl-strip .tl-cursor{top:-5px;bottom:-3px;width:2px;z-index:3}
/* the blocks are short, 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 axis the blocks stand on: a hairline, ticked in real time. */
.brew-timeline .tl-axis{position:relative;height:20px;
  border-top:1px solid color-mix(in oklab,var(--ink-soft) 55%,transparent)}
.brew-timeline .tl-tick{position:absolute;top:0;width:1px;height:4px;
  background:color-mix(in oklab,var(--ink-soft) 40%,transparent)}
.brew-timeline .tl-tick.is-major{height:7px;background:var(--ink-soft)}
.brew-timeline .tl-tick i{position:absolute;top:9px;left:50%;transform:translateX(-50%);
  font:500 10px/1 "JetBrains Mono",monospace;font-variant-numeric:tabular-nums;
  color:var(--ink-soft);white-space:nowrap}
/* the ends would otherwise hang off their own edge of the ruler */
.brew-timeline .tl-tick[data-edge="start"] i{left:0;transform:none}
.brew-timeline .tl-tick[data-edge="end"] i{left:auto;right:0;transform:none}

/* Pointing at a name lights the slice of the brew it belongs to (see
   buildBar's `link`). The chips can't sit above their own segments — a
   5-second step owns 6% of the track — so the tie is shown on demand
   instead of implied by geometry that would clip every short name. */
.brew-timeline .tl-strip .tl-seg.is-linked,
.brew-timeline .tl-strip .tl-seg.g-prep.is-linked,
.brew-timeline .tl-strip .tl-seg.g-brew.is-linked,
.brew-timeline .tl-strip .tl-seg.g-milk.is-linked,
.brew-timeline .tl-strip .tl-seg.g-serve.is-linked{background-color:rgba(217,119,87,.42);
  box-shadow:inset 0 0 0 1px var(--accent)}

/* the names, wrapping — tight under the track they belong to */
.brew-timeline .tl-steps{display:flex;flex-wrap:wrap;gap:6px;margin-top:9px}
.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}
.brew-timeline .tl-chip.g-prep{background:color-mix(in oklab,var(--ph-prep) 11%,transparent);
  border:1px solid color-mix(in oklab,var(--ph-prep) 38%,transparent);color:var(--ink)}
.brew-timeline .tl-chip.g-prep .tl-chip-n{color:var(--ph-prep)}
.brew-timeline .tl-chip.g-prep.done{background:color-mix(in oklab,var(--ph-prep) 26%,transparent)}
.brew-timeline .tl-chip.g-brew{background:color-mix(in oklab,var(--ph-brew) 11%,transparent);
  border:1px solid color-mix(in oklab,var(--ph-brew) 40%,transparent);color:var(--ink)}
.brew-timeline .tl-chip.g-brew .tl-chip-n{color:var(--ph-brew)}
.brew-timeline .tl-chip.g-brew.done{background:color-mix(in oklab,var(--ph-brew) 26%,transparent)}
.brew-timeline .tl-chip.g-milk{background:color-mix(in oklab,var(--ph-milk) 11%,transparent);
  border:1px solid color-mix(in oklab,var(--ph-milk) 40%,transparent);color:var(--ink)}
.brew-timeline .tl-chip.g-milk .tl-chip-n{color:var(--ph-milk)}
.brew-timeline .tl-chip.g-milk.done{background:color-mix(in oklab,var(--ph-milk) 26%,transparent)}
.brew-timeline .tl-chip.g-serve{background:color-mix(in oklab,var(--ph-serve) 10%,transparent);
  border:1px solid color-mix(in oklab,var(--ph-serve) 38%,transparent);color:var(--ink)}
.brew-timeline .tl-chip.g-serve .tl-chip-n{color:var(--ph-serve)}
.brew-timeline .tl-chip.g-serve.done{background:color-mix(in oklab,var(--ph-serve) 24%,transparent)}
/* The blocks' own phase colours live with the plot they belong to (see
   .tl-strip .tl-seg above). A second copy here — same specificity, later in
   the file, and using the `background` shorthand — silently reset the
   background-clip the gap between blocks depends on. */
/* the blocks stand apart on the axis now, so a phase hand-over needs no rule
   of its own — the legend above and the colour change carry it */

/* ── 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. */
  /* One column: the explicit two-row placement the desktop layout uses has to
     be handed back, or every item would be assigned to the same two cells. */
  .brew-timeline .stage{grid-template-columns:1fr;grid-template-rows:none}
  /* .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;grid-column:auto;grid-row:auto;
    display:block;max-width:none}
  .brew-timeline .stage-side{grid-column:auto;grid-row:auto}
  .brew-timeline .controls{grid-column:auto;grid-row:auto;margin-top:14px}
  /* .stage-surface is a plain block here, so the row gap that separated the
     readout from the surface on desktop no longer applies. */
  .brew-timeline .bt-scale{margin-top:0}
  /* 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}
  .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:3px;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 ──────────────────────────────────────────────────────────
   The panel reads as one instrument deck: the grinder and what it resolves to,
   the figures you turn, the ones that follow, then the window actions. Its
   height is fixed whether or not anything is edited — see .bt-dirty. */
.brew-timeline .bt-topbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:2px}
.brew-timeline .bt-grinder{display:flex;align-items:center;gap:10px;flex:1 1 320px;min-width:0}
.brew-timeline .bt-grinder-box{flex:1 1 auto;min-width:0;max-width:19rem}
/* 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:1 1 100%;order:1}
  .brew-timeline .bt-grinder-box{max-width:none}
}
@media (max-width:400px){
  .brew-timeline .bt-grinder .bt-topbar-lbl{display:none}
}
.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-actions{display:flex;align-items:center;gap:8px;flex:none}
@media (max-width:640px){
  .brew-timeline .bt-actions{order:2;margin-left:auto}
}
.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)}

/* ── The instruments ────────────────────────────────────────────────────────
   A cell is a thing you turn: bordered, with a stepper and an accent it takes
   on once you have moved it. A readout is a thing that follows: no border, no
   stepper, so the difference is legible without a second column of chrome. */
.bt-facts{display:flex;flex-wrap:wrap;align-items:stretch;gap:8px;margin:0;padding:0}
.bt-fact-label{font:600 9px/1 "JetBrains Mono",monospace;letter-spacing:.16em;
  text-transform:uppercase;color:var(--color-ink-soft)}
.brew-timeline .bt-cell{position:relative;display:flex;flex-direction:column;gap:3px;
  padding:6px 9px 7px;border:1px dashed var(--color-border);border-radius:7px;
  background:var(--color-surface);min-width:100px;
  transition:border-color .12s ease, background-color .12s ease}
.brew-timeline .bt-cell-field{display:flex;align-items:baseline;gap:3px;padding-right:26px}
.brew-timeline .bt-cell-pre{font:600 13px/1 "JetBrains Mono",monospace;color:var(--color-ink-soft)}
.brew-timeline .bt-cell-input{width:4.5ch;padding:0;border:0;background:none;color:var(--color-ink);
  font:600 20px/1.15 "JetBrains Mono",monospace;font-variant-numeric:tabular-nums;
  -moz-appearance:textfield}
.brew-timeline .bt-cell-input::-webkit-outer-spin-button,
.brew-timeline .bt-cell-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.brew-timeline .bt-cell-input:focus{outline:none}
.brew-timeline .bt-cell:focus-within{border-style:solid;border-color:var(--color-accent)}
.brew-timeline .bt-fact-unit{font:600 11px/1 "JetBrains Mono",monospace;color:var(--color-ink-soft)}

/* Two 24x24 targets (WCAG 2.5.8) stacked at the cell's edge — the whole point
   of the redesign: a figure you can move without typing. */
.brew-timeline .bt-spin{position:absolute;right:4px;top:50%;transform:translateY(-40%);
  display:flex;flex-direction:column}
.brew-timeline .bt-spin button{width:24px;height:24px;display:grid;place-items:center;border:0;
  background:none;color:var(--color-ink-soft);cursor:pointer;padding:0;border-radius:4px;
  -webkit-tap-highlight-color:transparent;touch-action:manipulation}
.brew-timeline .bt-spin button:hover{color:var(--color-accent);background:rgba(217,119,87,.10)}
.brew-timeline .bt-spin button:active{background:rgba(217,119,87,.20)}
.brew-timeline .bt-spin svg{width:11px;height:11px;stroke-width:3}

/* Edited: the cell itself says so. The chip that used to say it in words is
   gone — it named the fact of an edit without naming which figure moved, and
   it pushed the save row onto a new line as it appeared. */
.brew-timeline .bt-cell.is-edited{border-style:solid;border-color:var(--color-accent);
  background:rgba(217,119,87,.06)}
.brew-timeline .bt-cell.is-edited .bt-fact-label{color:var(--color-accent)}
.brew-timeline .bt-cell.is-edited .bt-cell-input,
.brew-timeline .bt-cell.is-edited .bt-cell-pre,
.brew-timeline .bt-cell.is-edited .bt-fact-unit{color:var(--color-accent-2)}

.brew-timeline .bt-read{display:flex;flex-direction:column;gap:3px;padding:6px 2px 7px;
  justify-content:center;min-width:0}
.brew-timeline .bt-read-val{font:600 13px/1.25 "JetBrains Mono",monospace;
  font-variant-numeric:tabular-nums;color:var(--color-ink)}
.brew-timeline .bt-read-sub{font:500 11px/1.2 "JetBrains Mono",monospace;color:var(--color-ink-soft)}
.brew-timeline .bt-read-sub:empty{display:none}

/* Task 4: the bean card reuses .bt-facts/.bt-read (see _bean_card.html.erb)
   but its values are prose — a bean name, a roaster — not the tabular
   figures the mono type was built for; a plain readable face and a wrap
   suit them better than the player's own chips. */
.brew-timeline .bean-facts .bt-read{padding:8px 12px;border:1px dashed var(--color-border);
  border-radius:7px;background:var(--color-surface)}
.brew-timeline .bean-facts .bt-read-val{font-family:"Inter",sans-serif;font-variant-numeric:normal;
  white-space:normal}

@media (max-width:640px){
  .bt-facts{display:grid;grid-template-columns:1fr 1fr;order:3;width:100%;gap:6px}
  .brew-timeline .bt-cell{min-width:0}
  .brew-timeline .bt-cell-input{font-size:18px}
}

/* ── The way back, and the way to keep it ───────────────────────────────────
   Reserved height at rest, contents revealed once the draft differs from ours,
   so an edit never moves anything else on the page. */
/* The reserved height is the whole point of this row, so it stays — but it
   was carrying 18px of margin on top of it, which is what opened the gap
   between the figures and the brew they describe. */
.brew-timeline .bt-dirty{display:flex;justify-content:flex-end;align-items:center;gap:8px;
  min-height:30px;margin:0}
.brew-timeline .bt-dirty[data-state="rest"] > *{visibility:hidden}
.brew-timeline .bt-dirty-reset{display:grid;place-items:center;width:30px;height:30px;
  border:1px dashed var(--color-border);border-radius:6px;background:none;
  color:var(--color-ink-soft);cursor:pointer}
.brew-timeline .bt-dirty-reset:hover{border-style:solid;border-color:var(--color-accent);
  color:var(--color-accent)}
.brew-timeline .bt-dirty-reset svg{width:15px;height:15px}
.brew-timeline .bt-dirty-save{font:600 12px/1 "Inter",sans-serif;color:var(--color-bg);
  background:var(--color-ink);border:0;border-radius:6px;padding:9px 14px;cursor:pointer}
.brew-timeline .bt-dirty-save:hover{background:var(--color-accent-2)}
.brew-timeline .bt-dirty-saved{font:500 11.5px/1 "Inter",sans-serif;color:var(--color-ink-soft)}
.brew-timeline .bt-dirty-saved a{color:var(--color-accent);text-decoration:underline;text-underline-offset:2px}

/* ── The method's own spec, above the panel ─────────────────────────────────
   One line of what we published, so an edited panel always has something to
   disagree with, and the handoff into it. */
/* Directly under the Overview heading, above the map: it reads as the
   method's own spec caption — this is the brew you are about to look at —
   rather than a footnote discovered after the steps. */
.bt-specline{display:flex;flex-wrap:wrap;align-items:center;gap:10px 14px;
  border-bottom:1px dashed var(--color-border);padding-bottom:12px;margin:0 0 18px}
.bt-specline-tag{font:600 9px/1 "JetBrains Mono",monospace;letter-spacing:.18em;text-transform:uppercase;
  color:var(--color-ink-soft);border:1px dashed var(--color-border);border-radius:4px;padding:4px 7px}
.bt-specline-figs{font:500 13px/1.5 "JetBrains Mono",monospace;color:var(--color-ink);
  font-variant-numeric:tabular-nums;flex:1 1 auto;min-width:0}
.bt-specline-figs i{font-style:normal;color:var(--color-border);padding:0 6px}
.bt-specline-cta{font:600 12.5px/1 "Inter",sans-serif;color:var(--color-ink);background:none;
  border:1px dashed var(--color-ink);border-radius:6px;padding:9px 14px;cursor:pointer;
  display:inline-flex;align-items:center;gap:7px;white-space:nowrap}
.bt-specline-cta:hover{border-style:solid;border-color:var(--color-accent);color:var(--color-accent)}
.bt-specline-cta svg{width:14px;height:14px}
@media (max-width:640px){
  .bt-specline-cta{width:100%;justify-content:center}
}
/* ── 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}

/* Which brew is this? On the page the heading above the card answers that;
   in fullscreen the card IS the page, so it has to answer for itself. Two
   rules, not one selector list: :-webkit-full-screen is unknown to Firefox
   and would invalidate the whole rule for it. */
.brew-timeline .bt-fs-title{display:none;margin:0}
.brew-timeline:fullscreen .bt-fs-title{display:block;
  font:600 clamp(17px,1.9vw,24px)/1.2 "Source Serif 4",serif;color:var(--ink);
  letter-spacing:-.01em;margin:0 0 14px}
.brew-timeline:-webkit-full-screen .bt-fs-title{display:block;
  font:600 clamp(17px,1.9vw,24px)/1.2 "Source Serif 4",serif;color:var(--ink);
  letter-spacing:-.01em;margin:0 0 14px}

/* 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)}

/* A step's duration, in its own row: read-only text now. The composition
   itself becomes yours in the custom-brew-method editor, not here. */
.brew-timeline .bt-note-secs{font:600 12px/1 "JetBrains Mono",monospace;
  font-variant-numeric:tabular-nums;color:var(--color-ink-soft);white-space:nowrap}

