/* live.css - Talk live with Tomo (#/talk, js/screens/talk.js). Phone first and full height: Tomo and what is
   happening at the top, the words in the middle (they scroll, newest at the bottom; before anything is said only
   the one line on what to do and its fold), the big Start/End button centred at the bottom as on a phone call (before
   a call it stands alone, with one quiet line under it that Mute is there, and Tomo, "Ready when you are" and the line
   on what to do stand in the middle of the room above it). Every circle (Start, End, Mute) has its word under it, in
   ink, never inside it, as on a phone call. During a call (data-call=on) Mute and End, one size, are a pair centred
   at the foot, Mute on the left; the call's clock with its own time bar sits over the pair, or, on an upright phone,
   is the bar's (talk.js: app.shell count and progress; the page's own .own-count waits there), whose way out is a
   plain ✕ named "End the call", so the call has one End. Mute is a phone call's: always the slashed microphone and its
   word; pressed (aria-pressed=true, data-muted=true) it fills with ink and says Muted, never colour alone; unmuted, a
   thin (2 px) ring in the line colour grows with what the microphone hears (--lvl, the call's only level meter) and is
   gone in a quiet room, so a live Mute never looks pressed or focused; muted the ring is still. On an upright phone the
   call gives the words the room: Tomo is a small face beside what she
   is doing, and the line under her and the title (kept for screen readers) go. The call fills the
   screen at least (min-height): a note that appears makes the page longer, never squeezes Start off it, and
   the controls stay pinned to the foot of the screen, on a phone above the tab bar (and the offline note,
   --below, set by talk.js); above 720 px the offline note is at the top and the page starts under it (--above). From
   900 px, and on a phone held sideways, the call sits on the left and the words on the right. Toasts show at
   the top of the screen here, clear of the controls. Colours only through the tokens in app.css; nothing
   wider than the screen at 320 px; every control at least 44 px to tap. During a call the page is a session (no tab
   bar: --tab-h is 0 then), so the controls settle on the home indicator. The volume slider is for a computer: on a
   phone (720 px or less, or a touch screen) the phone's own buttons do it, at every width and in either theme. On an
   upright phone the controls are one full-width bar docked at the foot (the dock every session has, study.css) and
   the words, with no box round them, fill the room between Tomo and it; the title is the page's usual h1. */
body.live-on .tutor { display: none; }
body.live-on #toasts { top: calc(var(--bar-h) + env(safe-area-inset-top) + 8px); bottom: auto; }
/* During a call the bar's way out is a plain ✕, 44 px (its name, "End the call", is app.js's): End is said once, on
   the red circle in the dock. */
body.live-on .bar-back.stop { justify-content: center; min-width: var(--tap); padding: 0; }
body.live-on .bar-back.stop > span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

.live { --face: clamp(56px, 12dvh, 132px); display: grid; gap: 10px; grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto auto minmax(110px, 1fr) auto; grid-template-areas: "top" "stage" "talk" "controls";
  min-height: calc(100dvh - var(--bar-h) - env(safe-area-inset-top) - 46px); }
.live-top { grid-area: top; display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; min-width: 0; }
/* the page's title as on every other page (its own size, under the bar by the page's own padding) */
.live-top h1 { margin: 0; }
.live-left { font-variant-numeric: tabular-nums; }

.live-stage { grid-area: stage; display: grid; justify-items: center; text-align: center; gap: 4px; min-width: 0; }
.live-face { height: var(--face); aspect-ratio: 120 / 150; transition: transform .08s linear; }
.live-face svg { width: 100%; height: 100%; overflow: visible; filter: drop-shadow(0 6px 10px rgba(40, 28, 16, .18)); }
.live-face svg .bob { animation: bob 3.2s ease-in-out infinite; transform-origin: 50% 90%; }
.live-face.talk svg .beak-low { animation: talk .22s ease-in-out infinite alternate; }
.live-status { margin: 2px 0 0; font-size: 20px; font-weight: 700; letter-spacing: -.01em; min-height: 1.3em; }
.live-line { margin: 0; overflow-wrap: anywhere; }
/* Tall enough to tap (44 px) without making its line taller. During a call it waits: a stray tap would leave the call. */
.live-change { display: inline-block; padding: 12px 4px; margin: -12px 0; font-weight: 600; }
.live[data-call=on] .live-chg { display: none; }
.live-note { width: 100%; max-width: 560px; margin-top: 4px; padding: 10px 14px; border-radius: var(--r-sm); background: var(--warn-soft); color: var(--fg); font-size: 14px; text-align: left; }
.live-note.info { background: var(--accent-2-soft); }
.live-note p { margin: 0; }
.live-note a, .live-note .link { display: inline-flex; align-items: center; min-height: 44px; vertical-align: middle; font-weight: 600; }

/* The words: as tall as the call leaves room for (their own length never sets it: contain), scrolling inside. */
.live-talk { grid-area: talk; contain: size; overflow-y: auto; overscroll-behavior: contain; background: var(--panel); border: 1px solid var(--line); border-radius: var(--r); padding: 14px; }
.live-empty { color: var(--fg); max-width: 520px; margin: 0 auto; padding: 4px 2px; }
.live-empty p { margin: 0 0 8px; }
.live-lines { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.live-lines li { max-width: 88%; padding: 9px 14px 10px; border-radius: 16px; line-height: var(--lh-body); overflow-wrap: anywhere; animation: rise .18s ease-out; }
/* Japanese breaks between phrases, never inside a word (がっこ/うに: talk.js marks them, core.js markPhrases), at the
   body's line height: a call's words carry no readings, so no ruby band (app.css gives li:lang(ja) one). */
.live-lines li:lang(ja) { line-break: strict; word-break: auto-phrase; line-height: var(--lh-body); }
.live-lines .line-text { display: block; }
/* Before anything is said the words' card is only as tall as its one line and the fold: no empty box */
.live-talk:has(> .live-lines:empty) { contain: none; align-self: start; }
.live-lines .line-lola { justify-self: start; background: var(--sunk); border-bottom-left-radius: 4px; }
.live-lines .line-me { justify-self: end; background: var(--accent-soft); border-bottom-right-radius: 4px; }
.live-lines .line-who { display: block; font-size: 14px; font-weight: 650; color: var(--mute); margin-bottom: 1px; }
.live-after { display: flex; justify-content: center; padding-top: 14px; }
/* Saved: said at full contrast, as done, not as a dimmed button. */
#lv-save[data-done], #lv-save[data-done]:hover { opacity: 1; filter: none; background: var(--good-soft); color: var(--good); border-color: transparent; cursor: default; }

/* Pinned to the foot of the screen (above the tab bar on a phone), so a long page never hides Start: Start (End during
   a call) in the middle, as on a phone call. */
.live-controls { grid-area: controls; display: grid; grid-template-columns: minmax(0, 1fr); justify-items: center; align-items: center; gap: 6px; padding: 4px 2px 2px; min-width: 0;
  position: sticky; bottom: env(safe-area-inset-bottom); z-index: 2; background: var(--bg); }
.live-controls .live-levels { width: 100%; max-width: 300px; }
/* Start and End, and Mute beside End: one size (--call), 84 px here, 104 from 900 px, 68 on an upright phone; each
   circle's word under it (.lbl, in the room --lbl-room leaves below the circle; a tap on the word presses its circle). */
.live { --call: 84px; --lbl-room: 28px; }
.live-go { position: relative; width: var(--call); height: var(--call); min-height: 0; padding: 0; border-radius: 50%; border: 0;
  margin-bottom: var(--lbl-room); background: var(--accent-2); color: var(--panel); font-size: 14px; box-shadow: var(--shadow); }
.live-go .lbl, .live-mute .lbl { position: absolute; top: calc(100% + 8px); left: 50%; transform: translateX(-50%); min-width: 100%; text-align: center;
  color: var(--ink); font-size: var(--fs-14); font-weight: 700; line-height: 20px; white-space: nowrap; }
/* Before a call: one quiet line under Start that Mute is there (the M where there is a keyboard) */
.live-mutehint { margin: 0; max-width: 42ch; text-align: center; color: var(--ink-3); font-size: var(--fs-14); line-height: 1.4; }
.live[data-call=on] .live-mutehint { display: none; }
.live-go:hover { border: 0; filter: brightness(1.06); }
/* button:hover (app.css) would paint Start the pale hover grey under its white words (after End, the pointer is still
   over it): each look keeps its own colour on hover. */
@media (hover: hover) {
  .live-go:hover { background: var(--accent-2); }
  .live-go.on:hover { background: var(--bad); }
  .live[data-phase=connecting] .live-go:hover { background: var(--sunk); }
}
.live-go:focus-visible { outline: 3px solid var(--accent-2); outline-offset: 5px; border-radius: 50%; }
.live-go > svg { width: 30px; height: 30px; }
.live-go.on { background: var(--bad); }
.live-go.on:focus-visible { outline-color: var(--bad); }
.live-go .spinner { display: none; position: absolute; inset: -7px; width: auto; height: auto; border-width: 3px; border-color: transparent; border-top-color: var(--accent-2); }
.live[data-phase=connecting] .live-go { background: var(--sunk); color: var(--fg); }
.live[data-phase=connecting] .live-go .spinner { display: block; }
.live-levels { display: grid; gap: 4px; min-width: 0; }
.live-vol { display: grid; grid-template-columns: 4.6em minmax(0, 1fr) 3em; align-items: center; gap: 8px; min-height: 44px; margin: 0; font-weight: 500; }
/* The call's clock and its time bar, once it is connected: the bar fills with the time used (empty at 0:00). */
.live-time { display: grid; gap: 6px; justify-items: stretch; min-width: 0; }
.live-time:has(.live-clock:empty), .live[data-call=off] .live-time { display: none; }
.live-clock { margin: 0; font-weight: 700; color: var(--ink); text-align: center; }
.live-tbar { display: block; height: 4px; border-radius: 999px; background: var(--line); overflow: hidden; }
.live-tbar i { display: block; height: 100%; width: 0; border-radius: inherit; background: var(--ink-3); transition: width .5s linear; }
/* Mute: a phone call's, as big as End. Always the slashed microphone and its word under it; pressed, filled with ink
   and "Muted". Unmuted, a thin ring in the line colour grows out from it with what the microphone hears (--lvl, 0 to
   1) and is gone in a quiet room, so it reads as a level, never as pressed or focused; muted, it is still. */
.live-mute { --lvl: 0; position: relative; width: var(--call); height: var(--call); min-height: 0; padding: 0; border-radius: 50%;
  margin-bottom: var(--lbl-room); font-size: var(--fs-14); font-weight: 700; background: var(--surface-2); color: var(--ink); border: 1.5px solid var(--line-strong); }
.live-mute > svg { width: 26px; height: 26px; }
.live-mute[aria-pressed=true] { background: var(--ink); color: var(--surface); border-color: var(--ink); }
.live-mute[aria-pressed=true] .lbl { color: var(--ink); }
.live-ring { position: absolute; inset: -3px; border-radius: 50%; border: 2px solid var(--line-strong); pointer-events: none;
  opacity: min(1, calc(var(--lvl) * 5)); transform: scale(calc(1 + var(--lvl) * .1)); transition: transform .08s linear, opacity .12s linear; }
.live-mute[aria-pressed=true] .live-ring { opacity: 0; transform: none; }
@media (hover: hover) {
  .live-mute:hover { background: var(--accent-soft); border-color: var(--field); }
  .live-mute[aria-pressed=true]:hover { background: var(--ink); border-color: var(--ink); filter: brightness(1.15); }
}
.live-mute:focus-visible { outline: 3px solid var(--focus); outline-offset: 6px; border-radius: 50%; }
/* During a call: Mute and End a pair centred at the foot, Mute on the left, as on a phone call; the clock and its time
   bar over them (on an upright phone, the bar's), and on a computer the volume under them. */
.live[data-call=on] .live-controls { grid-template-columns: auto auto; grid-template-areas: "time time" "mute go" "vol vol"; justify-content: center; column-gap: var(--s-6); }
.live[data-call=on] .live-levels { display: contents; }
.live[data-call=on] .live-mute { grid-area: mute; }
.live[data-call=on] .live-go { grid-area: go; }
.live[data-call=on] .live-time { grid-area: time; justify-self: center; width: 100%; min-width: 200px; max-width: 240px; }
.live[data-call=on] .live-vol { grid-area: vol; justify-self: center; width: 100%; min-width: 260px; max-width: 340px; }
.live-vol input { width: 100%; min-width: 0; height: 44px; margin: 0; accent-color: var(--accent); background: transparent; }
.live-vol output { text-align: right; }

/* Phones: the page's own padding gives the call the whole height above the tab bar, and the controls stay
   pinned just above the tab bar (and the offline note) however long the page grows. */
@media (max-width: 720px) {
  .page.talk-page { padding: var(--s-4) var(--gut-r, 14px) calc(var(--tab-h) + 10px + var(--below, 0px) + env(safe-area-inset-bottom)) var(--gut-l, 14px); }
  .live { min-height: calc(100dvh - var(--bar-h) - env(safe-area-inset-top) - var(--tab-h) - var(--s-4) - 10px - var(--below, 0px) - env(safe-area-inset-bottom)); gap: 8px; }
  .live-controls { bottom: calc(var(--tab-h) + var(--below, 0px) + env(safe-area-inset-bottom)); padding: 6px 2px; }
  /* Pinned, nothing of the page shows between them and the tab bar. */
  .live-controls::after { content: ""; position: absolute; left: 0; right: 0; top: 100%; height: calc(var(--tab-h) + 8px); background: var(--bg); pointer-events: none; }
  .live-status { font-size: 18px; }
}
/* An upright phone: the call's controls (Start, or Mute, End and the clock) are one bar docked at the foot, the full
   width, on the tab bar before a call and on the home indicator during one, as every session's dock is (study.css);
   the words fill what is between Tomo and the bar, with no box round them (each line is its own bubble). */
@media (max-width: 720px) and (min-height: 501px) {
  .page.talk-page { padding-bottom: calc(var(--dock-at) + var(--below, 0px)); }
  .live { min-height: calc(100dvh - var(--bar-h) - env(safe-area-inset-top) - var(--s-4) - var(--dock-at) - var(--below, 0px)); gap: var(--s-3); }
  .live-talk { padding: 0 0 var(--s-2); border: 0; border-radius: 0; background: none; }
  .live-controls { gap: var(--s-2); bottom: calc(var(--dock-at) + var(--below, 0px));
    margin: 0 calc(-1 * var(--gut-r, 14px)) 0 calc(-1 * var(--gut-l, 14px)); padding: var(--s-2) var(--gut-r, 14px) calc(var(--s-2) + var(--dock-pad)) var(--gut-l, 14px);
    background: var(--surface); border-top: 1px solid var(--line); }
  .live-controls::after { display: none; }
  .live-controls .live-levels { max-width: none; width: 100%; }
  .live { --call: 68px; --lbl-room: 26px; }
  .live-go > svg { width: 26px; height: 26px; }
  /* The call: one row, Mute | End, centred, one size (68 px at every phone width), 32 px apart; the clock and its time
     line are the bar's (the page's own clock shows only until the bar has it). */
  .live[data-call=on] .live-controls { grid-template-areas: "time time" "mute go"; column-gap: var(--s-6); padding-top: var(--s-3); padding-bottom: calc(var(--s-2) + var(--dock-pad)); }
  /* The words get the room: Tomo small beside what she is doing; the title (for screen readers) and the line go. */
  .live[data-call=on] { --face: 44px; grid-template-rows: auto minmax(110px, 1fr) auto; grid-template-areas: "stage" "talk" "controls"; }
  .live[data-call=on] .live-top { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .live[data-call=on] .live-stage { grid-template-columns: auto minmax(0, 1fr); justify-items: start; align-items: center; text-align: left; column-gap: var(--s-3); }
  .live[data-call=on] .live-status { margin: 0; }
  .live[data-call=on] .live-line { display: none; }
  .live[data-call=on] .live-note { grid-column: 1 / -1; }
}
/* Before a call, in one column (a phone upright, a narrow window): Tomo, "Ready when you are" and the line on what to do
   stand in the middle of the room above Start, not at the top of it (the room is shared above and below them). */
@media (max-width: 899px) and (min-height: 501px) {
  .live[data-call=off]:has(.live-lines:empty) { grid-template-rows: auto minmax(0, 1fr) auto auto minmax(0, 1fr) auto; grid-template-areas: "top" "." "stage" "talk" "." "controls"; }
}
/* Above 720 px, with no connection, the room the offline note takes at the top of the page (--above). */
@media (min-width: 721px) {
  .page.talk-page { padding-top: calc(28px + var(--above, 0px)); }
  .live { min-height: calc(100dvh - var(--bar-h) - env(safe-area-inset-top) - 46px - var(--above, 0px)); }
}
/* Wide: the call on the left, the words on the right. */
@media (min-width: 900px) {
  .live { --face: 170px; grid-template-columns: minmax(300px, 380px) minmax(0, 1fr); grid-template-rows: auto 1fr auto;
    grid-template-areas: "top talk" "stage talk" "controls talk"; column-gap: 28px; row-gap: 14px; min-height: max(460px, calc(100dvh - var(--bar-h) - 90px - var(--above, 0px))); }
  .live-stage { align-content: center; }
  .live-talk { padding: 20px; }
  .live { --call: 104px; }
  .live-go { font-size: 15px; }
  .live-mute { font-size: 15px; }
  .live-mute > svg { width: 30px; height: 30px; }
  .live-levels { width: 100%; max-width: 340px; }
}
/* A phone held sideways (short and wide): the call in a narrow column beside the words, Lola smaller, the
   heading for screen readers only (the minutes stay), so Start and End are on the first screen. (560 px wide
   or more: an upright phone with the keyboard up is wider than tall too, and keeps its own layout.) */
@media (orientation: landscape) and (max-height: 500px) and (min-width: 560px) {
  .live { --face: clamp(44px, 15dvh, 72px); grid-template-columns: minmax(0, 300px) minmax(0, 1fr); grid-template-rows: auto 1fr auto;
    grid-template-areas: "top talk" "stage talk" "controls talk"; column-gap: 16px; row-gap: 6px; }
  .live-top { justify-content: center; }
  .live-top h1 { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .live-stage { gap: 2px; align-content: center; }
  .live-status { font-size: 17px; margin: 0; }
  .live-talk { padding: 12px 14px; }
  .live-controls { gap: 4px 12px; padding: 4px 2px; }
  .live { --call: 64px; --lbl-room: 26px; }
  .live-go { font-size: 14px; }
  .live-go > svg, .live-mute > svg { width: 24px; height: 24px; }
  .live-levels { max-width: none; gap: 0; }
  /* short as it is, the call keeps one row: Mute | End | the clock over its time bar */
  .live[data-call=on] .live-controls { grid-template-columns: auto auto minmax(0, 1fr); grid-template-areas: "mute go time"; justify-content: stretch; column-gap: var(--s-4); }
  .live[data-call=on] .live-time { justify-self: stretch; min-width: 0; max-width: none; margin-bottom: var(--lbl-room); }
}
@media (orientation: landscape) and (max-height: 500px) and (min-width: 721px) {
  .page.talk-page { padding-top: calc(8px + var(--above, 0px)); }
  .live { min-height: calc(100dvh - var(--bar-h) - env(safe-area-inset-top) - 24px - var(--above, 0px)); }
}
/* How a call works: a fold under the one line that says what to do */
.live-how { margin-top: var(--s-2); }
.live-how p { margin: 0 0 var(--s-2); }
/* A phone (720 px wide or less, or a touch screen): the phone's own volume buttons do it, so there is no slider, the
   same at every phone width and in either theme. */
@media (max-width: 720px), (hover: none) and (pointer: coarse) {
  .live-vol { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .live-face, .live-tbar i, .live-mute, .live-ring { transition: none; }
  .live-face svg .bob, .live-face.talk svg .beak-low, .live-lines li { animation: none; }
}

/* The Talk live card on the Speak page (js/screens/speak.js). */
.live-card { display: flex; align-items: center; gap: 14px; min-height: 68px; margin: -4px 0 18px; padding: 12px 16px; border-radius: var(--r); background: var(--accent-2-soft);
  color: var(--fg); text-decoration: none; border: 1.5px solid transparent; }
.live-card:hover { border-color: var(--accent-2); }
.live-card b { display: block; font-size: 16px; }
.live-card small { display: block; color: var(--mute); font-size: 14px; line-height: 1.35; }
.live-card-ic { display: grid; place-items: center; width: 44px; height: 44px; border-radius: 50%; background: var(--accent-2); color: var(--panel); flex: none; }
.live-card-ic svg { width: 22px; height: 22px; }
.live-card-go { flex: none; display: inline-flex; align-items: center; min-height: 44px; padding: 0 18px; border-radius: 999px; background: var(--accent-2); color: var(--panel); font-weight: 650; }
@media (max-width: 420px) { .live-card-go { display: none; } }

/* The Admin page's Talk live panel (js/screens/owner-live.js): its switch is a full-size target. */
.own-live .switch { min-height: 44px; }
