/* /listen/:n — THE FULL-SCREEN PLAYER · /recordings — EVERY RECORDING. (D-549e)
 *
 * Andrew: "users need a button to project to bluetooth device. But let's move this and the chevron
 * menu to the full screen. We do need a See all button tho to a new surface with all recordings."
 *
 * THE CARD IS A DOORWAY. THIS IS THE CONTROL PANEL.
 * Every control on the home card is one more thing between a scrolling thumb and the play button —
 * so the route picker and the actions menu live here, where she has already chosen to arrive.
 */

.lsn { min-height: 100%; padding: var(--rhythm-pad); display: flex; flex-direction: column; gap: var(--space-16); color: var(--text-on-dark); }
.lsn-bar { display: flex; align-items: center; justify-content: space-between; }
.lsn-close { width: var(--dim-40); height: var(--dim-40); border: 0; background: 0; color: var(--text-on-dark); border-radius: var(--radius-round); display: flex; align-items: center; justify-content: center; cursor: pointer; }
.lsn-close svg { width: var(--size-18); height: var(--size-18); }
.lsn-close:active { opacity: 0.72; }
.lsn-close:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }

.lsn-eyebrow { font-family: var(--font-label); font-size: var(--size-11); font-weight: var(--weight-700); letter-spacing: var(--tracking-05); text-transform: uppercase; color: var(--gold-200); }
.lsn-title { font-family: var(--font-display); font-weight: var(--weight-500); font-size: var(--size-28); line-height: var(--leading-115); color: var(--text-on-dark); }

/* the SAME waveform the card draws, from the SAME stored peaks — one fact, two surfaces */
.lsn-wave { position: relative; height: var(--dim-56, 56px); cursor: pointer; overflow: hidden; } /* token-exception */
.lsn-wbars { position: absolute; inset: 0; display: flex; align-items: center; gap: 2px; } /* token-exception */
.lsn-wb { flex: 1; min-width: 0; border-radius: var(--radius-pill); background: rgba(255,255,255,.28); } /* token-exception: on the dark hero */
.lsn-wplayed { position: absolute; inset: 0 auto 0 0; width: 0; overflow: hidden; transition: width var(--duration-200) linear; pointer-events: none; }
.lsn-wplayed .lsn-wb { background: var(--text-on-dark); }

.lsn-times { display: flex; align-items: center; justify-content: space-between; }
.lsn-t, .lsn-d { font-family: var(--font-label); font-size: var(--size-12); font-weight: var(--weight-600); color: rgba(255,255,255,.7); font-variant-numeric: tabular-nums; } /* token-exception */

.lsn-transport { display: flex; align-items: center; justify-content: center; gap: var(--space-20); margin-top: var(--space-8); }
.lsn-rate { min-width: var(--dim-40); height: var(--dim-32); padding: 0 var(--space-8); border: 0; border-radius: var(--radius-pill); background: rgba(255,255,255,.14); color: var(--text-on-dark); font-family: var(--font-label); font-size: var(--size-12); font-weight: var(--weight-700); font-variant-numeric: tabular-nums; cursor: pointer; } /* token-exception */
.lsn-skip { width: var(--dim-44); height: var(--dim-44); flex: none; border: 0; background: 0; color: var(--text-on-dark); border-radius: var(--radius-round); display: flex; align-items: center; justify-content: center; cursor: pointer; }
.lsn-skip { position: relative; }
.lsn-skip svg { width: var(--size-28); height: var(--size-28); transform: scale(1.12); }  /* scaled, not resized — the row stays centred (D-549j) */
/* the number is TEXT in the label face — never baked into the glyph (D-549g / D-429) */
.lsn-skipn {
  position: absolute; top: 52%; left: 50%;
  transform: translate(-50%, -50%);
  font-family: var(--font-label);
  font-size: var(--size-10);
  font-weight: var(--weight-700);
  color: currentColor;
  pointer-events: none;
}
/* 🔴 THE GLYPH IS INK, NOT EVERGREEN. (D-551)
 * The ground moved from --green-900 to --surface-inverse, and this button is the one thing the
 * ground FORCES: a cream disc with a GREEN play arrow on an ink screen is a leftover from the old
 * background, not a decision. It would have passed every check we own — --green-900 is a real
 * token — and looked, at a glance, fine. */
.lsn-play { width: 72px; height: 72px; flex: none; border: 0; border-radius: var(--radius-round); background: var(--text-on-dark); color: var(--ink-900); display: flex; align-items: center; justify-content: center; cursor: pointer; } /* token-exception: the hero control */
.lsn-play svg { width: var(--size-24); height: var(--size-24); }
.lsn-ic-play { display: flex; margin-left: var(--nudge-2); }
.lsn-ic-pause { display: none; }
.lsn-playing .lsn-ic-play { display: none; }
.lsn-playing .lsn-ic-pause { display: flex; }
.lsn-rate:active, .lsn-skip:active, .lsn-play:active { opacity: 0.8; }
.lsn-rate:focus-visible, .lsn-skip:focus-visible, .lsn-play:focus-visible, .lsn-route:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }

/* 🔴 THE ROUTE PICKER — "play on another device". (D-549e)
 * It opens the SYSTEM sheet (AirPlay + Bluetooth on iOS; Remote Playback elsewhere). We do not draw
 * a device list: we cannot know what is paired, and Web Bluetooth is GATT — a DATA protocol that
 * cannot route sound at all. An app that asks for Bluetooth permission and then does not play
 * through the speaker is worse than one that never asked.
 *
 * ⚠️ AND THE BUTTON DOES NOT EXIST WHERE THERE IS NO PICKER. `.lsn-noroute` is an empty spacer that
 * keeps the transport centred, because a control that does nothing is the one thing this card has
 * spent all day refusing to be. */
.lsn-route { width: var(--dim-44); height: var(--dim-44); flex: none; border: 0; background: 0; color: var(--text-on-dark); border-radius: var(--radius-round); display: flex; align-items: center; justify-content: center; cursor: pointer; }
.lsn-route svg { width: var(--size-24); height: var(--size-24); }
.lsn-route:active { opacity: 0.72; }
.lsn-noroute { width: var(--dim-44); height: var(--dim-44); flex: none; }

/* `.lsn-voice` LIVED HERE. It is gone with the credit line it styled (D-550) — a CSS rule that can
 * never fire is a lie about the surface (D-522).
 *
 * ⚠️ AND IT WAS DOING A SECOND, INVISIBLE JOB. It carried `margin-top: auto` — the only thing in
 * this column pushing against the bottom of the screen. I nearly handed that job to
 * `.lsn-route-now`, which is `display:none` whenever she is NOT casting: a spacer that vanishes
 * exactly when it is needed. So the column now simply stacks from the top, and the transport sits
 * under the wave where it belongs, rather than being flung to the bottom of a tall phone by a
 * credit line nobody asked for. */

/* the chevron menu is SHARED·ACTIONS (403), not this card's and not 109's (D-556). The player marks
 * itself `.act-on-dark`; the dark treatment lives WITH the component, not scattered across the
 * surfaces that happen to be dark. */

/* ── /recordings — the back catalogue is a PLACE ───────────────────────────── */
.rec { min-height: 100%; padding: var(--rhythm-pad); display: flex; flex-direction: column; gap: var(--space-12); }
.rec .lsn-bar .rec-close { width: var(--dim-40); height: var(--dim-40); border: 0; background: 0; color: var(--text-secondary); border-radius: var(--radius-round); display: flex; align-items: center; justify-content: center; cursor: pointer; }
.rec .lsn-bar .rec-close svg { width: var(--size-18); height: var(--size-18); }
.rec-eyebrow { font-family: var(--font-label); font-size: var(--size-11); font-weight: var(--weight-700); letter-spacing: var(--tracking-05); text-transform: uppercase; color: var(--kind-watch-icon); }
.rec-title { font-family: var(--font-display); font-weight: var(--weight-500); font-size: var(--size-28); line-height: var(--leading-115); color: var(--text-primary); }
/* ── 🔴 THE SHELF IS ORGANISED BY PHASE, BECAUSE THE PHASE IS THE ONLY JOIN KEY. (D-552) ──────
 * Andrew: "use phases to organise it… phase 1 article + all area articles + all week recordings in
 * that phase. There should be a search and easy to find each manually."
 *
 * Three kinds of recording — 53 WEEK, 5 PHASE, 60 AREA (D-400 · D-626) — and the ONLY property all three
 * possess is the phase. Every other grouping has to invent a relationship the data does not have.
 *
 * THE GROUPS ARE FOR BROWSING. THE FIELD IS FOR KNOWING. A parent at 3am has already decided what
 * is wrong; she is not browsing. Ship only the groups and a 105-item library becomes a maze. */
.rec-search { display: flex; align-items: center; gap: var(--space-8); height: var(--dim-44); padding: 0 var(--space-12); background: var(--surface-card); border-radius: var(--radius-pill); box-shadow: var(--shadow-card); color: var(--text-tertiary); }
.rec-search svg { width: var(--size-18); height: var(--size-18); flex: none; }
.rec-search input { flex: 1; min-width: 0; border: 0; background: 0; outline: 0; font-family: var(--font-body); font-size: var(--size-14); color: var(--text-primary); }
.rec-search input::placeholder { color: var(--text-tertiary); }
.rec-search:focus-within { outline: var(--focus-ring); outline-offset: var(--focus-offset); }

.rec-body { display: flex; flex-direction: column; gap: var(--space-4); }
.rec-grp { display: flex; flex-direction: column; }
.rec-gh { display: flex; align-items: center; justify-content: space-between; width: 100%; min-height: var(--control-min); padding: var(--space-8) var(--space-4); border: 0; background: 0; cursor: pointer; }
.rec-gh:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
/* 🔴 THE PHASES ARE NUMBERED, AND THEY RUN FIRST → LAST.
 * Andrew: "You need to label the four Phase 1 - XX" — and, in the same pass, "why is WK 52 in
 * phase 1?" IT NEVER WAS: phaseFor(52) is the LAST phase (5 since D-626). But I had reversed the groups (newest-first,
 * like a podcast feed) and left the numbers off, so THE GROUP AT THE TOP OF AN UNNUMBERED LIST IS
 * PHASE 1, whatever the data says. The surface was telling him something the code did not believe.
 * A year with a baby runs forwards; so does this list; and the number is on the label. */
.rec-gname { display: flex; align-items: baseline; gap: var(--space-8); font-family: var(--font-label); font-size: var(--size-12); font-weight: var(--weight-700); letter-spacing: var(--tracking-05); text-transform: uppercase; color: var(--text-secondary); }
.rec-gnum { color: var(--text-tertiary); font-variant-numeric: tabular-nums; }
/* the ONE gold moment on this surface (D-440): where she actually is */
.rec-ghere { font-size: var(--size-10); font-weight: var(--weight-700); letter-spacing: var(--tracking-05); color: var(--gold-700); background: var(--gold-90); border-radius: var(--radius-pill); padding: var(--space-4) var(--space-8); }
.rec-gn { display: flex; align-items: center; gap: var(--space-8); font-family: var(--font-label); font-size: var(--size-12); font-weight: var(--weight-600); color: var(--text-tertiary); font-variant-numeric: tabular-nums; }
/* the caret rotates — REST is ">" and OPEN is "⌄" (D-453): the accordion says which way it goes */
.rec-gn svg { width: var(--size-14); height: var(--size-14); transition: transform var(--duration-200); }
.rec-gh[aria-expanded="true"] .rec-gn svg { transform: rotate(90deg); }
.rec-gh[aria-expanded="false"] + .rec-list { display: none; }

.rec-count { font-family: var(--font-label); font-size: var(--size-12); font-weight: var(--weight-600); color: var(--text-tertiary); margin: 0; }

/* ── 🔴 THE ROW IS SHORTER, AND THE GLYPH IS DOING THE WORK. (D-554) ──────────────────────────
 * Andrew: "make each recording bar shorter and more visually interesting."
 *
 * It was a 72px card with a 40px disc and two lines of text — 105 of them is 7,500px of identical
 * slab. It is now ~56px, and the interest is not decoration: it is the KIND GLYPH. An area read
 * carries its own area's icon (the same one the Toolkit and Progress use), a phase read carries the
 * compass, a week read carries its NUMBER. The eye can now sort the list without reading a word.
 * (D-379: shape says WHAT it is; colour says what STATE it is in — never the other way round.) */
.rec-list { display: flex; flex-direction: column; gap: var(--space-4); margin: var(--space-4) 0 var(--space-8); }
.rec-row { display: flex; align-items: center; gap: var(--space-12); width: 100%; padding: var(--space-8) var(--space-12); background: var(--surface-card); border: 0; border-radius: var(--radius-card); box-shadow: var(--shadow-card); text-align: left; cursor: pointer; }
.rec-row:active { background: var(--surface-card-hover); }
.rec-row:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }

.rec-play { width: var(--dim-32); height: var(--dim-32); flex: none; border-radius: var(--radius-round); background: var(--accent); color: var(--text-on-accent); display: flex; align-items: center; justify-content: center; cursor: pointer; }
.rec-play svg { width: var(--size-12); height: var(--size-12); margin-left: var(--nudge-2); }
.rec-play:active { opacity: 0.8; }
.rec-play:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
.rec-ic-pause { display: none; }
.rec-ic-pause svg { margin-left: 0; }
.rec-row.is-playing .rec-ic-play { display: none; }
.rec-row.is-playing .rec-ic-pause { display: flex; }
/* colour = STATE. The row that is sounding is the only teal thing in the list. */
.rec-row.is-playing { box-shadow: var(--shadow-card), inset 0 0 0 2px var(--accent); } /* token-exception: the playing row */
.rec-row.is-playing .rec-t { color: var(--accent); }

.rec-mid { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--space-4); }
.rec-wk { display: flex; align-items: center; gap: var(--space-4); font-family: var(--font-label); font-size: var(--size-10); font-weight: var(--weight-700); letter-spacing: var(--tracking-05); text-transform: uppercase; color: var(--text-tertiary); }
.rec-g { display: flex; align-items: center; justify-content: center; width: var(--size-14); height: var(--size-14); flex: none; color: var(--accent); }
.rec-g svg { width: var(--size-14); height: var(--size-14); }
/* the week has no glyph, because the week IS one: the number is the icon */
.rec-wn { font-family: var(--font-label); font-size: var(--size-10); font-weight: var(--weight-700); font-variant-numeric: tabular-nums; }
.rec-t { font-family: var(--font-display); font-size: var(--size-15, 0.9375rem); font-weight: var(--weight-500); color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* token-exception */
.rec-dur { flex: none; font-family: var(--font-label); font-size: var(--size-12); font-weight: var(--weight-600); color: var(--text-tertiary); font-variant-numeric: tabular-nums; }

/* ── 🔴 THE DOCK — WHAT SHE SEES WHEN SHE PRESSES PLAY. (D-554) ───────────────────────────────
 * Andrew: "What happens when you click play? What do people see then?"
 *
 * She sees THIS PAGE. The disc plays it where she stands; the row opens the full player. Throwing
 * her into a full-screen player because she tapped play is the app deciding, on her behalf, that
 * she has finished browsing.
 *
 * ⚠️ AND THIS IS NOT A SECOND PLAYER. It is a third VIEW of the one <audio> element (D-549) — so it
 * cannot disagree with the card or the full player about what is sounding, or where she is in it. */
.rec-dock { position: sticky; bottom: 0; display: flex; align-items: center; gap: var(--space-12); margin-top: auto; padding: var(--space-8) var(--space-12); background: var(--surface-inverse); color: var(--text-on-dark); border-radius: var(--radius-card); box-shadow: var(--shadow-sheet); }
.rec-dock[hidden] { display: none; }
.rec-dtoggle { width: var(--dim-32); height: var(--dim-32); flex: none; border: 0; border-radius: var(--radius-round); background: var(--text-on-dark); color: var(--ink-900); display: flex; align-items: center; justify-content: center; cursor: pointer; }
.rec-dtoggle svg { width: var(--size-12); height: var(--size-12); margin-left: var(--nudge-2); }
.rec-dtoggle:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
.rec-dock .rec-ic-pause { display: none; }
.rec-dock.is-playing .rec-ic-play { display: none; }
.rec-dock.is-playing .rec-ic-pause { display: flex; }
.rec-dmid { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--space-4); border: 0; background: 0; padding: 0; text-align: left; color: inherit; cursor: pointer; }
.rec-dmid:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
.rec-dlabel { font-family: var(--font-label); font-size: var(--size-10); font-weight: var(--weight-700); letter-spacing: var(--tracking-05); text-transform: uppercase; color: var(--gold-200); }
.rec-dt { font-family: var(--font-display); font-size: var(--size-14); font-weight: var(--weight-500); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rec-dleft { flex: none; font-family: var(--font-label); font-size: var(--size-11); font-weight: var(--weight-600); color: rgba(255,255,255,.6); font-variant-numeric: tabular-nums; } /* token-exception: on the ink dock */
.rec-dbar { position: absolute; left: var(--space-12); right: var(--space-12); bottom: var(--space-4); height: 2px; background: rgba(255,255,255,.2); border-radius: var(--radius-pill); overflow: hidden; } /* token-exception */
.rec-dbar span { display: block; height: 100%; width: 0; background: var(--text-on-dark); transition: width var(--duration-200) linear; }

/* 🔴 ONE RECORDING, AND IT SAYS ONE. A shelf with one book on it is a shelf with one book on it —
 * we do not pad it out to look like a catalogue. */
.rec-note { margin-top: var(--space-12); font-size: var(--size-14); line-height: var(--leading-150); color: var(--text-tertiary); }

/* "Playing on Kitchen HomePod" — a parent whose phone has gone quiet because the sound is in
 * another room should not have to work that out for herself. Empty when she is on the phone. */
.lsn-route-now { font-family: var(--font-label); font-size: var(--size-12); font-weight: var(--weight-600); color: var(--gold-200); }
.lsn-route-now:empty { display: none; }

/* ── 🔴 THE LOCK SCREEN IS A SURFACE. (D-549k) ────────────────────────────────
 * Andrew: "i also need to see what appears on lock screen."
 *
 * It is the surface a parent sees MOST — she presses play, puts the phone in her pocket, and every
 * time she glances at it for the next four minutes THIS is BabyWeeks. It is also the one surface we
 * do not draw: iOS renders it from `navigator.mediaSession.metadata`, and it will render EXACTLY
 * what we put there — including nothing.
 *
 * ⚠️ The frame below is NOT a mock-up. It reads the LIVE MediaSession object and shows what iOS has
 * been handed: title, artist, artwork. If it looks wrong here, it is wrong on her phone. */
.lok { position: relative; height: 100%; background: linear-gradient(160deg, #2b3a33 0%, #1a2420 100%); color: #fff; display: flex; flex-direction: column; padding: var(--space-24) var(--space-20); } /* token-exception: iOS chrome, not our palette */
.lok-clock { text-align: center; margin-top: var(--space-24); }
.lok-time { font-family: -apple-system, system-ui, sans-serif; font-size: 68px; font-weight: 300; line-height: 1; letter-spacing: -2px; } /* token-exception: this is APPLE's type, not ours — the point is fidelity */
.lok-date { font-family: -apple-system, system-ui, sans-serif; font-size: 15px; opacity: .85; margin-top: 4px; } /* token-exception */
.lok-np { margin-top: auto; background: rgba(255,255,255,.14); backdrop-filter: blur(20px); border-radius: 16px; padding: 12px; display: flex; align-items: center; gap: 12px; } /* token-exception */
.lok-art { width: 56px; height: 56px; border-radius: 8px; flex: none; background: rgba(255,255,255,.12); object-fit: cover; } /* token-exception */
.lok-art.lok-missing { display: flex; align-items: center; justify-content: center; font-size: 10px; color: #ff8a8a; text-align: center; font-family: -apple-system, system-ui; } /* token-exception */
.lok-meta { flex: 1; min-width: 0; font-family: -apple-system, system-ui, sans-serif; } /* token-exception */
.lok-t { display: block; font-size: 15px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* token-exception: iOS truncates. So do we — this is a MIRROR, not a design. */
.lok-a { display: block; font-size: 13px; opacity: .7; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* token-exception */
.lok-ctl { display: flex; align-items: center; gap: 10px; } /* token-exception */
.lok-btn { width: 32px; height: 32px; border: 0; background: 0; color: #fff; display: flex; align-items: center; justify-content: center; cursor: pointer; } /* token-exception */
.lok-btn svg { width: 20px; height: 20px; }
.lok-scrub { height: 3px; background: rgba(255,255,255,.25); border-radius: 2px; margin: 10px 2px 2px; overflow: hidden; } /* token-exception */
.lok-scrub span { display: block; height: 100%; width: 0; background: #fff; } /* token-exception */
.lok-note { margin-top: 10px; font-size: 11px; opacity: .6; font-family: -apple-system, system-ui; } /* token-exception */
