/* ---------- log ---------- */
main { flex: 1; min-height: 96px; overflow-y: auto; padding: 10px 0; display: flex; flex-direction: column; gap: 6px; }
/* Like a chat app, lines sit at the bottom, so the newest one is right above the suggested reply.
   (A top auto margin, not justify-content: flex-end, which would cut off the top when it scrolls.) */
main > :first-child { margin-top: auto; }
/* Nothing in the chat shrinks to fit: a long conversation scrolls. (The reply bubble, with its min-height, used
   to get squeezed shorter than its text, which then ran out of it.) */
main > * { flex-shrink: 0; }
.jump { position: fixed; left: 50%; transform: translateX(-50%); bottom: 230px; z-index: 2; background: var(--color-text); color: var(--color-bg);
  border: 0; border-radius: var(--radius-pill); padding: 6px 14px; font-size: var(--text-xs); font-weight: 600; cursor: pointer; }
.msg { background: var(--color-surface); border-radius: var(--radius-s); padding: 8px 12px; border-left: 3px solid var(--color-border); font-size: var(--text-md); }
/* Long unbroken words (names, booking codes, addresses without spaces) wrap inside the bubble instead of
   running out of it. */
.msg, .draft, .welcome, .you-said, .note-line, .goal-text, .note-head h3, .note-item strong { overflow-wrap: anywhere; min-width: 0; }
.msg .who { font-size: var(--text-2xs); color: var(--color-text-muted); margin-bottom: 1px; }
.msg .tr { margin-top: 3px; color: var(--color-text-muted); font-size: var(--text-sm); }
.msg.me { border-left-color: var(--color-action); }
.msg.agent { border-left-color: var(--color-them); }
.msg.babble { border-left-color: var(--color-accent); }
.msg.sys, .msg.note { background: none; color: var(--color-text-muted); font-size: var(--text-xs); text-align: center; border: 0; padding: 2px; }
.msg.note a { color: var(--color-action); font-weight: 600; }
.msg.steer { background: none; border: 0; color: var(--color-text-muted); font-size: var(--text-xs); font-style: italic; padding: 0 12px; }
/* Hands-free conversations read as a chat: them on the left, you on the right. Readability goes to the
   newest line, where the eye is; older lines step back. */
body:not([data-mode="code"]) main .msg.agent, body:not([data-mode="code"]) main .msg.me, body:not([data-mode="code"]) main .msg.babble {
  max-width: 84%; border: 0; border-radius: var(--radius-l); padding: 9px 15px; cursor: pointer; transition: opacity .2s, font-size .2s; }
body:not([data-mode="code"]) main .msg.agent { position: relative; align-self: flex-start; margin-inline-start: 38px; background: var(--color-bubble-them);
  border-end-start-radius: var(--radius-xs); }
body:not([data-mode="code"]) main .msg.me { align-self: flex-end; background: var(--color-bubble-me); border-end-end-radius: var(--radius-xs); }
body:not([data-mode="code"]) main .msg.babble { align-self: flex-start; background: var(--color-bubble-babble); border: 1.5px solid var(--color-border);
  border-end-start-radius: var(--radius-xs); }
/* Their avatar is their language, written in its own script (हि, 中, Es): who's talking, at a glance. Shown once per run of lines. */
body:not([data-mode="code"]) main .msg.agent::before { content: attr(data-av); position: absolute; inset-inline-start: -38px; bottom: 0; width: 30px; height: 30px;
  display: grid; place-items: center; border-radius: var(--radius-round); background: var(--color-them); color: var(--color-surface); font-size: var(--text-xs); font-weight: 700;
  font-style: normal; line-height: 1; }
body:not([data-mode="code"]) main .msg.agent + .msg.agent::before { visibility: hidden; }
body:not([data-mode="code"]) main .msg.agent + .msg.agent { margin-top: -2px; }
.msg.sep { align-self: center; background: none; border: 0; padding: 6px 0 2px; font-size: var(--text-2xs); color: var(--color-text-muted); }
body:not([data-mode="code"]) main .msg.steer { align-self: flex-end; text-align: end; }
main .msg.old { opacity: .6; }
main .msg.latest .body { font-size: var(--text-5xl); line-height: 1.28; font-weight: 600; }
main .msg.latest .tr { font-size: var(--text-lg); }
/* Your own words you already know: the big type stays on what they said. */
body:not([data-mode="code"]) main .msg.me.latest .body { font-size: var(--text-2xl); line-height: 1.3; }
body:not([data-mode="code"]) main .msg.me.latest .tr { font-size: var(--text-md); }
/* Forming: someone's still talking, or Babble is still working the line out. The border pulses until it settles. */
main .msg.forming, .hearing { animation: forming 1.3s ease-in-out infinite; --ring: rgb(var(--rgb-them) / .7); }
main .msg.unsure.forming, .hearing { --ring: rgb(var(--rgb-text-muted) / .5); }
@keyframes forming { 0%, 100% { box-shadow: 0 0 0 1px transparent; } 50% { box-shadow: 0 0 0 3px var(--ring); } }
@media (prefers-reduced-motion: reduce) { main .msg.forming, .hearing { animation: none; box-shadow: 0 0 0 2px var(--ring); } }
main .msg.playing { box-shadow: 0 0 0 3px var(--color-action); animation: none; }
/* Babble can't tell who said it: the bubble waits in the middle for a swipe (left = them, right = you). */
main .msg.unsure { align-self: center; max-width: 88%; border: 1.5px dashed var(--color-text-muted); border-radius: var(--radius-ml); background: var(--color-surface);
  padding: 8px 14px; touch-action: pan-y; user-select: none; -webkit-user-select: none; cursor: grab;
  transition: transform .25s, background .2s, opacity .3s; }
main .msg.unsure .body { font-size: var(--text-3xl); line-height: 1.3; }
main .msg.unsure[data-lean="them"] { background: var(--color-bubble-them); }
main .msg.unsure[data-lean="me"] { background: var(--color-bubble-me); }
main .msg.unsure.to-them { align-self: flex-start; background: var(--color-bubble-them); border-style: solid; border-color: transparent; }
main .msg.unsure.to-me { align-self: flex-end; background: var(--color-bubble-me); border-style: solid; border-color: transparent; }
main .msg.unsure.waiting .swipe-hint, main .msg.unsure.to-them .swipe-hint, main .msg.unsure.to-me .swipe-hint { visibility: hidden; }
.swipe-hint { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 6px; font-size: var(--text-2xs); color: var(--color-text-muted); }
.swipe-hint button { background: none; border: 1px solid var(--color-border); border-radius: var(--radius-pill); padding: 4px 10px; font-size: var(--text-xs); color: var(--color-text); cursor: pointer; }
/* Computing → settled: a line still being translated shows a soft placeholder, then the text lands. */
main .msg .part { transition: color .25s; }
main .msg .body .part.pending { color: var(--color-text-muted); font-style: italic; font-weight: 400; animation: breathe 1.4s ease-in-out infinite; }
@keyframes breathe { 50% { opacity: .45; } }
/* Someone is talking (or Babble is still working it out): three dots where the next line will land. */
.hearing { align-self: flex-start; display: flex; gap: 5px; margin-inline-start: 38px; padding: 12px 16px; border-radius: var(--radius-l);
  border-end-start-radius: var(--radius-xs); background: var(--color-bubble-them); }
.hearing span { width: 8px; height: 8px; border-radius: var(--radius-round); background: var(--color-text-muted); animation: pulse 1s ease-in-out infinite; }
.hearing span:nth-child(2) { animation-delay: .15s; }
.hearing span:nth-child(3) { animation-delay: .3s; }
