/* Tutor — "Teacher explains" read-aloud card. Pairs with teacher-voice.js.
   [2026-09-12] Sits directly under the page <h1> on every tutor page. Same language as
   the chapter cards around it: white, slate-200 border, orange accent, rounded-xl.
   Every selector is tv-prefixed so the shell's generic names (.card/.hero) never answer. */
.tv-card {
  --tv-h: 2.4rem;      /* [2026-09-16] one height for every control in the row: teacher pills, speed, voice */
  background: #fff;
  border: 1px solid #e2e8f0;
  border-radius: 0.9rem;
  padding: 0.5rem 0.65rem;
  margin: 0 0 1.25rem;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
  font-family: inherit;
  color: #0f172a;
  container-type: inline-size;
  position: relative;
}

/* [2026-09-15] One toolbar row. Pawan: "occupies 3 rows and looks unorganized — make sure it occupies
   1 row only". [2026-09-16] "use the button size of male teacher / female teacher for slow medium fast
   too": every control is the same pill now — .tv-teacher, .tv-speed button and .tv-vpill share one
   height (--tv-h), font and radius; the captions are gone and a hairline separates the three groups.
   The head shrinks first (sub-line, then title) so the controls stay on one line down to ≈760px of
   card; only under 640px does the row stack. */
.tv-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.9rem; }
.tv-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.tv-head { display: flex; align-items: center; gap: 0.6rem; flex: 1 1 0; min-width: 0; margin: 0; }
.tv-icon {
  flex: 0 0 auto; width: var(--tv-h); height: var(--tv-h); border-radius: 0.65rem;
  background: linear-gradient(145deg, #fff7ed, #ffedd5); border: 1px solid #fed7aa;
  display: flex; align-items: center; justify-content: center; font-size: 1.1rem;
}
.tv-titles { min-width: 0; overflow: hidden; }
.tv-title { font-weight: 900; font-size: 0.92rem; line-height: 1.2; color: #0f172a; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tv-foot { display: flex; align-items: baseline; gap: 0 0.5rem; min-width: 0; margin-top: 0.1rem; font-size: 0.7rem; line-height: 1.35; color: #64748b; white-space: nowrap; }
.tv-sub, .tv-status, .tv-voice { overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.tv-status, .tv-voice { color: #94a3b8; }
.tv-status:empty, .tv-voice:empty { display: none; }
/* The status / voice note takes over the small line the moment it has something to say. */
.tv-foot:has(.tv-status:not(:empty), .tv-voice:not(:empty)) .tv-sub { display: none; }

/* The control cluster: teachers · speed · voice, right-aligned, never wrapping inside itself. */
.tv-ctl { display: flex; flex: 0 0 auto; align-items: center; gap: 0.4rem; margin-left: auto; }
.tv-teachers { display: flex; flex: 0 0 auto; gap: 0.4rem; }
.tv-speed { display: inline-flex; gap: 0.3rem; margin-left: 0.35rem; padding-left: 0.75rem; border-left: 1px solid #e2e8f0; }
.tv-vwrap { position: static; margin-left: 0.35rem; padding-left: 0.75rem; border-left: 1px solid #e2e8f0; }

/* ONE shape for every control — a rounded square ([2026-09-16] Pawan: "keep the same shapes on desktop
   as well", after the phone bar). Only the colours differ per family. */
.tv-teacher, .tv-speed button, .tv-vpill {
  box-sizing: border-box; height: var(--tv-h);
  display: inline-flex; align-items: center; gap: 0.4rem; white-space: nowrap;
  padding: 0 0.85rem; border: 1.5px solid; border-radius: 0.55rem;
  font: inherit; font-weight: 800; font-size: 0.84rem; line-height: 1; cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s, transform 0.1s, box-shadow 0.15s;
  -webkit-tap-highlight-color: transparent;
}
.tv-teacher:active, .tv-speed button:active, .tv-vpill:active { transform: translateY(1px); }
.tv-teacher:focus-visible, .tv-speed button:focus-visible, .tv-vpill:focus-visible { outline: 3px solid #fdba74; outline-offset: 2px; }

/* Teacher pills: the orange family. */
.tv-teacher { padding-left: 0.3rem; border-color: #fdba74; background: #fff7ed; color: #9a3412; }
.tv-teacher:hover { background: #ffedd5; border-color: #fb923c; }
.tv-teacher.tv-active { background: #ea580c; border-color: #ea580c; color: #fff; box-shadow: 0 4px 12px rgba(234, 88, 12, 0.28); }
.tv-avatar {
  width: calc(var(--tv-h) - 0.6rem); height: calc(var(--tv-h) - 0.6rem); border-radius: 0.4rem; background: #fff; border: 1px solid #fed7aa;
  display: inline-flex; align-items: center; justify-content: center; font-size: 1.05rem; flex: 0 0 auto;
}
.tv-teacher.tv-active .tv-avatar { border-color: rgba(255, 255, 255, 0.6); }
.tv-tlabel { display: inline-flex; align-items: baseline; gap: 0.35rem; }
.tv-tname { font-weight: 900; }
.tv-tplay { position: relative; font-size: 0.62rem; opacity: 0.8; }

/* Speed pills: the slate family; the active one is solid. */
.tv-speed button { border-color: #e2e8f0; background: #f8fafc; color: #475569; }
.tv-speed button:hover { color: #0f172a; background: #fff; border-color: #cbd5e1; }
.tv-speed button.tv-active { background: #0f172a; border-color: #0f172a; color: #fff; box-shadow: 0 1px 3px rgba(15, 23, 42, 0.25); }
.tv-speed .tv-speed-toggle { display: none; }   /* phones only — see the 640px block */

/* Head shrinks before the controls wrap: sub-line first, then the title (the card keeps its aria-label). */
@container (max-width: 1000px) { .tv-foot { display: none; } }
@container (max-width: 940px) { .tv-titles { display: none; } .tv-head { flex: 0 0 auto; } }

/* [2026-09-16] Topic page: the title and the card share one band (teacher-voice.js wraps the
   chapter <header> and the card in .tv-hero-row) — "look at the blank space on right of
   Mathematics … make sure it won't go waste". The card keeps its natural width and the title
   takes every spare pixel (grow 999 vs 1), so there is never a hole between the 🎧 and the
   controls; a long title wraps its lines rather than push the card off the band. The row is the
   size container here (the card gives up its own), so the card's caption queries above still
   work, measured against the row: on a shared line (row ≥ 70rem ≈ title 22rem + gap + the
   733px of icon + controls) the captions go and the 🎧 stands for the card; where the row is
   narrower flex-wrap drops the card under the title at full width — the layout every page had
   before — and the captions return with the room. The <header>'s own Tailwind margin
   (mb-6 / sm:mb-8) moves onto the row so the band keeps one gap to the columns beneath. */
.tv-hero-row { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem 2rem; margin: 0 0 1.5rem; container-type: inline-size; }
.tv-hero-row > header { flex: 999 1 22rem; min-width: 0; margin: 0; }
.tv-hero-row > .tv-card { flex: 1 0 auto; margin: 0; container-type: normal; }
@container (min-width: 70rem) { .tv-hero-row .tv-titles { display: none; } .tv-hero-row .tv-head { flex: 0 0 auto; } }
@media (min-width: 640px) { .tv-hero-row { margin-bottom: 2rem; } }

/* Player strip: only present while playing / paused. */
.tv-player { display: none; margin-top: 0.75rem; padding-top: 0.7rem; border-top: 1px dashed #e2e8f0; }
.tv-card.tv-playing .tv-player { display: block; }
.tv-controls { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.tv-btn {
  font: inherit; font-size: 0.78rem; font-weight: 800; padding: 0.4rem 0.75rem;
  border: 1px solid #e2e8f0; border-radius: 0.55rem; background: #f8fafc; color: #0f172a; cursor: pointer;
}
.tv-btn:hover { background: #f1f5f9; border-color: #cbd5e1; }
.tv-pause { background: #fff7ed; border-color: #fed7aa; color: #9a3412; }
.tv-card.tv-paused .tv-pause { background: #ea580c; border-color: #ea580c; color: #fff; }
.tv-nowwrap { margin-top: 0.55rem; font-size: 0.82rem; color: #334155; }
.tv-nowlbl { font-size: 0.66rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: #ea580c; margin-right: 0.2rem; }
.tv-now { font-weight: 700; }
.tv-progress { height: 4px; border-radius: 999px; background: #f1f5f9; margin-top: 0.5rem; overflow: hidden; }
.tv-bar { height: 100%; width: 0; background: linear-gradient(90deg, #fb923c, #ea580c); transition: width 0.4s; }

.tv-unsupported .tv-teacher, .tv-unsupported .tv-speed { opacity: 0.45; pointer-events: none; }

/* Section being explained — a soft outline that follows the teacher down the page. */
.tv-reading { position: relative; }
article.tv-reading { border-left-color: #ea580c !important; }
section.tv-reading, article.tv-reading, header.tv-reading {
  box-shadow: 0 0 0 3px #ffedd5, 0 0 0 4px #fdba74;
  border-radius: 0.75rem;
  transition: box-shadow 0.3s;
}
header.tv-reading { padding: 0.35rem 0.5rem; margin-left: -0.5rem; margin-right: -0.5rem; }

/* Per-topic "Explain" button, sits in the topic's header row. */
.tv-sec-btn {
  margin-left: auto; flex: 0 0 auto;
  font: inherit; font-size: 0.7rem; font-weight: 800; letter-spacing: 0.02em;
  padding: 0.28rem 0.6rem; border-radius: 0.5rem;
  border: 1px solid #fed7aa; background: #fff7ed; color: #9a3412; cursor: pointer; white-space: nowrap;
}
.tv-sec-btn:hover { background: #ffedd5; border-color: #fb923c; }
.tv-sec-btn.tv-active { background: #ea580c; border-color: #ea580c; color: #fff; }

/* Mini player: fixed at the bottom while the card is scrolled away and the teacher is
   talking. Below the shell's chrome band (9000+) and clear of its bottom-right FABs. */
.tv-mini {
  position: fixed; left: 50%; bottom: 1rem; transform: translateX(-50%);
  z-index: 8000; max-width: calc(100vw - 2rem); width: max-content;
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.45rem 0.6rem 0.45rem 0.7rem;
  background: #0f172a; color: #fff; border-radius: 0.8rem;
  box-shadow: 0 10px 30px rgba(15, 23, 42, 0.35);
  font-size: 0.8rem;
}
.tv-mini[hidden] { display: none !important; }
.tv-mini-av { font-size: 1.3rem; line-height: 1; }
.tv-mini-txt { display: flex; flex-direction: column; min-width: 0; max-width: 46vw; }
.tv-mini-lbl { white-space: nowrap; font-size: 0.58rem; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; color: #fdba74; }
.tv-mini-now { font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tv-mini .tv-btn { background: rgba(255, 255, 255, 0.1); border-color: rgba(255, 255, 255, 0.18); color: #fff; padding: 0.35rem 0.6rem; }
.tv-mini .tv-btn:hover { background: rgba(255, 255, 255, 0.2); }

/* [2026-09-15] Voice pill + menu — the single control for accent AND voice, in the row.
   [2026-09-16] The menu is grouped Female / Male; each row is a roster voice with a one-line note.
   The menu is absolute inside the card (position:relative above). */
.tv-vpill { max-width: 13rem; border-color: #e2e8f0; background: #fff; color: #0f172a; padding-right: 0.65rem; }
.tv-vpill:hover, .tv-menu-open .tv-vpill { border-color: #fdba74; background: #fff7ed; }
.tv-vflag { font-size: 1rem; line-height: 1; }
.tv-vname { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tv-vcaret { font-size: 0.7rem; color: #94a3b8; }
.tv-menu {
  position: absolute; top: calc(100% + 8px); left: 0; z-index: 60; width: 21rem; max-width: calc(100% - 16px);
  max-height: 22rem; overflow: auto;
  background: #fff; border: 1px solid #e2e8f0; border-radius: 0.9rem; padding: 0.45rem;
  box-shadow: 0 18px 44px -14px rgba(15, 23, 42, 0.28), 0 2px 6px rgba(15, 23, 42, 0.06);
  color: #0f172a; font-size: 0.8rem; text-align: left;
}
.tv-menu[hidden] { display: none !important; }
.tv-menu-grp + .tv-menu-grp { margin-top: 0.35rem; border-top: 1px solid #f1f5f9; padding-top: 0.35rem; }
.tv-menu-hd { font-size: 0.66rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: #64748b; padding: 0.25rem 0.5rem 0.3rem; }
.tv-menu-none, .tv-menu-note { font-size: 0.7rem; color: #94a3b8; padding: 0.2rem 0.5rem 0.35rem; }
.tv-menu-note { color: #b45309; padding: 0.35rem 0.5rem; }
.tv-menu-v {
  display: flex; align-items: center; gap: 0.5rem; padding: 0.35rem 0.3rem 0.35rem 0.55rem;
  border-radius: 0.55rem; cursor: pointer; transition: background 0.12s;
}
.tv-menu-v:hover { background: #fff7ed; }
.tv-menu-v.tv-active { background: #fff7ed; box-shadow: inset 0 0 0 1.5px #ea580c; }
.tv-menu-v.tv-active .tv-menu-vname::before { content: "✓ "; color: #ea580c; }
.tv-menu-vtxt { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.tv-menu-vname { font-weight: 800; font-size: 0.8rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tv-menu-vtag { font-size: 0.66rem; color: #64748b; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tv-menu-prev { flex: 0 0 auto; width: 1.75rem; height: 1.75rem; border-radius: 50%; border: 1px solid #fed7aa; background: #fff; color: #ea580c; font: inherit; font-size: 0.65rem; cursor: pointer; }
.tv-menu-prev:hover { background: #ea580c; border-color: #ea580c; color: #fff; }

@media (max-width: 640px) {
  /* [2026-09-16] Pawan: "in mobile have it at the bottom of the screen and all in one row — mobile
     already has a space crunch and this is occupying too much". On a phone the card leaves the page
     flow and becomes a fixed bar along the bottom edge, one row: teacher avatars · Slow Med Fast ·
     voice. While the teacher talks the voice pill gives way to ⏭ and ■, a 3px progress line runs
     along the bar's top edge, and the active avatar carries a ❚❚ / ▶ badge (tap it to pause or
     resume). The page follows the teacher anyway — the section being read is outlined and scrolled
     into view — so the "Now explaining" caption is not missed, and the mini player is redundant.
     body.tv-mounted (set by mount()) reserves the bar's height under the page so the last lines and
     the page's own sticky chip are never hidden behind it. */
  :root { --tv-bar-h: 3.65rem; }   /* 44px shell tap-target buttons + 0.4rem padding each side + hairline */
  body.tv-mounted { padding-bottom: calc(var(--tv-bar-h) + env(safe-area-inset-bottom, 0px)) !important; }
  body.tv-mounted .sticky.bottom-4 { bottom: calc(var(--tv-bar-h) + 1rem); }
  body.tv-mounted .sticky.bottom-4:not(:has(a, button)) { display: none; }   /* the topic page's chip renders empty on phones */
  body.tv-dict .content > .tv-card { margin: 0 !important; }   /* its own rule below is later in the file */
  .tv-card {
    --tv-h: 2.3rem;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 8000; margin: 0;
    border-radius: 0; border: 0; border-top: 1px solid #e2e8f0;
    padding: 0.4rem 0.5rem calc(0.4rem + env(safe-area-inset-bottom, 0px));
    box-shadow: 0 -8px 24px rgba(15, 23, 42, 0.10);
    display: flex; align-items: center; gap: 0.3rem;
  }
  /* The row, the control cluster and the player strip all dissolve into the bar's one flex line. */
  .tv-row, .tv-ctl, .tv-controls { display: contents; }
  .tv-card.tv-playing .tv-player { display: contents; }
  .tv-head, .tv-pause, .tv-nowwrap, .tv-mini { display: none !important; }
  .tv-teachers { order: 1; gap: 0.3rem; }
  .tv-next { order: 2; } .tv-stop { order: 3; }
  .tv-speed { order: 4; margin-left: auto; padding-left: 0; border: 0; gap: 0.2rem; }
  .tv-vwrap { order: 5; margin: 0; padding: 0; border: 0; }
  .tv-card.tv-playing .tv-vwrap { display: none; }
  /* Pawan: "the circle shape should be square with mildly rounded border" — every control on the
     bar is a rounded square here (the desktop keeps its pills). */
  .tv-teacher, .tv-speed button, .tv-vpill, .tv-next, .tv-stop, .tv-avatar { border-radius: 0.55rem; }
  .tv-avatar { border-radius: 0.4rem; }
  /* Teacher tiles: avatar only, dead-centre, with a play-state badge on the active one. Pawan:
     "border orange, inner transparent or white" — so no orange fill here; the active tile has the
     deeper orange border and a soft ring, the idle one the pale border. */
  .tv-teacher { padding: 0; width: 2.75rem; justify-content: center; position: relative; background: #fff; border-color: #fdba74; }
  .tv-teacher:hover { background: #fff; border-color: #fb923c; }
  .tv-teacher.tv-active { background: #fff; border-color: #ea580c; border-width: 2px; color: #9a3412; box-shadow: 0 0 0 3px #ffedd5; }
  .tv-teacher .tv-tlabel { display: none; }
  .tv-avatar, .tv-teacher.tv-active .tv-avatar { width: auto; height: auto; border: 0; background: transparent; font-size: 1.35rem; line-height: 1; }
  .tv-teacher.tv-active::after {
    content: "▶"; position: absolute; right: -3px; bottom: -3px; width: 1rem; height: 1rem; border-radius: 0.3rem;
    background: #0f172a; color: #fff; font-size: 0.45rem; line-height: 1; display: flex; align-items: center; justify-content: center;
    border: 1.5px solid #fff;
  }
  .tv-card.tv-playing .tv-teacher.tv-active::after { content: "❚❚"; }
  .tv-card.tv-paused .tv-teacher.tv-active::after { content: "▶"; }
  /* Speed is one toggle here: ⏱ Medium → tap → ⏱ Fast → ⏱ Slow. Dark like the active pill on desktop. */
  .tv-speed button[data-speed] { display: none; }
  .tv-speed .tv-speed-toggle { display: inline-flex; padding: 0 0.7rem; font-size: 0.78rem; background: #0f172a; border-color: #0f172a; color: #fff; }
  .tv-speed-toggle:hover { background: #1e293b; border-color: #1e293b; color: #fff; }
  .tv-stval { min-width: 3.2em; text-align: left; }   /* Slow / Medium / Fast: the button keeps one width while it cycles */
  .tv-vpill { padding: 0 0.45rem 0 0.5rem; max-width: 9.5rem; }
  .tv-next, .tv-stop { box-sizing: border-box; height: var(--tv-h); padding: 0 0.6rem; border-radius: 0.55rem; font-size: 0.8rem; white-space: nowrap; }
  .tv-next .tv-btn-txt, .tv-stop .tv-btn-txt { display: none; }
  .tv-progress { position: absolute; top: -1px; left: 0; right: 0; height: 3px; margin: 0; border-radius: 0; background: #ffedd5; }
  /* The voice menu opens upward, full width of the bar. */
  /* Opens upward; the right gutter keeps its ▶ previews clear of the shell's floating button column. */
  .tv-menu { top: auto; bottom: calc(100% + 6px); left: 0.5rem !important; right: 4.25rem; width: auto; max-width: none; max-height: 60vh; }
}
@media (max-width: 360px) {
  .tv-card { gap: 0.25rem; padding-left: 0.4rem; padding-right: 0.4rem; } .tv-teacher { padding: 0 0.15rem; }
  .tv-vpill .tv-vname { display: none; }   /* 320px: flag + caret only; the menu shows the name */
}
@media print { .tv-card, .tv-mini, .tv-sec-btn { display: none !important; } }

/* [2026-09-15] Dictionary word page (dictionary/index.php). The card is the first block of
   .content, right under the hero; the older single-voice "Read all" pill retires in its favour. */
body.tv-dict .bd-readall { display: none !important; }
body.tv-dict .content > .tv-card { margin: 0 0 1.5rem; }
body.tv-dict .section-header { position: relative; }
body.tv-dict .section-header .tv-sec-btn { margin-left: 0.75rem; }
body.tv-dict .section.tv-reading { box-shadow: none; border-radius: 0; }
body.tv-dict .section.tv-reading .section-header { background: #fef3c7; border-radius: 6px; transition: background 0.3s; }
