/* PANIM — player.css  (Direction B — "The Plate")
   The transport bar. It follows the book's paper rather than staying night-dark:
   on a light page a black bar reads as a browser chrome bar bolted to the bottom,
   not as part of the object. Every colour below is derived from --paper / --ink /
   --accent, which js/motion.js keeps current with the chapter you are in. */

.player {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 900;
  background: var(--paper);
  border-top: 1px solid var(--rule-strong);
  color: var(--ink);
  font-family: var(--ui);
  /* ---------------------------------------------------------------------------
     THE BAR IS LIFTED OFF THE BOTTOM EDGE, 2026-09-07.
     The seek track was the LAST thing in the bar and the bar sat at bottom:0 with
     viewport-fit=cover, so on a phone the track lived inside the home-indicator
     gesture strip: a drag across it is claimed by iOS before the page ever sees a
     pointermove, and scrolling near the bottom of the screen caught the bar
     instead of the prose. --player-pad is that clearance, and it is the ONLY
     place the number lives -- --player-h below adds the same token so anything
     pinned above the bar (js/sync.js's readable band, the back-to-top control in
     components.css, scroll-padding-bottom in site.css) travels with it.
     env() is 0 on a desktop browser, so the max() floor is what actually raises
     the bar on a phone whose bottom toolbar is showing and reporting no inset.
     --------------------------------------------------------------------------- */
  padding-bottom: var(--player-pad);
}
/* both rows sit on the same measure as the page, so the transport lines up with
   the text column instead of running edge to edge under it */
.player-controls, .player-seek {
  max-width: var(--shell); margin-inline: auto; padding-inline: var(--edge);
}

.player-controls {
  display: flex; align-items: center; gap: .7rem;
  padding-block: .4rem;
  min-height: 64px;
}

.player-transport { display: flex; align-items: center; gap: .45rem; }
/* 🛑 `.player-transport .btn-icon` CAME OFF 2026-09-07 WITH THE MARKUP IT SIZED. The
   two skips were `.btn .btn-icon` carrying the strings "−15" and "+30"; they are
   .skip-mark now (css/components.css), which brings its own 44px box. The gap opened
   from .25rem to .45rem in the same edit — three drawn circles in a row need air
   between them where two words and a circle did not. */
/* THE TRANSPORT IS DRAWN, NOT TYPED, 2026-08-28.
   Play and pause were the text characters ▶ and ❚❚, set in whatever the font stack
   happened to have: two different weights on two different platforms, a vertical
   centring that drifted, and no relation to the Listening Room's transport, which
   was always SVG. These are the room's own two paths and the room's own class
   switch (js/player.js reflectPlaying).

   ONE COMPONENT, 2026-08-29. The rules that used to sit here are now
   .transport-play in components.css, shared with the Listening Room's play button.
   This bar's instance is the default size, so it declares nothing at all. */

/* THE TWO DRAWN MARKS ON THE BAR. Both stroked in the current ink so they inherit
   the chapter's paper like every other control here, and both on the same 19px box
   so they sit on one optical line beside the 1x and the word Follow.
   The crescent is the Sleep timer and the lamp is the Listening Room — swapped
   2026-08-29 (D14-B), because the moon had been pointing at the wrong one. */
#sleep-btn, #room-btn { display: grid; place-items: center; }
#sleep-btn svg, #room-btn svg { width: 19px; height: 19px; display: block; }

.player-meta {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-direction: column; justify-content: center;
  font-family: var(--ui);
}
/* THE ONE PLACE THE BAR SAYS WHERE YOU ARE, and until 2026-08-29 (D14-C) it was set
   at --ap-lg: 13.1px, the apparatus size meant for a caption you lean in to read.
   The player is chrome that has to be legible at arm's length, at night, on a
   nightstand, by somebody who is not looking at it so much as glancing at it — and
   it was the smallest legible type on the page. The title now takes its own step
   above the apparatus scale and the running time follows it up one.
   🛑 These two deliberately do NOT use --ap-*. The apparatus scale is for type set
   inside the reading column, where the measure and the reading distance are the
   book's. A player bar is furniture and is read from further away. */
.player-meta .meta-title {
  font-size: .95rem; font-weight: 500; letter-spacing: .02em; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* 🛑 --ink-soft, NOT `opacity: .6`. Measured 2026-08-29: ink at .6 composites to
   4.31:1 on the ch II stock against a 4.5:1 requirement, and axe caught it at 4.45:1
   on the jacket. The token is 6.01:1 at its worst stock and is the vocabulary the rest
   of the site already uses for quiet text — an opacity is an unmeasured colour. */
.player-meta .meta-time {
  font-size: .82rem; color: var(--ink-soft); letter-spacing: .02em;
}
/* 🛑 .meta-status IS GONE, 2026-09-07. The bar has one meta line — #meta-time — and
   js/player.js reads that id and no other. The unavailable state says what it is
   through the transport and the seek bar below, both of which are styled for it. */

/* FOLLOW HAD NO SIGHTED STATE AT ALL until 2026-08-29. js/player.js has always
   toggled .is-active on this button and nothing in any stylesheet matched it, so
   Follow-on and Follow-off were the same button — while .is-suspended, which is a
   sub-state of ON, was styled. A sighted reader could see the degraded state and not
   the state it degraded from. --accent is what .is-active means everywhere else on
   this site (.nav-chapters a.is-active, .ntr.is-active), and it is on .btn-icon so the
   Room's own Follow button (#room-follow) gets it from the same rule. */
.btn-icon.is-active { color: var(--accent); }

.player-secondary { display: flex; align-items: center; gap: .25rem; }
.player-secondary .btn-icon { min-width: 44px; min-height: 44px; font-size: .85rem; }
#speed-btn { font-family: var(--ui); font-size: var(--ap-md); min-width: 44px; }

/* Follow is on, but the reader has scrolled ahead and the page has stopped moving
   with the voice (js/sync.js). Left lit, the button claims something untrue; turned
   off, the reader loses the state they are actually in. So it goes quiet and carries
   a hollow marker — still active, not currently driving. Tapping returns to the voice.
   No new colour: this is the apparatus rule, a rule doing the job. */
/* --ink-faint (4.72:1 at the worst stock), not `opacity: .55`, which composited to
   3.69:1 on the ch VII stock. Quieter than the base .btn-icon --ink-soft, and legal. */
#follow-btn.is-suspended { color: var(--ink-faint); }
#follow-btn.is-suspended::after {
  content: ''; display: block; height: 1px; margin-top: 2px;
  background: currentColor; opacity: .5;
}

.player-seek { position: relative; padding-bottom: .5rem; }
.seekbar {
  position: relative;
  height: 3px;
  margin: 19px 0;    /* pads the click/tap zone around the visual track to ~44px tall */
  background: color-mix(in srgb, var(--ink) 14%, transparent);
  cursor: pointer;
  touch-action: none;
}
.seekbar::before {
  content: "";
  position: absolute; left: 0; right: 0; top: 50%; transform: translateY(-50%);
  height: 44px;      /* invisible 44px-tall hit area, WCAG target size, without changing the visual track */
}
.seekbar-fill {
  position: absolute; top: 0; left: 0; height: 100%;
  background: var(--accent);
  width: 0%;
  pointer-events: none;
}
.seekbar-buffered {
  position: absolute; top: 0; left: 0; height: 100%;
  background: color-mix(in srgb, var(--ink) 22%, transparent);
  width: 0%;
  pointer-events: none;
}
/* ---------------------------------------------------------------------------
   THE ROOM'S SEEK IS THIS SEEK
   The Listening Room used to carry its own bar — .room-seek / .room-seek-fill, its
   own track, its own fill, its own focus ring, its own 2px geometry — which is the
   same quantity drawn twice in two idioms. It is the same component now, pinned to
   the bottom edge of the screen instead of sitting inside a bar, and it inherits
   the invisible 44px hit area from .seekbar::before rather than declaring a second
   one. The Room's colours arrive from its own --ink / --accent (css/room.css).
   --------------------------------------------------------------------------- */
.seekbar-edge {
  position: absolute; left: 0; right: 0;
  bottom: max(0px, env(safe-area-inset-bottom));
  margin: 0; height: 2px; z-index: 2;
  /* 20%, not the bar's 14%: this track lies over a photograph, not over paper */
  background: color-mix(in srgb, var(--ink) 20%, transparent);
}
.seekbar-edge:focus-visible { outline: 2px solid var(--accent); outline-offset: -4px; }
/* ---------------------------------------------------------------------------
   THE CHAPTER RAIL — the book index, on its own axis
   These ten marks used to live INSIDE .seekbar. That track measures position in the
   chapter you are listening to, so the two were different quantities drawn on one
   rail: the fill said "55% through chapter I" while the tick at that same 55% meant
   "chapter V", and tapping it changed chapter. Now the position track is only ever
   position, and the index sits above it, labelled, where evenly spaced marks read as
   what they are.
   --------------------------------------------------------------------------- */
/* 🔴 22px, NOT 20px — 2026-09-07. The rail was sized to the 11.5px numeral it used
   to carry (see .seek-mark). The numeral grew and the box had to grow with it, or
   the current chapter's underline sat on the seek bar's own track. */
.chapter-rail {
  position: relative;
  height: 22px;
  margin: 0 0 7px;
}
.seekbar-marks { position: absolute; inset: 0; }

/* THE NUMERAL IS THE MARK, 2026-08-28.
   The rail used to draw a 2px tick AND hang a numeral under it — two marks for one
   chapter, the tick carrying the state and the label carrying the name, so the eye
   had to assemble them. The numeral alone does both jobs and is the thing you were
   going to read anyway. It is also now set in LITERATA: the contents numerals and
   the running head moved out of Archivo months ago (README §3) and this rail was the
   one place left still setting a roman numeral in the apparatus sans, where V and X
   are drawn as capital letters of a grotesk and read as text rather than as number.

   CONTRAST. The label is real text, so the bar is 4.5:1, not the 3:1 a graphical
   tick needed — --ink-faint is exactly 4.5:1 against the darkest paper stock
   (see css/site.css). Read chapters step up to --ink-soft and the current one takes
   --accent plus a hairline, so the three states are ink weight, not colour alone. */
/* 🛑 UNDER 44px, AND DOCUMENTED RATHER THAN FIXED — 2026-08-30 (D16-A). The
   full-page touch-target audit flags these ten and they are the last ten on the
   site; every other sub-44px target is either fixed or is the Index of Scripture's
   citation row, which carries its own note.
   These are exempt under WCAG 2.2 SC 2.5.8 for the same reason that list is:
   **their POSITION is the information.** Each mark sits at its chapter's exact time
   offset along the scrub bar, so growing the box to 44px would (a) overlap its
   neighbours at the chapter boundaries and (b) put the tick somewhere other than
   the moment it names — which changes what the control means rather than making it
   easier to hit. The scrub bar itself is the full-width primary target and it is
   well over the floor; these are a convenience on top of it.
   ⚠️ If they ever stop being decorative shortcuts to a control that is already
   reachable, this exemption stops applying. */
.seek-mark {
  position: absolute; top: 0;
  transform: translateX(-50%);
  padding: 0 .18em 3px;
  background: none; border: 0; cursor: pointer;
  font-family: var(--serif);
  font-variation-settings: var(--lit-normal);
  /* 🔴 .86rem, WAS .72rem — 2026-09-07. The author: "numerals could be bigger on the
     audio player." He is asking the third time for the same thing: the Names index
     letter grew for "the abc … could be bigger its hard to see", the Sources group
     head grew the same day, and this rail is the last small label left. 11.52px of
     roman numeral is the smallest type on the site's furniture, and a roman numeral
     is the hardest kind of small type to read — V, X and I are the same three strokes.
     🛑 THE CEILING IS ARITHMETIC, NOT TASTE. The ten marks are evenly spaced across
     the rail and the rail is hidden below 641px, so the tightest real case is the
     bar at 641px: nine gaps of about 63px carrying "VIII" at its widest. 13.76px
     measures 30px there — it fits with room, and 1rem does not.
     🛑 CONTRAST IS UNCHANGED AND STILL 4.5:1. --ink-faint is exactly the AA floor for
     body text against the darkest stock; growing type never lowers a requirement that
     is already met at the smaller size, so nothing here needs re-measuring. */
  font-size: .86rem; font-weight: 500; font-style: normal;
  letter-spacing: .05em; line-height: 1;
  color: var(--ink-faint);
  border-bottom: 1px solid transparent;
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.seek-mark::before {
  /* 44px-square invisible tap target centred on the numeral */
  content: "";
  position: absolute; top: 50%; left: 50%;
  width: 44px; height: 44px; min-width: 100%;
  transform: translate(-50%, -50%);
}
.seek-mark-label { font-style: normal; }
.seek-mark:hover, .seek-mark:focus-visible { color: var(--ink); }
.seek-mark.is-complete { color: var(--ink-soft); }
.seek-mark.is-current {
  color: var(--accent); font-weight: 600;
  border-bottom-color: var(--accent);
}
/* the end marks sit at 0% and 100%, so a centred numeral would hang off the bar */
.seek-mark:first-child { transform: none; }
.seek-mark:last-child { transform: translateX(-100%); }

.seek-handle {
  position: absolute; top: 50%; width: 11px; height: 11px; margin-left: -5.5px;
  background: var(--ink); border-radius: 50%;
  transform: translateY(-50%);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--paper) 85%, transparent);
}

.player[data-state="unavailable"] .player-transport,
.player[data-state="unavailable"] .seekbar {
  opacity: .45; pointer-events: none;
}

/* ---------------------------------------------------------------------------
   THE BAR HIDES WHEN NOTHING IS PLAYING
   Measured 2026-08-27 at 402x874: the bar is 161.6px on a phone (not the 114px
   it is on desktop -- see the mobile row rules below), which is 18.5% of the
   screen, permanently, spent on the words "Select a chapter to begin" and a dead
   0:00 / 0:00. On a page whose thesis is a book read in daylight, that made the
   most app-like object the most constant one.
   `idle` is the state player.js already sets before anything is loaded and again
   when playback resets, so nothing new has to be tracked. Chapter selection lives
   in the running head (see components.css, .nav-toc) and in the Listening Room,
   so the bar is not the only way in and can leave completely.
   --------------------------------------------------------------------------- */
.player {
  transform: translateY(0);
  transition: transform var(--dur-med) var(--ease);
  will-change: transform;
}
.player[data-state="idle"] {
  transform: translateY(100%);
  pointer-events: none;
}
/* Anything pinned above the bar has to travel with it, or it hangs in mid-air
   over the prose while the bar is gone. --player-h is the single source. */
/* Both measured in a real browser, not estimated: 136px at 1440 and 92px at 402,
   where the rail is hidden. js/sync.js reads this to work out which part of the
   screen the reader can actually see, so a wrong number here makes the read-along
   stop scrolling to lines that are behind the bar.
   🔴 136, NOT 134 — 2026-09-07, and this is the trap the note above always warned
   about. Growing the rail's numerals to .86rem grew the rail from 20px to 22px, and
   the bar with it. The comment said "re-measure if the bar's contents change" and
   the numerals ARE the contents; a type change is a layout change here. Measured
   `#player.getBoundingClientRect().height` at 1440/900/700/641 — 136 at every one —
   rather than adding 2 to the old number and hoping.
   ⚠️ 402 IS UNCHANGED AT 92 + 16 = 108, verified the same way, because the rail is
   display:none below 641px and takes its whole height with it. */
:root {
  --player-pad: env(safe-area-inset-bottom, 0px);
  --player-h: calc(136px + var(--player-pad));
}
@media (max-width: 640px) {                                 /* measured at 402px wide */
  :root {
    --player-pad: max(env(safe-area-inset-bottom, 0px), 16px);
    --player-h: calc(92px + var(--player-pad));
  }
}
body:has(.player[data-state="idle"]) { --player-h: 0px; }
@media (prefers-reduced-motion: reduce) { .player { transition: none; } }

/* ---------------------------------------------------------------------------
   MOBILE: ONE ROW, NOT THREE
   The old rule wrapped .player-meta onto its own full-width row (order:3,
   flex-basis:100%), which is what made the bar TALLER on the device with the
   least room -- 111.6px of controls instead of 64px.
   Speed / Follow / Sleep are not dropped, they are already in the Listening Room
   (#room-speed, #room-sleep, #room-follow, #room-chapters), which is a superset
   of this bar. The Room button stays, so all four remain one tap away.
   --------------------------------------------------------------------------- */
@media (max-width: 640px) {
  .player-controls {
    flex-wrap: nowrap;
    gap: .35rem;
    padding: .25rem .6rem;
    min-height: 56px;
  }
  .player-transport { gap: 0; }
  .player-meta { flex: 1 1 auto; min-width: 0; }
  /* the seek bar directly below already shows position; the Room carries a clock */
  .player-meta .meta-time { display: none; }
  #speed-btn, #follow-btn, #sleep-btn { display: none; }
  .player-seek { padding-bottom: .25rem; }
  .seekbar { margin: 14px 0; }
  /* The chapter rail is 26px, which is a lot of a 92px bar to spend on an index that
     is already in the running head, the Contents and the Listening Room — the same
     argument that drops Speed / Follow / Sleep above. The position track stays. */
  .chapter-rail { display: none; }
}

/* 🛑 THE MIX PANEL (C13) WAS NEVER BUILT, and its three rules came out 2026-09-07.
   There is no mix sheet in index.html and no code that opens one. The one level a
   reader can actually move is the music bed, and that is decided in the master, not
   at playback. */

/* ---------- sleep sheet (C12) ---------- */
.sleep-options { display: grid; grid-template-columns: repeat(2, 1fr); gap: .6em; margin: 1em 0 1.4em; }
.sleep-options .btn.is-active { background: color-mix(in srgb, var(--accent) 30%, transparent); }

/* ---------- completion modal ---------- */
.completion-actions { display: flex; gap: .8em; flex-wrap: wrap; margin-top: 1.4em; }

/* the one-tap offline row at the foot of the chapters sheet — D22-E.
   js/room.js says why it exists. It is a real button, not a hairline control: it
   starts a 400MB download and the reader should be able to see that it is a
   decision. 44px comes from .btn. */
.save-all-row { margin-top: 1.4em; padding-top: 1.2em; border-top: 1px solid var(--rule); }
.save-all-row .btn { width: 100%; justify-content: center; }
/* the other language's audio, under this one's — the same decision, second */
.save-all-row .btn + .btn { margin-top: .6em; }
.save-all-row .sheet-note {
  margin: .7em 0 0;
  font-family: var(--ui); font-size: var(--ap-sm);
  color: var(--ink-faint); line-height: 1.5;
}
