/* Read-aloud: the toggle, the floating player, and the reading highlight.
   Behaviour and the reasoning behind it live in web/app/tts.js. */

/* ---- toggle -------------------------------------------------------------
   Same pill as .course-bmk so the lesson meta row keeps one control language;
   it turns brand-coloured while a reading is open, which is the only signal a
   reader has that the player they scrolled away from is still theirs. */
.tts-toggle {
  display: inline-flex; align-items: center; gap: .35rem; cursor: pointer;
  padding: .35rem .7rem; border: 1px solid var(--border); border-radius: var(--r-pill);
  background: var(--surface); color: var(--muted); font: inherit; font-size: .8rem; font-weight: 700;
  transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.tts-toggle svg { width: 15px; height: 15px; }
.tts-toggle:hover { color: var(--text); border-color: color-mix(in srgb, var(--blue) 45%, var(--border)); }
.tts-toggle[aria-pressed="true"] {
  color: var(--blue); border-color: color-mix(in srgb, var(--blue) 55%, var(--border));
  background: color-mix(in srgb, var(--blue) 10%, var(--surface));
}
/* On a question card the toggle sits in the meta line, where the label would
   crowd the topic/ID text on a narrow card — the icon alone carries it. */
.tts-toggle.is-compact { margin-left: auto; padding: .3rem .55rem; }
.tts-toggle.is-compact span { display: none; }
/* .qmeta is a plain block of uppercase, letter-spaced small caps; it becomes a
   row only when it is carrying a control, and the control opts out of the
   inherited casing. */
.qmeta:has(.tts-toggle) { display: flex; align-items: center; gap: .5rem; }
.tts-toggle { text-transform: none; letter-spacing: normal; }
/* In the lesson meta row the listen pill takes the right-hand slot and the
   bookmark follows it, instead of the two splitting the free space between
   them (both carry `margin-left: auto` of their own). */
.course-meta-row .tts-toggle { margin-left: auto; }
.course-meta-row .tts-toggle + .course-bmk { margin-left: 0; }

/* ---- player -------------------------------------------------------------
   Desktop: a panel anchored under the toggle (position set inline by tts.js).
   Mobile: pinned to the bottom edge — see the media query below. */
.tts-player {
  position: fixed; z-index: 60;
  /* Width is set from the widest row rather than guessed: the transport buttons,
     the three speed buttons and the close button are a fixed run, and a hard
     width narrower than that clipped the close button off the right edge. */
  width: max-content; min-width: 244px; max-width: min(300px, calc(100vw - 24px));
  /* Glass: mostly transparent, with the page behind it blurred hard. The player
     floats over the very text it is reading, so an opaque panel would hide a
     chunk of it. The blur is what buys the transparency — it destroys the detail
     of whatever is behind, so the controls keep their edges even over body text;
     `saturate` puts back the colour a wide blur radius washes out, which is what
     makes it read as glass rather than as fog.
     Contrast note: at 23% the panel is barely a fill at all — the ink rides almost
     entirely on the blurred page, so every control that must hold contrast carries
     its own (.tts-main the solid gradient, .tts-rates .is-on its tint, and the rest
     a far more opaque button surface — see below). The panel's own job is now the
     blur, the hairline and the shadow, not the tint. */
  background: color-mix(in srgb, var(--surface) 23%, transparent);
  /* The blur has to rise with the transparency: it is what destroys the detail of
     whatever is behind, and at 23% fill a weaker radius would let body text read
     straight through the controls. */
  -webkit-backdrop-filter: blur(34px) saturate(2.1);
  backdrop-filter: blur(34px) saturate(2.1);
  border: 1px solid color-mix(in srgb, var(--surface) 42%, transparent);
  border-radius: var(--r-lg);
  /* The inset hairline is the lit top edge that sells a pane of glass; the drop
     shadow is deeper than --shadow-lg because a translucent panel needs the
     separation that its own fill no longer provides — and needs more of it the
     less fill there is. */
  box-shadow: 0 16px 48px rgba(16, 24, 40, .24), inset 0 1px 0 color-mix(in srgb, #fff 62%, transparent);
  padding: .5rem .55rem .45rem;
  /* Two columns so the Auto checkbox rides beside the volume control instead of
     costing a fourth row of its own — the panel floats over the text being read,
     so every row it does not need is text it does not cover. */
  display: grid; grid-template-columns: 1fr auto; align-items: center; gap: .34rem;
}
.tts-track, .tts-row:not(.tts-row--vol), .tts-note { grid-column: 1 / -1; }
.tts-row--vol { grid-column: 1; }
.tts-auto { grid-column: 2; justify-self: end; }
:root[data-theme="dark"] .tts-player {
  background: color-mix(in srgb, var(--surface) 28%, transparent);
  border-color: color-mix(in srgb, #fff 14%, transparent);
  box-shadow: 0 16px 48px rgba(0, 0, 0, .55), inset 0 1px 0 color-mix(in srgb, #fff 12%, transparent);
}
/* Firefox before 103 and any engine without backdrop-filter would render the
   panel as plain 50% alpha — i.e. body text straight through the controls. Those
   get the opaque panel instead: transparency is the nice-to-have, legibility is
   not. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .tts-player { background: var(--surface); border-color: var(--border); }
}
/* Somebody who has asked the OS for less transparency, or for more contrast, wants
   exactly what the no-backdrop-filter engines already get — so this is the same
   declaration, not a new design. Worth stating separately rather than folding into the
   @supports above: that query is about capability, this one is about a preference, and
   the day the fallback changes for a browser reason these must not move together.
   Dropping the filter here also drops the 34px blur, which is the most expensive paint
   in the app and sits on a `position: fixed` panel over scrolling text. */
@media (prefers-reduced-transparency: reduce), (prefers-contrast: more) {
  .tts-player {
    background: var(--surface); border-color: var(--border);
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
}
/* The controls sit on glass, so they cannot be as transparent as it is — a button
   whose fill matches its backdrop has no edge at all. They stay well more opaque
   than the panel, which also gives the panel its depth: solid chips on a sheer
   pane, not a uniform wash.
   :not(.tts-main) matters: this selector outranks the bare `.tts-main` rule below
   on specificity, so without the exclusion it repaints the play button white —
   and its icon is white, which made the main control invisible in light theme
   while staying visible in dark. */
.tts-player .tts-btn:not(.tts-main), .tts-player .tts-rates {
  background: color-mix(in srgb, var(--surface) 78%, transparent);
}
.tts-player .tts-track { background: color-mix(in srgb, var(--text) 16%, transparent); }
.tts-x { display: grid; place-items: center; width: 24px; height: 24px; padding: 0; cursor: pointer; border: none; background: transparent; color: var(--muted); border-radius: var(--r-xs); }
.tts-x svg { width: 14px; height: 14px; }
.tts-x:hover { background: var(--surface-2); color: var(--text); }

.tts-track { height: 5px; border-radius: var(--r-xs); background: var(--surface-2); cursor: pointer; overflow: hidden; }
.tts-track > i { display: block; height: 100%; width: 100%; border-radius: inherit; background: var(--blue); transform: scaleX(0); transform-origin: left; }
.tts-time { font-size: .66rem; font-weight: 700; color: var(--muted); font-variant-numeric: tabular-nums; margin-left: auto; white-space: nowrap; }

.tts-row { display: flex; align-items: center; gap: .22rem; }
.tts-btn {
  display: inline-flex; align-items: center; gap: .08rem; justify-content: center;
  min-width: 30px; height: 30px; padding: 0 .28rem; cursor: pointer;
  border: 1px solid var(--border); border-radius: var(--r-sm);
  background: var(--surface); color: var(--text); font: inherit;
}
.tts-btn svg { width: 14px; height: 14px; }
.tts-btn b { font-size: .62rem; font-weight: 800; }
.tts-btn:hover { border-color: var(--muted); }
.tts-main { background-color: var(--grad-solid); background-image: var(--grad-ui); color: var(--brand-ink); border-color: transparent; }
.tts-main svg { width: 15px; height: 15px; }
.tts-main:hover { filter: brightness(1.06); }

.tts-rates { display: inline-flex; margin-left: auto; border: 1px solid var(--border); border-radius: var(--r-sm); overflow: hidden; }
.tts-rates button {
  cursor: pointer; border: none; background: var(--surface); color: var(--muted);
  font: inherit; font-size: .66rem; font-weight: 800; padding: .34rem .22rem; min-width: 28px;
}
.tts-rates button + button { border-left: 1px solid var(--border); }
.tts-rates button.is-on { background: color-mix(in srgb, var(--blue) 14%, var(--surface)); color: var(--blue); }

/* volume row */
.tts-row--vol { gap: .35rem; }
.tts-volbtn { display: grid; place-items: center; width: 24px; height: 24px; flex: none; padding: 0; cursor: pointer; border: none; background: transparent; color: var(--muted); border-radius: var(--r-xs); }
.tts-volbtn svg { width: 15px; height: 15px; }
.tts-volbtn:hover { color: var(--text); }
.tts-volbtn[aria-pressed="true"] { color: var(--bad); }
/* Deliberately not full-width: volume is a set-and-forget control, and a long
   slider next to a 30px transport button reads as the most important thing on
   the panel, which it is not. */
.tts-vol { flex: 0 1 64px; min-width: 0; height: 18px; cursor: pointer; }
/* Styled track (2026-09-14): the bare `accent-color` range showed the platform's own control —
   Chrome's blue pill on Mac, a grey bar on Android — and no filled portion. Now a 4px rail with
   the filled part in --blue up to --val (set inline by tts.js on every input), and a round
   thumb in the same blue with a white ring so it reads on both themes. The two vendor blocks
   have to be written twice — a shared selector list invalidates the whole rule in each engine. */
.tts-vol { -webkit-appearance: none; appearance: none; background: transparent; }
.tts-vol::-webkit-slider-runnable-track { height: 4px; border-radius: 999px;
  background: linear-gradient(90deg, var(--blue) var(--val, 80%), var(--border) var(--val, 80%)); }
.tts-vol::-moz-range-track { height: 4px; border-radius: 999px; background: var(--border); }
.tts-vol::-moz-range-progress { height: 4px; border-radius: 999px; background: var(--blue); }
.tts-vol::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 14px; height: 14px; margin-top: -5px;
  border-radius: 50%; background: var(--blue); border: 2px solid var(--surface); box-shadow: 0 1px 3px rgba(0,0,0,.25); }
.tts-vol::-moz-range-thumb { width: 14px; height: 14px; border-radius: 50%; background: var(--blue);
  border: 2px solid var(--surface); box-shadow: 0 1px 3px rgba(0,0,0,.25); }
.tts-vol:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; border-radius: 999px; }

.tts-auto { display: flex; align-items: center; gap: .35rem; font-size: .7rem; font-weight: 650; color: var(--muted); cursor: pointer; }
.tts-auto input { accent-color: var(--blue); width: 13px; height: 13px; }
.tts-note { margin: 0; font-size: .66rem; line-height: 1.4; color: var(--muted); border-top: 1px solid var(--border); padding-top: .35rem; }
.tts-link { color: var(--blue); text-decoration: underline; cursor: pointer; }

/* ---- reading highlight --------------------------------------------------
   A tinted left rail rather than a background wash: the questions and course
   body already use background colour to mean "correct/wrong" and "callout", so
   a fourth wash would collide with those meanings. */
.tts-reading {
  background: color-mix(in srgb, var(--blue) 9%, transparent);
  box-shadow: -.55rem 0 0 color-mix(in srgb, var(--blue) 9%, transparent), inset 3px 0 0 var(--blue);
  border-radius: 0 var(--r-xs) var(--r-xs) 0;
  transition: background .2s ease, box-shadow .2s ease;
}
tr.tts-reading { box-shadow: inset 3px 0 0 var(--blue); }
.opt.tts-reading { box-shadow: inset 0 0 0 2px var(--blue); background: color-mix(in srgb, var(--blue) 8%, transparent); }

@media (max-width: 720px) {
  /* A panel tethered to a button is unusable at 360px, so the player becomes a
     bottom sheet — thumb-reachable, and out of the way of the text being read.
     `!important` because tts.js writes the desktop anchor position inline. */
  .tts-player {
    left: 0 !important; right: 0; top: auto !important; bottom: 0;
    width: auto; min-width: 0; max-width: none; border-radius: var(--r-lg) var(--r-lg) 0 0;
    border-left: none; border-right: none; border-bottom: none;
  }
  /* The sheet sits over the text being read, so its height is a direct cost —
     hence the tighter gap here, on top of the two-column layout the base rule
     already gives it. Transport buttons stay at the 44px tap target. */
  .tts-player { gap: .28rem; padding: .4rem 1rem calc(.4rem + env(safe-area-inset-bottom)); }
  .tts-btn { min-width: 44px; height: 44px; }
  .tts-rates button { padding: .6rem .5rem; min-width: 42px; }
  .tts-x { width: 40px; height: 40px; }
  .tts-volbtn { width: 32px; height: 32px; }
  .tts-vol { flex: 0 1 104px; height: 24px; }
  .tts-toggle.is-compact span { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .tts-reading, .tts-track > i, .tts-toggle { transition: none; }
}
