/* Native Chat uses the house surfaces and the shared feel kit. No page palette. */
.cq-room .composer-shell { min-width:0; }
.cq-room .composer {
  display:grid; grid-template-columns:44px minmax(0,1fr) 56px 44px;
  gap:8px; align-items:end; padding:14px; border-color:var(--line-strong);
}
.cq-room .composer:focus-within { border-color:var(--eon-accent,var(--lime)); }
.cq-room .composer #composer-input {
  grid-column:1 / -1; grid-row:1; width:100%; min-width:0;
  min-height:70px; font-size:16px; line-height:1.6; padding:4px 2px 12px;
}
.cq-room #composer-attach { grid-column:1; grid-row:2; }
.cq-room .cq-live { grid-column:2; grid-row:2; justify-self:start; }
.cq-room #composer-mic { grid-column:3; grid-row:2; }
/* Dictate is its icon: an 11 px caption stacked inside the 44 px ring crossed
   it (21 Oct live assessment F7). Its name is the button's aria-label. */
.cq-room #composer-mic span { display:none; }
.cq-room #composer-send { grid-column:4; grid-row:2; }
/* Symbols only (operator, 21 Oct): Live voice is its three bars and Dictate its
   icon. Each button's own aria-label and title carry the words, which
   chat_conversation.js keeps in step with the call's state. */
.cq-room .cq-live-label { display:none; }
/* A narrow composer (the Ask launcher's reserved room on a phone, or 200%
   text) gave Live conversation a ~30 px column and wrapped it into a tall
   stack beside Dictate. Narrower than about 320 px, Live voice takes its own
   row under the others, label intact. Four fixed tracks (44 + 56 + 44 and
   three gaps) were also wider than the box itself at 380 px with 200% text:
   the textbox and Send ran 15 px past the composer's edge. So there the grid
   keeps three tracks, Attach and Send on the second row, Live voice and
   Dictate share the third; every control is still 44 px and inside the box.
   The size container is the row around the composer (the composer cannot
   restyle its own grid from its own query); at these widths the composer
   fills it, and its width never depends on its content. */
.cq-room .composer-shell { container:cq-composer / inline-size; }
@container cq-composer (max-width:322px) {
  .cq-room .composer { grid-template-columns:44px minmax(0,1fr) 44px; }
  .cq-room #composer-send { grid-column:3; grid-row:2; }
  .cq-room .cq-live { grid-column:1 / 3; grid-row:3; }
  .cq-room #composer-mic { grid-column:3; grid-row:3; }
}
.cq-room .composer button { min-height:44px; min-width:44px; height:auto; margin:0; }
.cq-room .cq-live,.cq-room .cq-task,.cq-room .cq-actions button {
  font:inherit; font-size:13px; font-weight:600; color:var(--ink);
  background:var(--surface); border:1px solid var(--line-strong);
  border-radius:0; padding:10px 12px; cursor:pointer;
  min-height:44px; overflow-wrap:anywhere;
}
.cq-room .cq-live { display:inline-flex; align-items:center; justify-content:center; background:transparent; border-color:transparent; padding:0; }
.cq-room .cq-live::before { content:''; width:10px; height:12px; flex:none; border-inline:2px solid currentColor; background:linear-gradient(currentColor,currentColor) center/2px 100% no-repeat; color:var(--ink-dim); }
.cq-room .cq-status,.cq-room .composer-hint,.cq-room .cq-live-boundary {
  font-size:12px; line-height:1.5; color:var(--ink-dim); opacity:1;
}
.cq-room .cq-status { min-height:18px; margin:7px 3px 0; }
/* The line under the composer about where live voice goes is read out only
   (operator, 23 Oct: icons only, no sentence beneath). It takes no room on
   the screen and stays Live voice's description (aria-describedby). */
.cq-room .cq-live-boundary {
  position:absolute; width:1px; height:1px; margin:0; overflow:hidden; clip-path:inset(50%); white-space:nowrap;
}
.cq-room .composer-hint { margin-top:4px; }
.cq-room .cq-handoff {
  margin:0 0 10px; padding:12px; border:1px solid var(--line-strong);
  border-radius:0; background:var(--surface); color:var(--ink);
}
.cq-room .cq-handoff[hidden] { display:none; }
.cq-room .cq-handoff summary,.cq-room .cq-sources summary { cursor:pointer; min-height:44px; padding:10px 0; font-size:13px; font-weight:600; }
.cq-room .cq-handoff pre { white-space:pre-wrap; overflow-wrap:anywhere; font:inherit; font-size:13px; max-height:160px; overflow:auto; }
.cq-room .cq-actions { display:flex; flex-wrap:wrap; gap:8px; }
.cq-room .cq-task { font-size:12px; padding:8px 12px; border-color:var(--eon-accent,var(--lime)); }
.cq-room .msg-actions { flex-wrap:wrap; }
.cq-room .chat-toolbar .icon-btn-sm { width:44px; height:44px; min-width:44px; min-height:44px; }
.cq-room .msg-actions button { min-width:44px; min-height:44px; }

.cq-room .cq-sources { margin:12px 0 4px; color:var(--ink); border-top:1px solid var(--line); text-align:left; }
.cq-room .cq-sources p,.cq-room .cq-sources li > span { color:var(--ink-dim); font-size:12px; line-height:1.5; }
.cq-room .cq-sources summary span { margin-left:6px; color:var(--ink-dim); font-family:var(--mono); font-variant-numeric:tabular-nums; }
.cq-room .cq-sources ul { list-style:none; padding:0; margin:0; }
.cq-room .cq-sources li { display:flex; flex-wrap:wrap; align-items:center; gap:4px 16px; border-top:1px solid var(--line-soft); }
.cq-room .cq-sources a { display:inline-flex; align-items:center; gap:8px; min-height:44px; font-size:13px; color:var(--ink); text-decoration:underline; text-underline-offset:3px; }
.cq-room .cq-sources li > span { padding-bottom:6px; }
.cq-start { position:relative; isolation:isolate; width:min(100%,700px); margin:auto; padding:30px 12px 24px; color:var(--ink); text-align:left; }
.cq-start .cq-kicker { display:flex; justify-content:space-between; flex-wrap:wrap; gap:8px 20px; font-size:9px; font-weight:600; letter-spacing:.1em; color:var(--ink-dim); }
.cq-start .cq-kicker > :last-child { color:var(--ink-dim); }
.cq-start h2 { font-family:var(--display); font-size:clamp(42px,4.6vw,62px); font-weight:700; line-height:.98; letter-spacing:-.06em; margin:24px 0 17px; }
.cq-start h2 em { color:inherit; font-style:normal; }
.cq-start > p:not(.cq-kicker) { max-width:52ch; font-size:14px; line-height:1.55; color:var(--ink-dim); }
.cq-starters { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); column-gap:24px; margin-top:24px; border-top:1px solid var(--line-strong); }
.cq-starters button { display:grid; grid-template-columns:22px minmax(0,1fr) 22px; align-items:center; gap:14px; text-align:left; padding:15px 2px; border:0; border-bottom:1px solid var(--line-strong); border-radius:0; color:var(--ink); background:transparent; cursor:pointer; font:inherit; min-height:72px; }
.cq-starters button:hover,.cq-starters button:focus-visible { background:var(--surface); }
.cq-starters button:active { color:var(--eon-accent,var(--lime)); }
.cq-starters strong,.cq-starter-words > span { display:block; }
.cq-starters strong { font-size:15px; line-height:1.4; font-weight:600; }
.cq-starter-words > span { font-size:12px; color:var(--ink-dim); line-height:1.5; margin-top:4px; }
.cq-starters .cq-starter-number { font-size:10px; color:var(--ink-dim); font-family:var(--mono); font-variant-numeric:tabular-nums; }
.cq-starters .cq-starter-arrow { font-size:20px; color:var(--ink-dim); text-align:right; }
.cq-start > .cq-start-note { font-size:11px !important; margin-top:15px; }
@media(max-width:650px) {
  .cq-start { padding:18px 2px; }
  .cq-starters { margin-top:20px; }
  .cq-starters { column-gap:14px; }
  .cq-starters button { grid-template-columns:minmax(0,1fr) 16px; padding:11px 1px; gap:4px 6px; align-items:start; }
  .cq-starter-number { grid-column:1; }
  .cq-starter-words { grid-column:1 / -1; grid-row:2; }
  .cq-starter-arrow { grid-column:2; grid-row:1; width:16px; height:16px; }
  .cq-starters strong { font-size:13px; }
  .cq-starter-words > span { font-size:11px; }
  .cq-start h2 { font-size:36px; margin:18px 0 14px; }
  .cq-room .composer { padding:10px; gap:6px; }
  .cq-room .cq-live { font-size:12px; padding-right:0; }
  .cq-room .cq-live-boundary { font-size:11px; }
}
@media(max-width:350px) { .cq-starters { grid-template-columns:1fr; } }

/* Keep controls and the starter heading within short or keyboard viewports.
 * Fold only repeated introductory/helper copy; real context, errors and approvals remain. */
@media(max-height:500px) {
  html[data-living] main.cq-room.chat-wrap.lw-content { padding-top:4px !important; }
  .cq-room .lw-chat-intro, .cq-room .cq-kicker { display:none; }
  [data-living] .cq-room .chat-toolbar { padding-block:0; }
  [data-living] .cq-room .composer-shell { padding-top:4px; padding-bottom:max(4px,env(safe-area-inset-bottom)); }
  .cq-room .composer { padding:8px; gap:4px; }
  .cq-room .composer #composer-input { min-height:32px; max-height:32px; padding:2px; line-height:1.5; overflow-y:auto !important; }
  .cq-room .cq-status { min-height:0; margin-top:2px; }
  .cq-room .cq-status:empty, .cq-room .composer-hint, .cq-room .cq-live-boundary { display:none !important; }
  [data-living] .cq-room .chat-body { padding-block:8px; }
  .cq-room .cq-start { padding:4px 2px; }
  .cq-room .cq-start h2 { font-size:32px; margin:4px 0 12px; }
}
html:is(.csw-kb-open, .cq-short, .cq-tight)[data-living] main.cq-room.chat-wrap.lw-content { padding-top:4px !important; }
html:is(.csw-kb-open, .cq-short) .cq-room .lw-chat-intro, html:is(.csw-kb-open, .cq-short) .cq-room .cq-kicker { display:none; }
html:is(.csw-kb-open, .cq-short, .cq-tight)[data-living] .cq-room .chat-toolbar { padding-block:0; }
html:is(.csw-kb-open, .cq-short, .cq-tight)[data-living] .cq-room .composer-shell { padding-top:4px; padding-bottom:4px; }
html:is(.csw-kb-open, .cq-short, .cq-tight) .cq-room .composer { padding:8px; gap:4px; }
html.csw-kb-open .cq-room .composer #composer-input { min-height:32px; max-height:32px; padding:2px; line-height:1.5; overflow-y:auto !important; }
/* html.cq-short (chat_conversation.js markShortRoom): fewer than 500 px of
   the page's own height, which a media query cannot see once the page itself
   is zoomed (200% text as page zoom: a 820 px phone lays out in 410 px). The
   same folds apply, but the textbox only starts at one line: the keyboard is
   not up, so it still grows with a draft (app.js autosize) and every typed
   line can be read. Its rows="2" floored the empty box at two lines (autosize
   measures height:auto, which is the rows height), so the box sizes from its
   content here: one line empty, every typed line as it comes, until the
   thread's own room runs out (cq-draft-fit, below). Where field-sizing is
   not supported it keeps the two rows it had. */
html.cq-short .cq-room .composer #composer-input { min-height:32px; padding:2px; line-height:1.5; field-sizing:content; }
/* A real short screen (200% text or a landscape phone: under 500 px of
   window) also matches the media query above, whose 32 px cap is the
   keyboard's: a typed three-line draft showed one line at a time. Without
   the keyboard (app.js csw-kb-open) the box grows as it does when zoomed;
   with it, the cap stays. */
html.cq-short:not(.csw-kb-open) .cq-room .composer #composer-input { max-height:none; }
/* html.cq-tight (chat_conversation.js placeDock): during a call the thread
   fell under the room it keeps (about three lines of the answer and its task
   or source control), most often because a draft grew, in a window tall
   enough that the short room's layout never came. Until the card goes, the
   call takes the short room's compact layout: these folds of helper copy and
   spare padding, the one-row card and the dock (below). Real context, errors
   and approvals stay; the textbox keeps its own empty height.
   html.cq-draft-capped (capDraft): while that compact layout holds the card,
   in either room, a draft grows only into the room the thread can spare
   (--cq-draft-max, never under the box's empty height) and then scrolls, so
   it can no longer push the thread, the answer's words and the call's own
   controls off the screen. Every line is still reached by scrolling or by
   the caret. With the keyboard up its one-line cap stays. */
html.cq-draft-capped:not(.csw-kb-open) .cq-room .composer #composer-input { max-height:var(--cq-draft-max); overflow-y:auto !important; }
html:is(.csw-kb-open, .cq-short, .cq-tight) .cq-room .cq-status { min-height:0; margin-top:2px; }
/* During a compact call the composer's routine "Draft ready" line (one row,
   two at 200% text on a phone) took 20-38 px from the thread the moment a
   draft was typed, and with it the answer's last readable line (render proof
   cf1, callDraft). It is helper copy: Send's own state says the same. It is
   still read out (role=status, and the textbox's description); every other
   line (an upload, a refusal, a handoff) stays on screen. */
html:is(.cq-short, .cq-tight) .cq-room:has(.cq-voice-slot) .cq-status[data-cq-routine] {
  position:absolute; width:1px; height:1px; margin:0; overflow:hidden; clip-path:inset(50%); white-space:nowrap;
}
/* The answer's own row of actions in a compact layout (a short room, or a
   call's cq-tight). With no voice to play, app.js still draws each reply's
   play button, unseen and untappable (_voiceTtsAttributes: disabled,
   aria-hidden, visibility:hidden), and this room's 44 px floor for those
   buttons made it hold a 44 px cell and its gap. At 215 CSS px of width (430
   with 200% text) that put Prepare task on a second row, and copy over
   Prepare task (102 px with the row's margin) filled all but 4 px of the
   call's 121 px thread: the latest answer's words were above it (render cf3,
   c73ddb00, turnsCall). Here that unseen button takes no room, so copy and
   Prepare task (44 + 6 + 106 px of the 159 px inside the reply) share one row,
   and the row's head margin is the short room's 4 px. Once voice can play,
   app.js lifts aria-hidden and the button is back in the row. */
html:is(.cq-short, .cq-tight) .cq-room .msg-actions { margin-top:4px; }
html:is(.cq-short, .cq-tight) .cq-room .msg-actions [data-voice-tts][aria-hidden="true"] { display:none; }
/* Still in a compact layout, the reply's actions keep ONE row of 44 px
   targets at 190 CSS px (380 with 200% text). There the reply's 9/11 px
   padding (app.css, phone) left 134 px inside it, copy and Prepare task
   (44 + 6 + 106) took two rows, and with the call's 65 px thread the end of
   the reply was those two rows and no word of the answer (render cf5,
   turnsCall and callDraft; at 215 CSS px with voice to play the play button
   wrapped them the same way). The reply's padding gives 6 px back on each
   side (144 px inside), the row's gap is 4 px, and Prepare task shows its
   last word, "Task", with a 6 px side padding (44 px wide): copy, play and
   Task are 140 px, one row. Its name is still "Prepare task" (aria-label;
   the visible word is part of it), the same button, listener and index;
   only the word "Prepare " is folded, nothing tappable is. The answer's
   lines are a little tighter (1.45), so the thread's band holds a whole
   line above that row. Outside a compact layout nothing here applies.
   The word folds only in a room 200 CSS px wide or less (html.cq-narrow,
   chat_conversation.js markShortRoom: 190 is a 380 px phone at 200%). R2
   read 2 found "Task" alone wherever the room was short, at 215 CSS px and
   on a landscape phone too, where copy and Prepare task (44 + 4 + 94 of
   the 159 px inside the reply) already share one row: there it reads
   "Prepare task" again. */
html:is(.cq-short, .cq-tight) .cq-room .msg.eon { padding:6px !important; }
html:is(.cq-short, .cq-tight) .cq-room .msg.eon .text { line-height:1.45; }
html:is(.cq-short, .cq-tight) .cq-room .msg-actions { gap:4px; }
html:is(.cq-short, .cq-tight) .cq-room .cq-task { padding:8px 6px; }
html.cq-narrow:is(.cq-short, .cq-tight) .cq-room .cq-task { text-transform:capitalize; }
html.cq-narrow:is(.cq-short, .cq-tight) .cq-room .cq-task-lead { display:none; }
html:is(.csw-kb-open, .cq-short, .cq-tight) .cq-room .cq-status:empty, html:is(.csw-kb-open, .cq-short, .cq-tight) .cq-room .composer-hint, html:is(.csw-kb-open, .cq-short, .cq-tight) .cq-room .cq-live-boundary { display:none !important; }
html:is(.csw-kb-open, .cq-short, .cq-tight)[data-living] .cq-room .chat-body { padding-block:8px; }
html:is(.csw-kb-open, .cq-short) .cq-room .cq-start { padding:4px 2px; }
html:is(.csw-kb-open, .cq-short) .cq-room .cq-start h2 { font-size:32px; margin:4px 0 12px; }
/* A short room's welcome. At 190 x 410 (380 px with 200% text) the greeting
   was set at 27 px and broke into five lines, 146 px in a 139 px thread, so
   even at its top its last line was cut (render cf5, fresh). Here it is set
   at 22 px (about four lines, under 100 px) and the hero's 11vh foot gives
   way to 8 px; its words and every quick question stay, a scroll down. */
html.cq-short .cq-room .eon-hero-greet { font-size:22px; line-height:1.1; }
html.cq-short .cq-room .eon-hero { padding-bottom:8px; }
/* During a compact call the quick questions stand on the card, and the
   thread's band (65 px at 190 x 410) could not hold one whole: each was
   57 px (two lines of 13 px with 8/14 px padding). Here a question is two
   lines of 12 px in a 44 px target, so the last one is whole and tappable
   above the card; the others and the plain line are a scroll up. */
html:is(.cq-short, .cq-tight) .cq-room:has(.cq-voice-slot) .eon-hero-chip { padding:4px 10px; font-size:12px; line-height:1.35; }
/* A short room's typed draft with no call. app.js autosize caps the box's
   inline height at 40% of the window (164 px at 410), under the content
   height this room grows the box to above, so a three-line draft that wraps
   to seven lines at 190 CSS px kept 8 px of itself out of view (render cf5,
   draft: scrollHeight 172, clientHeight 164). Where field-sizing works the
   box takes its content's height here, up to nine lines or the thread's
   own room (cq-draft-fit, below), and a longer draft scrolls; the inline
   height stays app.js's everywhere else. A call's
   cap (cq-draft-capped) and the keyboard's one line are unchanged. The
   routine "Draft ready" line below it (one row, two at 200% text) is helper
   copy whose words Send's own state carries: in a short room it is read out
   only (role=status), as during a call, so the composer keeps its place on
   the screen; every other line (an upload, a refusal, a handoff) shows. */
@supports (field-sizing: content) {
  html.cq-short:not(.csw-kb-open):not(.cq-draft-capped) .cq-room .composer #composer-input { height:auto !important; max-height:calc(9lh + 4px); }
}
html.cq-short .cq-room .cq-status[data-cq-routine] {
  position:absolute; width:1px; height:1px; margin:0; overflow:hidden; clip-path:inset(50%); white-space:nowrap;
}
/* A short room scrolls rather than clipping (R2 read 2, finding 2). The
   living shell holds Chat's room with overflow:hidden, so whatever a short
   window could not fit was cut off with no way to reach it. With no call, a
   typed draft the box shows whole (above) can need more than the screen:
   at 190 x 410 a three-line draft wraps to seven lines (172 px), and the
   room's 342 px under the header then needs 92 (the bar, wrapped) + 16 (the
   thread's own padding) + 282 (the composer row, narrow trims below) = 390:
   Live voice and Dictate stood 48 px under the screen, out of reach (the
   wrapped bar's 48 px made it so; before it the same row was already cut by
   about 16 px). On a landscape phone (844 x 390) a
   long draft does the same. Here the room scrolls by exactly that much and
   nothing is cut; a room that fits never scrolls, and nothing moves
   sideways (overflow-x stays the shell's hidden). The thread keeps its own
   scroll and its overscroll stays its own (app.css). A typed draft under an
   answer no longer needs it (cq-draft-fit, below); it stays for what no
   fold can make fit. */
html.cq-short[data-living] main.cq-room.chat-wrap.lw-content { overflow-y:auto; }
/* What a short room's draft may take with no call (chat_conversation.js
   fitShortDraft, CF10 risk render on 22653053). Grown to its content, a
   three-line draft took the thread from the answer: at 215 CSS px the thread
   kept 31 px and the answer and Prepare task were cut above the box; at
   190 x 410 the composer ran 21 px under the screen; a classic Chat on a
   landscape phone showed no word of the answer. Here the box grows only
   while the thread still shows the latest turn's last line and all under it
   (--cq-short-draft-max, measured on Chat's own room), never under its own
   empty height, and past that it scrolls: every line is reached by
   scrolling or by the caret. The keyboard's one line and a call's cap
   (cq-draft-capped) are unchanged. */
html.cq-short:not(.csw-kb-open):not(.cq-draft-capped) main.cq-room.cq-draft-fit .composer #composer-input { max-height:var(--cq-short-draft-max); overflow-y:auto !important; }

/* Chat's live voice stage (chat_voice_view.js), in the slot Chat places
   directly above the composer, in the composer's own centred column
   (.eon-chat .composer: max-width 760px, margin auto). House tokens only.
   The engine's stage draws the call; the card itself only arrives and
   leaves: it rises into place in 280 ms on the house panel easing (Ask's
   --ask-t-panel / --ask-ease-out values), and with Reduce Motion it only
   fades. Transform and opacity only, never layout. */
.cq-room .cq-voice-slot { max-width:760px; margin:0 auto; }
@keyframes cvv-arrive { from { opacity:0; transform:translateY(10px); } to { opacity:1; transform:none; } }
@keyframes cvv-arrive-still { from { opacity:0; } to { opacity:1; } }
.cq-voice-slot .cvv { animation: cvv-arrive 280ms cubic-bezier(.2,.8,.2,1) both; }
.cq-voice-slot .cvv[data-motion="still"] { animation-name: cvv-arrive-still; animation-duration: 180ms; }
@media (prefers-reduced-motion: reduce) { .cq-voice-slot .cvv { animation-name: cvv-arrive-still; animation-duration: 180ms; } }
/* While the call card is open in a conversation with no turns yet, the big
   greeting, the wash behind it and the classic gallery step aside instead of
   being cut off above the card. What helps stays, just above the card: one
   plain line from Chat (cq-call-intro: what to do, where the words will
   appear) and the quick questions, at full 44 px height. A quick question
   tapped during the call is asked over the call (sendChat's call route).
   Every turn the call adds ends the empty state as usual; closing the card
   brings the whole welcome back. Taller than its room, it scrolls from the
   top (safe alignment), never cut off above. */
.cq-room:has(.cq-voice-slot) .chat-empty-state { justify-content: safe flex-end; padding-bottom: 8px; }
/* While the card is open the turns stand on it: a thread shorter than its
   box sits at the box's foot, next to the call, not at its head with an
   empty band between (at 1280 px with 200% text the latest turn was above
   the screen and the band was all that showed). Safe alignment: a longer
   thread still starts at its top and scrolls, and followThreadEnd keeps its
   end in view. The card brings its own margin, so the thread's own 20 px
   foot is not kept under the questions or the latest turn as well. */
.cq-room:has(.cq-voice-slot) .chat-body { padding-bottom: 8px; justify-content: safe flex-end; }
.cq-room:has(.cq-voice-slot) .chat-empty-state > :not(.eon-hero-chips, .cq-call-intro) { display:none; }
.cq-room:has(.cq-voice-slot) .eon-hero-chips { margin-top: 10px; }
.cq-room:has(.cq-voice-slot) .eon-hero-chip { min-height: 44px; }
.cq-room .cq-call-intro { display:none; }
.cq-room:has(.cq-voice-slot) .cq-call-intro { display:block; margin: 0; max-width: 52ch; font-size: 13px; line-height: 1.5; color: var(--ink-dim); }
.cq-room:has(.cvv:is([data-state="ended"], [data-state="ended-unconfirmed"], [data-state="error"])) .cq-call-intro { display:none; }
/* Once the conversation has turns, they need the room more than the drawing
   does. On a phone or a laptop-height screen the lent stage keeps 88 px (it
   still draws in full above 72 px; the engine sizes itself from its own box)
   and the thread gains 56 px. Chat sizes only the box it holds; the stage's
   own styles stay the engine's. The Living intro line above the thread
   ("Your thinking partner / Context travels with the conversation", words
   only, no action) also steps aside while the card is open; an attached
   context strip, which has actions, stays. */
@media (max-width: 560px), (max-height: 900px) {
  .cq-room:not(:has(.chat-empty-state)) .cq-voice-slot [data-eon-voice-stage] { height: 88px; }
}
:root:has(.cq-room .cq-voice-slot) .lw-chat-intro { display:none; }
/* Chat has its own conversation and its own live voice, so on Chat Ask's
   launcher and the pet's controls rest (the desk's own shadow-part rule,
   cs.css): before, during and after a call, on every thread. No box, not
   just unseen, so nothing invisible can be tapped. Ask stays mounted: its
   sheet, task drafts, decisions, sound check and the call engine keep
   working through their own actions, and every other page keeps the
   launcher. The message row's room for the launcher (app.js askEonRowRoom,
   read only by app.css's Chat row border) is therefore never needed here:
   it stays 0 even while Ask's panel holds the pet's controls in place. */
:root:has(.cq-room) #eon-ask-root::part(pill) { display:none; }
:root:has(.cq-room) #eon-ask-root::part(companion-controls) { display:none; visibility:hidden; pointer-events:none; }
.cq-room .composer-shell { --eon-ask-row-room: 0px !important; }
/* The empty-state greeting is set big; on a phone it wraps to three lines and
   the centred column overflowed upward, out of reach of the scroll, so only
   its last line showed. Safe centring keeps it centred when it fits and lets
   it start at the top when it does not. */
.cq-room .eon-hero { justify-content: safe center; }
.cvv {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0 0 8px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--bg-card);
  color: var(--ink);
}
.cvv[data-live="true"] { border-color: var(--accent); }
.cvv[data-state="muted"], .cvv[data-state="device-quiet"] { border-color: var(--warn); }
.cvv[data-state="error"] { border-color: var(--danger); }
.cvv-stage:empty { display: none; }
.cvv-simulated { margin: 0; color: var(--warn); font-size: 12px; }
.cvv-row { display: flex; align-items: center; gap: 12px; }
.cvv-status {
  flex: 1 1 auto;
  margin: 0;
  min-width: 0;
  color: var(--ink-dim);
  font-size: 14px;
  line-height: 1.35;
  overflow-wrap: anywhere;
}
.cvv[data-live="true"] .cvv-status { color: var(--ink); }
.cvv[data-state="device-quiet"] .cvv-status, .cvv[data-state="muted"] .cvv-status { color: var(--warn); }
.cvv-controls { display: flex; flex: none; gap: 8px; }
.cvv-controls button {
  min-width: 44px;
  min-height: 44px;
  padding: 0 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
  touch-action: manipulation;
  transition: background-color var(--transition-fast), border-color var(--transition-fast), opacity var(--transition-fast);
}
.cvv-controls button[hidden] { display: none; }
.cvv-controls button:active:not(:disabled) { background: var(--accent-soft); }
.cvv-controls button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.cvv-controls button:disabled { opacity: 0.5; cursor: default; }
/* Scoped like the base button rule (0,1,1) so these win without !important. */
.cvv-controls .cvv-mute[aria-pressed="true"] { border-color: var(--warn); color: var(--warn); }
.cvv-controls .cvv-end { border-color: var(--accent); color: var(--accent); }
.cvv[data-motion="still"] .cvv-controls button { transition: none; }
@media (prefers-reduced-motion: reduce) { .cvv-controls button { transition: none; } }
/* One-handed at 380 px and text at 200%: the controls take their own row.
   Measured on the card itself, not the window: at 200% text a 430 px phone
   leaves the card under 200 px, and the status line was squeezed to one
   letter per line beside the buttons. */
.cvv { container: cvv / inline-size; }
@container cvv (max-width: 420px) {
  .cvv-row { flex-wrap: wrap; }
  .cvv-controls { flex: 1 1 100%; }
  .cvv-controls button { flex: 1 1 auto; }
}
/* Genuinely narrow (a card under about 300 CSS px: 430 px with 200% text,
   or narrower): the stage stands beside the status words instead of above
   them and keeps 56 px, so a whole recent turn and the composer still share
   the screen with the call. Measured on the slot, the card's own width, so a
   real browser text size narrows it the same way. The engine still draws
   its own stage from its own box (small under 72 px); Mute and End keep
   their own 44 px row. The status column is never narrower than its longest
   word: at 380 px with 200% text the card is 158 px and a 64 px stage left
   "Connecting" 64 px, so it broke as "Connectin / g". The stage gives up to
   12 px first (56 down to 44 wide; it keeps 56 px of height), and words break
   only between words. */
.cq-room .cq-voice-slot { container: cq-voice / inline-size; }
@container cq-voice (max-width: 300px) {
  .cvv { display: grid; grid-template-columns: minmax(44px, 56px) minmax(min-content, 1fr); align-items: center; gap: 8px 10px; padding: 8px 10px; }
  .cvv-row { display: contents; }
  .cvv-stage { grid-column: 1; grid-row: 1; }
  .cvv-simulated { grid-column: 1 / -1; }
  .cvv-status { grid-column: 2; grid-row: 1; font-size: 13px; overflow-wrap: break-word; }
  .cvv:has(.cvv-stage:empty) .cvv-status { grid-column: 1 / -1; }
  .cvv-controls { grid-column: 1 / -1; }
  .cq-room .cq-voice-slot .cvv-stage [data-eon-voice-stage] { height: 56px; }
}
/* A short room (html.cq-short, chat_conversation.js: fewer than 500 px of
   height, zoomed or not) with a card wider than that: the stage, the status
   words and Mute / End share one row, so the card is the 56 px stage and its
   padding instead of a 144 px stage over a row of words and buttons. At
   1280 px with 200% text it was 257 px of a 400 px screen and the quick
   questions went above it. Narrower cards keep the two rows above. A call
   whose thread ran out of room in a tall window (html.cq-tight, below) gets
   the same one-row card. */
@container cq-voice (min-width: 301px) {
  html:is(.cq-short, .cq-tight) .cvv { display: grid; grid-template-columns: 56px minmax(min-content, 1fr) auto; align-items: center; gap: 8px 12px; padding: 8px 12px; }
  html:is(.cq-short, .cq-tight) .cvv-row { display: contents; }
  html:is(.cq-short, .cq-tight) .cvv-stage { grid-column: 1; grid-row: 1; }
  html:is(.cq-short, .cq-tight) .cvv-simulated { grid-column: 1 / -1; }
  html:is(.cq-short, .cq-tight) .cvv-status { grid-column: 2; grid-row: 1; }
  html:is(.cq-short, .cq-tight) .cvv:has(.cvv-stage:empty) .cvv-status { grid-column: 1 / 3; }
  html:is(.cq-short, .cq-tight) .cvv-controls { grid-column: 3; grid-row: 1; }
  html:is(.cq-short, .cq-tight) .cq-room .cq-voice-slot .cvv-stage [data-eon-voice-stage] { height: 56px; }
}
/* The call dock: one row of call controls in a short room (html.cq-short,
   or html.cq-tight: chat_conversation.js placeDock). While a call runs, the card's own Mute
   and End buttons are moved into the composer's row, into the cell Live
   voice holds; Live voice is the only control that steps aside, because
   during a call it only brings focus to End. Attach, the textbox, files,
   Dictate and Send stay where they are; the card keeps the stage and the
   status words in one row. When the call is over (or the room is tall
   again) Mute and End go back to the card and Live voice returns. A
   composer under about 322 px gives the dock its own full row (where Live
   voice and Dictate were) and Dictate moves up beside Send, into the
   second row's free middle cell, so the composer keeps its height. */
.cq-room .composer > .cvv-controls { grid-column:2; grid-row:2; justify-self:start; min-width:0; }
.cq-room .composer > .cvv-controls button { padding:0 10px; }
.cq-room .composer:has(> .cvv-controls) .cq-live { display:none; }
.cq-room .composer > .cvv-controls[data-motion="still"] button { transition:none; }
@container cq-composer (max-width:322px) {
  .cq-room .composer > .cvv-controls { grid-column:1 / -1; grid-row:3; justify-self:stretch; }
  .cq-room .composer > .cvv-controls button { flex:1 1 0; }
  .cq-room .composer:has(> .cvv-controls) #composer-mic { grid-column:2; grid-row:2; justify-self:end; }
}
/* With its controls docked the card is the stage and its words: a 1 px
   frame (3 px until render cf8; the narrow card's too, below), so the
   thread keeps its band. The docked composer's own head and
   foot are 4 px. At 1280 px with 200% text (640 x 400) the card was 70 px and
   the composer 98 px, and the thread's 96 px band showed one word of the
   answer, "before.", over its row of actions: the line above it started 6 px
   above the band (render cf6, turnsCall and callDraft). These give the band
   14 px, the whole line above and 8 px to spare (the 1 px frame adds 4).
   The stage keeps its 56 px. */
html:is(.cq-short, .cq-tight) .cvv[data-docked="true"] { padding:1px 10px; margin-bottom:4px; }
html:is(.cq-short, .cq-tight) .cq-room .composer:has(> .cvv-controls) { padding-block:4px; }
/* More: a narrow composer during a compact call (chat_conversation.js
   placeDock). At 190 x 410 (380 px with 200% text) the composer was three
   44 px rows, the textbox, Attach / Dictate / Send, and Mute / End, 146 px;
   the thread's 83 px band showed one word of the answer and the stage had
   given up 12 px to 44 (render cf6). Here the composer is two rows: the
   textbox beside Send, then Mute, End and More (4 px frame: 102 px). Attach
   and Dictate are the same buttons with their own listeners, behind More
   (aria-expanded); opened, they take a third row, and closing gives the room
   back. Dictate stays on screen while it records (app.js shows #rec-overlay),
   so a tap-mode recording can always be stopped where it was started. Every
   control is 44 px or more. Wider composers, rooms that are not compact and
   Chat with no call never show More. */
.cq-room .composer > .cq-more { display:none; }
@container cq-composer (max-width:322px) {
  html:is(.cq-short, .cq-tight) .cq-room .composer:has(> .cq-more) { padding:4px; }
  html:is(.cq-short, .cq-tight) .cq-room .composer:has(> .cq-more) #composer-input { grid-column:1 / 3; grid-row:1; align-self:center; padding:2px 6px; }
  html:is(.cq-short, .cq-tight) .cq-room .composer:has(> .cq-more) #composer-send { grid-column:3; grid-row:1; }
  html:is(.cq-short, .cq-tight) .cq-room .composer:has(> .cq-more) > .cvv-controls { grid-column:1 / 3; grid-row:2; gap:4px; }
  html:is(.cq-short, .cq-tight) .cq-room .composer:has(> .cq-more) > .cvv-controls button { padding:0 2px; }
  .cq-room .composer > .cq-more {
    display:inline-flex; align-items:center; justify-content:center; grid-column:3; grid-row:2;
    padding:0 2px; border:1px solid var(--line-strong); border-radius:var(--r-pill);
    background:transparent; color:var(--ink); font:inherit; font-size:14px; cursor:pointer; touch-action:manipulation;
  }
  .cq-room .composer > .cq-more[aria-expanded="true"] { border-color:var(--eon-accent,var(--lime)); }
  .cq-room .composer > .cq-more:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
  .cq-room .composer:has(> .cq-more[aria-expanded="true"]) #composer-attach { grid-column:1; grid-row:3; }
  .cq-room .composer:has(> .cq-more[aria-expanded="true"]) #composer-mic { grid-column:2; grid-row:3; justify-self:start; }
  .cq-room .composer:has(> .cq-more[aria-expanded="false"]) #composer-attach { display:none; }
  .cq-room .composer-shell:not(:has(> #rec-overlay[style*="flex"])) > .composer:has(> .cq-more[aria-expanded="false"]) #composer-mic { display:none !important; }
  .cq-room .composer:has(> .cq-more[aria-expanded="false"]) #composer-mic { grid-column:2; grid-row:3; justify-self:start; }
}
/* The whole latest turn. With More shown (data-cq-folds-bar:
   chat_conversation.js showMore), the band of 115 px at 190 x 410 began
   mid-answer: the reply's "EON" stood 61 px above it, its first two lines
   under the Chat bar (render cf7). More closed, the bar (app.js's own
   buttons: history, files, full screen, deep mode, new chat) stands behind
   More with Attach and Dictate: 44 px. Opened, More gives the bar back above
   the thread and Attach and Dictate a third row, for as long as it is open.
   No word is smaller and nothing tappable is hidden while More is closed
   except what it names.
   A narrow bar opened did not fit its row (render cf8, 190 x 410: History,
   Files, the bar's name, then Full screen, Deep mode and New chat at x 128
   to 272, the last two past the screen's right edge; at 215 CSS px New chat
   the same). Opened from More, the bar wraps: History, Files and the name on
   one row, Full screen, Deep mode and New chat on the next, at the bar's
   right as they always are, 4 px between the rows. Every button keeps its
   44 px and its place in the tab order; their group wraps too, so even a
   bar narrower than the three of them never puts one off the screen. The
   thread lends the second row (48 px) while More is open; the textbox,
   Send, Mute, End, More and the 56 px stage keep theirs, and closing gives
   the room back. */
html:is(.cq-short, .cq-tight) .cq-room:has(.composer > .cq-more[data-cq-folds-bar][aria-expanded="false"]) .chat-toolbar { display:none; }
html:is(.cq-short, .cq-tight) .cq-room:has(.composer > .cq-more[data-cq-folds-bar][aria-expanded="true"]) .chat-toolbar { flex-wrap:wrap; row-gap:4px; }
html:is(.cq-short, .cq-tight) .cq-room:has(.composer > .cq-more[data-cq-folds-bar][aria-expanded="true"]) .chat-toolbar > :has(> #chat-fullscreen-btn) { flex-wrap:wrap; margin-inline-start:auto; }
/* The same bar with no call (R2 read 2, finding 1). With no call there is
   no More, and the bar never wrapped: at 190 x 410 (380 px with 200% text,
   or CSS zoom 2) Deep mode and New chat stood at x 444 and 544 of a 380 px
   screen in every no-call state of all eight enlarged cases, so they could
   not be tapped. Now the bar wraps wherever its five 44 px buttons do not
   fit one row: History, Files and the bar's name on the first, Full screen,
   Deep mode and New chat on the second at its right, 4 px between. Where
   they fit (ordinary 380, 430 and 1280, a landscape phone, 1280 with 200%
   text) nothing moves: the name grows from 0 (app.css flex:1, min-width:0),
   so the bar breaks only when the buttons alone are wider than it, and the
   group's auto margin takes no room while the name is growing. No button
   is resized, hidden or reordered. */
.cq-room .chat-toolbar { flex-wrap:wrap; row-gap:4px; }
.cq-room .chat-toolbar > :has(> #chat-fullscreen-btn) { flex-wrap:wrap; margin-inline-start:auto; }
/* The bar's name in a narrow room (html.cq-narrow: 200 CSS px or less,
   chat_conversation.js markShortRoom). Wrapped, the name's cell is what the
   first row leaves beside History and Files: 54 px at 190 CSS px, and the
   18 px mark and its 8 px gap left the name 28 px, so "EON" read "E…" with
   More open (R2 read 2, finding 4) and would with no call. There the mark
   steps aside and the name has the whole cell: "EON" whole, a conversation's
   title its first word or so before the ellipsis it always had. The mark is
   app.js's eonLogo, aria-hidden, with no action; the name, every button
   and the bar's rows are unchanged. At 215 CSS px the cell is 79 px, the
   mark stays and the name has 53 px. */
html.cq-narrow .cq-room .cc-brand > .eon-logo { display:none; }
/* What pays for the bar's second row in a narrow short room (190 x 410,
   no call). The wrapped bar takes 48 px more than its one row did, and the
   welcome's thread fell from 139 to about 91 px, under the 97-110 px a
   greeting from app.js's pool needs there (four or five lines at 22 px in
   the 110 px the hero's 24 px sides left it). Here the room's head and the
   composer row's head are 0 (a docked call already has both at 0), the
   composer's frame is 4 px (a call's More composer has it), so the thread
   gets 16 px back; and the greeting is set at 20 px in the hero's own width
   less 8 px a side (142 px): four lines, five at the longest, under 106 px.
   Every word and quick question stays; no control changes size. */
html.cq-narrow.cq-short[data-living] main.cq-room.chat-wrap.lw-content { padding-top:0 !important; }
html.cq-narrow.cq-short[data-living] .cq-room .composer-shell { padding-top:0; }
html.cq-narrow.cq-short .cq-room .composer { padding:4px; }
html.cq-narrow.cq-short .cq-room .eon-hero { padding-inline:8px; }
html.cq-narrow.cq-short .cq-room .eon-hero-greet { font-size:20px; line-height:1.05; }
/* The whole latest turn during any docked compact call, narrow or wide.
   At 1280 px with 200% text (640 x 400, render cf8, More never shown: the
   composer is wide) all eleven words were in the band [124, 234] but the
   reply's "EON" stood at y 101, 32 px over its first line (133): 23 px above
   the band. While the call is docked: no head above the Chat bar (the room's
   4 px) and none above the card in the composer's row (the thread's own 4 px
   foot stays between them), the card's frame is 1 px (its stage keeps
   56 px: rules below), the reply's name sits 2 px over its dashed line and
   2 px under it (7 and 7), its row of actions sits right under its last
   line (4 px) and its foot is 2 px (6). Together 30 px: the reply's "EON"
   to Prepare task in the band with 7 px to spare. At 190 x 410 these and
   the folded bar give 74 px for the 61 px gap. No font size, line height,
   stage or 44 px target changes; a room that is not compact, and Chat with
   no call, keep every one of them. */
html:is(.cq-short, .cq-tight)[data-living] main.cq-room.chat-wrap.lw-content:has(.cvv[data-docked="true"]) { padding-top:0 !important; }
html:is(.cq-short, .cq-tight) .cq-room .composer-shell:has(> .composer > .cvv-controls) { padding-top:0; }
html:is(.cq-short, .cq-tight) .cq-room:has(.cvv[data-docked="true"]) .msg.eon .from { margin-bottom:2px; padding-bottom:2px; }
html:is(.cq-short, .cq-tight) .cq-room:has(.cvv[data-docked="true"]) .msg-actions { margin-top:0; }
html:is(.cq-short, .cq-tight) .cq-room:has(.cvv[data-docked="true"]) .msg.eon { padding-bottom:2px !important; }
html:is(.cq-short, .cq-tight)[data-living] .cq-room:has(.cvv[data-docked="true"]) .chat-body { padding-top:4px; }
/* A narrow docked card (under about 300 CSS px: 190 x 410 is 380 px with
   200% text) is only the stage and its words, in a 1/8 px frame, and the
   thread's foot is the short room's 4 px. Its stage keeps the narrow card's
   56 px: cut to 44 px it gave the thread 12 px (render cf5) and fell under
   the 52 px the drawing needs (cf6); the room now comes from the composer's
   More (above), which gives 44 px. The card is 60 px (64 with the 3 px
   frame it had before render cf8) and the thread's band at least 115 px:
   two whole lines of the answer over its one row of actions. The
   card's own row comes back with its controls when the call ends or the room
   is tall again. */
@container cq-voice (max-width: 300px) {
  html:is(.cq-short, .cq-tight) .cvv[data-docked="true"] { padding:1px 8px; }
}
/* Play audio during a docked call (the engine's resumeAudio: the browser
   blocked EON's sound). Beside More, Mute, Play audio and End need 140 px
   of a 100 px cell (125 at 215 CSS px), and End ran under More, which took
   the tap (R2 finding 1). Wrapping that cell made the composer 48 px taller
   and at 190 x 410 the latest answer lost its first four words above the
   thread's band. So Play audio stays on the card (chat_voice_view.js
   keepResume), in the row the card already has: on a narrow card in the
   stage's place, over the stage, which keeps its 56 px and its box and is
   back as soon as the sound plays; on a wide card beside the status words.
   The card, the composer, Mute, End, More and the textbox keep their size
   and place, and every button keeps 44 px. */
.cvv[data-docked="true"] > .cvv-row > .cvv-resume {
  position:relative; z-index:1; min-width:44px; min-height:44px; padding:0 2px;
  border:1px solid var(--line-strong); border-radius:var(--r-md); background:var(--bg-card); color:var(--ink);
  font:inherit; font-size:14px; line-height:1.2; cursor:pointer; -webkit-user-select:none; user-select:none; touch-action:manipulation;
}
.cvv[data-docked="true"] > .cvv-row > .cvv-resume[hidden] { display:none; }
.cvv[data-docked="true"] > .cvv-row > .cvv-resume:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
@container cq-voice (max-width: 300px) {
  .cvv[data-docked="true"] > .cvv-row > .cvv-resume { grid-column:1; grid-row:1; align-self:stretch; justify-self:stretch; }
  .cvv[data-docked="true"]:has(> .cvv-row > .cvv-resume:not([hidden])) .cvv-status { grid-column:2; }
}
@container cq-voice (min-width: 301px) {
  html:is(.cq-short, .cq-tight) .cvv[data-docked="true"] > .cvv-row > .cvv-resume { grid-column:3; grid-row:1; padding:0 14px; border-radius:var(--r-pill); }
}
html:is(.cq-short, .cq-tight)[data-living] .cq-room:has(.cvv[data-docked="true"]) .chat-body { padding-bottom:4px; }
/* A page zoomed by CSS zoom (chat_conversation.js markShortRoom): the living
   shell's 100dvh is multiplied by the zoom, so the room is kept within what
   is left of the screen below its own top. The shell itself is not changed;
   browser zoom and text size never set this. Where even the room's smallest
   content does not fit what is left (380 px at CSS zoom 2: a 204 px room for
   a 228 px card and composer), the room scrolls rather than clipping: the
   living shell's overflow:hidden for this room cut Mute and End in half with
   no way to reach them (render cf3, c73ddb00). A room that fits never
   scrolls. */
html.cq-zoomed[data-living] main.cq-room { max-height:var(--cq-room-fit); overflow-y:auto; }
/* Jump to latest (app.js, #chat-jump) floats a fixed 148 px above the
   screen's bottom, a guess at the composer's height. In Chat the composer's
   row also carries the call card and, at 200% text, three rows of controls,
   so the guess put the button over the textbox. Here (by id, over app.css's
   chat-full and keyboard offsets) it floats just above that row's top edge
   wherever the browser can anchor to it (elsewhere app.css's offset stays),
   and it is a full 44 px target. */
.cq-room #chat-jump { width: 44px; height: 44px; }
@supports (anchor-name: --a) {
  .cq-room .composer-shell { anchor-name: --cq-composer-row; }
  .cq-room #chat-jump { position-anchor: --cq-composer-row; bottom: calc(anchor(top) + 8px); }
}
