/* The whole bar auto-hides, YouTube-style. Title on the left — `minmax(0, 1fr)`, so it is the
   only column that ever truncates — the transport and its neighbours on the right, the scrubber
   along the bottom edge.

   Two rules about HOW it hides:

   - It fades, it does not collapse. The app grid keeps its 78px row either way. Collapsing it
     would grow `main`, change `waterfall.clientHeight`, and `--fall` is measured off that —
     a mid-run change there desyncs the fall from the audio clock. Never make the header's
     height conditional.
   - It keeps its hit area at opacity 0, deliberately. That is what makes `header:hover` work
     when the bar is invisible: moving the pointer into the top of the window brings it back
     with no JS and no hot-zone element. The cost is that an unseen button is still clickable,
     which is fine because hovering reveals it before any click lands.

   It auto-hides in every transport state, not just while playing — see revealChrome(). The
   only hold is an open settings panel. */
header {
  /* Floating over the stage, not a row in it — see layout.css for why that is not optional. */
  position: absolute; top: 0; left: 0; right: 0; z-index: 15;
  height: var(--header-h);
  display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: 1fr 9px;
  align-items: center; gap: 4px 18px; padding: 7px 18px 0;
  border-bottom: 0;   /* the scrubber's own line is the divider */
  background: rgba(33, 17, 27, .78);
  backdrop-filter: blur(20px);
  opacity: 0;
  transition: opacity 200ms ease;
}
.app[data-chrome="on"] header,
header:hover,
/* Keyboard focus pins the bar open; a mouse click does not. Plain `:focus-within` held it up
   forever after you clicked Play — the button keeps focus, so the idle timer dropped
   data-chrome and the bar still never faded. `:has(:focus-visible)` keeps the tab-through
   reveal and drops the click-sticks case. */
header:has(:focus-visible) { opacity: 1; }

/* Just the piece and the clock, in the slot the MiaoScore wordmark and paw used to hold. The
   brand is on the favicon and the tab title; repeating it above a piano the player is looking
   at was the least useful thing on the bar. (The paw mark went with it, and with it the beat
   tap — the falling tiles and the scrubber already carry the beat.) */
/* Centred, not baseline-aligned. It was baseline when the row was nothing but text — title and
   clock — and the mode switch broke that: a bordered box has no baseline worth sharing, so it
   sat a few pixels below the title's optical centre. Centring aligns the box and costs the
   clock a baseline it was not being read against anyway. */
.range { display: flex; align-items: center; gap: 10px; min-width: 0; }
.range strong { font-size: var(--text-lg); font-weight: 700; letter-spacing: -.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 46ch; }

/* The mode switch. Segmented the way the drawer's own groups are (settings.css .choices.group),
   because it is the same kind of choice: two values you compare, not a list you scan. Smaller
   and quieter than a .load — it is a permanent fixture beside the title, not an action — and
   the only fill is on the mode you are in.

   Each segment carries a glyph, and they are the two the drawer's Mode radios carried before
   Mode moved out here: the Keyboard category's own icon for Waterfall, because the page it goes
   to IS the keyboard, and a tap with its ripples for Effortless, because that page has no keys.
   Two words in the same small caps were a pair you had to read; two shapes are a pair you
   glance at, which is what a permanent fixture on the bar should cost. The paw would have been
   the obvious mark for Effortless and cannot be one: assets/paw.svg carries its own cream
   gradient and can only arrive as an <img> (see file:// in CLAUDE.md), so it cannot take the
   segment's colour the way a stroked glyph does. */
.mode-switch {
  display: flex; flex: none; gap: 2px; padding: 3px;
  border-radius: 999px; border: 1px solid rgba(255,255,255,.14); background: rgba(255,255,255,.05);
}
.mode {
  display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 11px 0 9px;
  border-radius: 999px; white-space: nowrap; text-decoration: none;
  font-size: var(--text-sm); font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  color: #a9829a; transition: background 160ms ease, color 160ms ease;
}
/* The .load icons' drawing exactly - 24 box, stroke 2, round joins - because they sit on the
   same bar 18px away. Only the size differs: 13px, sized to the segment's smaller type. */
.mode svg { width: 13px; height: 13px; flex: none; fill: none; stroke: currentColor;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
a.mode:hover { background: rgba(255,255,255,.1); color: var(--pink-soft); }
/* The fill on the mode you are in is the brand's pink, not flat white. White made it the same
   chrome every .load is made of, and this is the one control on the bar that says where you
   ARE rather than what to do next. Translucent, so it stays under Play: one solid fill up
   there, and it belongs to the primary action. */
.mode[aria-current] { background: color-mix(in srgb, var(--pink-light) 24%, transparent); color: #fff; }
.mode:focus-visible { outline: 2px solid #ffd2e5; outline-offset: 2px; }

/* 18px of hit area straddling the header's bottom edge — half in the header, half over main,
   so the track lands *on* the divider instead of floating above it. Hence the -9px. */
.song-progress {
  grid-column: 1 / -1; align-self: end; position: relative; width: 100%; height: 18px;
  margin-bottom: -9px;
}
.song-progress::before, .song-progress::after {
  content: ""; position: absolute; left: -18px; right: -18px; top: 50%; height: 2px;
  transform: translateY(-50%); pointer-events: none;
}
.song-progress::before { background: rgba(255,255,255,.09); }
/* The played part is scaled, not resized: `--song-progress` is a 0-1 fraction driving a
   transform, which the compositor can advance subpixel-smooth. Growing a gradient's
   background-size instead repainted a full-width blurred bar on every frame, and stepped
   whole pixels while doing it. */
.song-progress::after {
  transform: translateY(-50%) scaleX(var(--song-progress, 0)); transform-origin: left;
  background: linear-gradient(90deg, var(--left-hand), var(--pink-light), var(--right-hand));
  box-shadow: 0 0 12px rgba(255,145,191,.2);
}
.song-progress input {
  -webkit-appearance: none; appearance: none; width: 100%; height: 18px; margin: 0;
  border-radius: 999px; cursor: pointer; opacity: 0;
}
.song-progress input::-webkit-slider-thumb {
  -webkit-appearance: none; width: 15px; height: 15px; border-radius: 50%;
  background: currentColor; border: 0;
}
.song-progress input::-moz-range-thumb {
  width: 15px; height: 15px; border-radius: 50%; border: 0; background: currentColor;
}
.song-progress-time {
  /* flex: none because the header's rule is that the TITLE is the only thing that ever gets
     squeezed. Without it the clock is shrinkable and breaks to two lines in a 43px row the
     moment the bar gets tight — 7ch of min-width does not stop a wrap. */
  flex: none;
  color: #a9829a; font-size: var(--text-sm); font-weight: 800;
  font-variant-numeric: tabular-nums; min-width: 7ch;
}

/* One control language: same height, same radius, same border. Only the primary action
   carries fill. */
.controls { display: flex; align-items: center; gap: 8px; }
.load, .play {
  height: var(--control-h); border-radius: var(--control-r);
  font-size: var(--text-md); font-weight: 700; white-space: nowrap;
}
.load {
  display: inline-flex; align-items: center; gap: 7px; padding: 0 13px;
  /* .load is element-agnostic — button and label today; the <a> that used to be one is the
     .mode-switch now. text-decoration stays: the next one may well be a link again. */
  text-decoration: none;
  border: 1px solid rgba(255,255,255,.14); color: var(--pink-soft);
  background: rgba(255,255,255,.05);
  cursor: pointer; transition: background 160ms ease, border-color 160ms ease;
}
.load:hover { background: rgba(255,255,255,.11); border-color: rgba(255,255,255,.24); }
.load svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round; }
.load.icon-only { width: var(--control-h); padding: 0; justify-content: center; }
.play {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-width: 116px; padding: 0 18px; border: 0; cursor: pointer;
  /* Dark ink on the lighter pink: white on the old gradient measured about 3.3:1. */
  color: #3d0f26; background: linear-gradient(135deg, #ffa8cd, #ff5ca2);
  box-shadow: 0 8px 22px rgba(255,79,154,.3);
  transition: filter 160ms ease;
}
.play:hover { filter: brightness(1.07); }
.play svg { width: 15px; height: 15px; fill: currentColor; }
