/* The public inbound pages on start.<domain>. The prospect arrives from
   augmented.engineering, so these pages take the site's look and its tokens
   (apps/site/src/styles/index.css): Red Hat Display, hairlines, square corners and
   the square dot, in the site's dark and light themes. Platform screens keep
   core/src/ui/base.css. */

/* Both themes in one set of tokens: light-dark() takes the first value under a light
   color-scheme and the second under a dark one. theme.js sets data-theme on <html>
   before the first paint; without it, the OS preference decides. As on the site,
   --ink is the page and --paper is the type. */
:root {
  --font: "Red Hat Display", -apple-system, "Segoe UI", sans-serif;
  --font-text: "Red Hat Text", -apple-system, "Segoe UI", sans-serif;
  color-scheme: light dark;
  --ink: light-dark(#ffffff, #0a0a0a);
  --paper: light-dark(#0a0a0a, #ffffff);
  /* The conversation stage, and the cards and panels raised off the page. */
  --stage: light-dark(#fafafa, #0c0c0c);
  --raised: light-dark(#ffffff, #0f0f0f);
  --field: light-dark(#ffffff, #151515);
  --field-focus: light-dark(#ffffff, #1a1a1a);
  --gray: light-dark(#666666, #8c8c8c);
  --hair: light-dark(#e6e6e6, #1f1f1f);
  --hair-lit: light-dark(#cccccc, #333333);
  --field-line: light-dark(#8f8f8f, #4a4a4a);
  --body: light-dark(#3d3d3d, #b8b8b8);
  --strong: light-dark(#161616, #ebebeb);
  --wash: light-dark(#f2f2f2, #161616);
  --wash-strong: light-dark(#e9e9e9, #1d1d1d);
  --grid-line: light-dark(rgba(10, 10, 10, 0.045), rgba(255, 255, 255, 0.035));
  --edge: light-dark(rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.06));
  --shade-1: light-dark(rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.45));
  --shade-2: light-dark(rgba(0, 0, 0, 0.07), rgba(0, 0, 0, 0.55));
  --error: light-dark(#c22d36, #ff7a7e);
  --error-ink: light-dark(#8c1c23, #ffd6d7);
  --error-bg: light-dark(#fdf2f2, #1e1012);
  --error-line: light-dark(#e3a2a6, #7a3b3e);
  --ok: light-dark(#1e9a5b, #5fd39a);
  --ok-line: light-dark(#8acda7, #2f6a4c);
  --gutter: clamp(16px, 4vw, 64px);
}
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

* { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }
body {
  min-height: 100svh; display: flex; flex-direction: column;
  background: var(--ink); color: var(--paper);
  font-family: var(--font); font-size: 18px; line-height: 1.55;
  -webkit-font-smoothing: antialiased; font-synthesis: none;
}
a { color: inherit; text-underline-offset: 4px; }
button, input, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
:focus-visible { outline: 2px solid var(--paper); outline-offset: 3px; }
::selection { background: var(--paper); color: var(--ink); }
input, textarea { caret-color: var(--paper); }
.visually-hidden { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
[hidden] { display: none !important; }

/* ---------- frame ---------- */
.top {
  display: flex; justify-content: space-between; align-items: center; gap: 16px;
  padding: 22px var(--gutter); border-bottom: 1px solid var(--hair);
}
.top-brand { display: flex; align-items: center; gap: clamp(8px, 1.1vw, 14px); min-width: 0; }
.wordmark { font-size: 18px; letter-spacing: -0.02em; text-decoration: none; white-space: nowrap; }
.wordmark .heavy { font-weight: 800; }
.wordmark .light { font-weight: 300; }
.dot { display: inline-block; vertical-align: baseline; width: 0.14em; height: 0.14em; margin: 0 0.055em; background: currentColor; }
.top-meta { display: flex; align-items: center; gap: 18px; font-size: 15px; color: var(--gray); min-width: 0; }
.top-meta strong { color: var(--paper); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.top-meta a { text-decoration: none; }
.top-meta a:hover { color: var(--paper); }

/* The dark and light switch, as on augmented.engineering: two squares, each a
   swatch of the theme it selects. The current theme's square carries the outline
   that keeps it visible on its own page. Each button is a 24px target around a
   14px square. Hidden until theme.js has run, because the buttons need it. */
.theme-switch { display: flex; align-items: center; flex: none; }
:root:not([data-theme]) .theme-switch { visibility: hidden; }
.sw { position: relative; width: 24px; height: 24px; padding: 0; border: 0; background: none; }
.sw::before { content: ""; position: absolute; inset: 5px; border: 1px solid transparent; transition: transform 0.2s ease, border-color 0.2s ease; }
.sw-dark::before { background: #0a0a0a; }
.sw-light::before { background: #ffffff; }
:root[data-theme="dark"] .sw-dark::before { border-color: #ffffff; }
:root[data-theme="light"] .sw-light::before { border-color: #0a0a0a; }
.sw:hover::before { transform: scale(1.15); }
.sw:focus-visible { outline-width: 1px; outline-offset: 0; }

main { flex: 1; width: 100%; max-width: calc(1320px + 2 * var(--gutter)); margin: 0 auto; padding: clamp(40px, 7vw, 104px) var(--gutter) clamp(56px, 8vw, 120px); }
.foot {
  border-top: 1px solid var(--hair); padding: 28px var(--gutter);
  display: flex; justify-content: space-between; gap: 12px 24px; flex-wrap: wrap;
  font-size: 15px; color: var(--gray);
}
.foot a { text-decoration: none; }
.foot a:hover { color: var(--paper); }

/* ---------- type ---------- */
.eyebrow { font-size: 12px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: var(--gray); }
h1 {
  font-size: clamp(32px, 4.4vw, 58px); font-weight: 700; line-height: 1.08;
  letter-spacing: 0.12em; text-transform: uppercase; text-wrap: balance;
}
.lede { font-size: clamp(20px, 1.9vw, 24px); line-height: 1.45; letter-spacing: -0.012em; color: var(--strong); max-width: 34ch; }
.label, .field > label {
  font-size: 12px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: var(--gray);
}

/* Where the person is: two short bars, the first filled at the details, both at
   the conversation, with the step in words beside them. */
.steps { display: inline-flex; align-items: center; gap: 10px; font-size: 13px; font-weight: 500; color: var(--gray); white-space: nowrap; font-variant-numeric: tabular-nums; }
.steps-bar { display: inline-flex; gap: 4px; }
.steps-bar i { width: 16px; height: 3px; background: var(--hair-lit); }
.steps-bar i[data-on] { background: var(--paper); }

/* The agent at rest, drawn in CSS: the canvas orb (client/talk/orb-gl.ts) in the
   look data-orb on #talk names. Pearl, the default: a soft sphere lit from the
   upper left, with a glint, a faint cool sheen and a bright rim. It stands for the
   agent in an empty chat. */
.log:empty::before {
  border-radius: 50%;
  background:
    radial-gradient(circle at 34% 30%, rgba(255, 255, 255, 0.95) 0, rgba(255, 255, 255, 0.5) 4%, rgba(255, 255, 255, 0) 13%),
    radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 0) 62%, rgba(236, 240, 255, 0.34) 97%),
    conic-gradient(from 210deg, rgba(150, 185, 255, 0.14), rgba(196, 176, 255, 0.12), rgba(140, 236, 220, 0.13), rgba(150, 185, 255, 0.14)),
    radial-gradient(circle at 36% 32%, #e2e3e6 0%, #a3a4a8 24%, #5a5b5f 52%, #2a2a2d 78%, #161618 100%);
  background-blend-mode: normal, screen, soft-light, normal;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.42), 0 0 3px rgba(255, 255, 255, 0.35), 0 0 22px rgba(225, 232, 255, 0.12);
  animation: breathe 6s ease-in-out infinite;
}
/* On a light page the sphere's own dark edge defines it, and the glow that lifts it
   off a dark page would be white on white; a soft shadow under it does that work. */
:root[data-theme="light"] .log:empty::before {
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.3), 0 6px 14px rgba(0, 0, 0, 0.16), 0 1px 3px rgba(0, 0, 0, 0.2);
}
@keyframes breathe { 50% { transform: scale(1.03); filter: brightness(1.08); } }

/* ---------- the gate ---------- */
/* Wide: the heading on the left, the form on the right, as one centred group: the
   left column is as wide as the heading, so the two do not drift apart. Narrow: the
   heading, then the form. The home page's close lays itself out the same way
   (apps/site/src/styles/index.css, .pf-close). */
.gate {
  --gate-gap: clamp(56px, 7vw, 112px);
  display: grid; align-items: center; justify-content: center;
  grid-template-columns: minmax(0, 520px) minmax(0, 500px);
  grid-template-areas: "intro panel";
  column-gap: var(--gate-gap); row-gap: clamp(40px, 4.4vw, 64px);
}
.gate-intro { grid-area: intro; display: flex; flex-direction: column; gap: clamp(30px, 3.4vw, 46px); padding-top: clamp(0px, 1vw, 14px); container-type: inline-size; }
/* The site's hero voice: a light line over a heavy one, set close. */
.gate h1 {
  font-size: clamp(44px, 5.8vw, 84px); font-weight: 500; line-height: 1.02;
  letter-spacing: -0.035em; text-transform: none; text-wrap: balance;
}
.gate h1 b { display: block; font-weight: 800; }
/* The agent at rest under the heading: the orb from the conversation page, so the
   left column holds the thing the person is about to talk to. The canvas leaves
   room for the halo, so it is pulled left and up to line the orb up with the
   heading. Wide screens only: a phone goes from the heading straight to the form. */
.gate-orb {
  --orb: clamp(300px, 34vw, 480px);
  /* from the orb's edge (its centre is a third of --orb into the column, its radius
     a third of --orb), across the gap and a little under the panel, which hides the
     route's end */
  --reach: calc(100cqw - var(--orb) * 0.66 + var(--gate-gap) + 24px);
  position: relative; z-index: 0;
  width: var(--orb); aspect-ratio: 1; max-width: 100%;
  margin: calc(var(--orb) * -0.1) 0 calc(var(--orb) * -0.1) calc(var(--orb) * -0.17);
}
/* The agent reaches for the form: one route from the orb, drawn once the orb has
   arrived, and a square pulse travelling along it into the panel, as on the home
   page's close. */
.gate-orb::before,
.gate-orb::after { content: ""; position: absolute; z-index: -1; left: 83%; top: 50%; }
.gate-orb::before {
  width: var(--reach); height: 1px; background: color-mix(in srgb, var(--paper) 20%, transparent);
  transform-origin: left center; animation: gate-route 1.1s cubic-bezier(0.2, 0.7, 0.2, 1) 0.9s both;
}
.gate-orb::after { width: 6px; height: 6px; margin: -2.5px 0 0 -3px; background: var(--paper); opacity: 0; animation: gate-reach 3.4s cubic-bezier(0.45, 0, 0.25, 1) 1.8s infinite; }
@keyframes gate-route { from { transform: scaleX(0); } }
@keyframes gate-reach {
  0% { opacity: 0; transform: translateX(0); }
  8% { opacity: 1; }
  60%, 100% { opacity: 1; transform: translateX(var(--reach)); }
}
@media (prefers-reduced-motion: reduce) {
  .gate-orb::before { animation: none; }
  .gate-orb::after { display: none; }
}
@media (max-width: 1000px) { .gate-orb { display: none; } }
.gate > .panel { grid-area: panel; position: relative; }

/* Laptops and desktops: the gate fills the window and the page does not scroll. The
   orb and the padding follow the window's height, and a panel taller than the
   window (the call and contact requests) scrolls inside itself. Phones and short
   windows scroll as a normal page. */
@media (min-width: 1001px) and (min-height: 600px) {
  body:has(main > .gate) { height: 100svh; height: 100dvh; overflow: hidden; }
  main:has(> .gate) { flex: 1; min-height: 0; display: flex; flex-direction: column; padding-block: clamp(24px, 6svh, 88px); }
  .gate { flex: 1; min-height: 0; grid-template-rows: minmax(0, 1fr); }
  .gate-intro { min-height: 0; }
  .gate-orb { --orb: clamp(220px, min(34vw, 100svh - 440px), 480px); }
  /* justify-self: end, so a wider panel grows to the left (start.ts animates it). The
     panel's body scrolls, not the panel, so its padding stays clear of the content.
     The body's inline padding leaves room for the focus rings. */
  .gate > .panel { justify-self: end; width: 100%; max-height: 100%; display: flex; flex-direction: column; overflow: hidden; }
  .gate > .panel > .panel-body { min-height: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; margin-inline: -8px; padding-inline: 8px; }
  /* The requests take a wider panel, with the days in two columns, so less of the
     panel scrolls. */
  /* The panel scrolls inside itself here, so it can stay centred beside the orb at
     any height, and the orb's route meets it whether it holds the forms or the
     request that was sent. */
  .gate:has([data-panel-body][data-state="human"]) { --gate-gap: clamp(40px, 5vw, 96px); grid-template-columns: minmax(0, 520px) minmax(0, 660px); align-items: center; }
  .panel-body[data-state="human"] .slot-days { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* While the call form scrolls inside the panel, its button stays in view at the
     panel's foot, over a fade that shows more of the form lies behind it. */
  .panel-body[data-state="human"] .request-part:not([data-state="sent"]) .panel-actions {
    position: sticky; bottom: 0; z-index: 1; background: var(--raised);
    padding-top: 12px; margin-top: -12px; box-shadow: 0 1px 0 var(--raised);
  }
  .panel-body[data-state="human"] .request-part:not([data-state="sent"]) .panel-actions::before {
    content: ""; position: absolute; left: 0; right: 0; bottom: 100%; height: 28px; pointer-events: none;
    background: linear-gradient(to bottom, transparent, var(--raised));
  }
}
/* A laptop's window: the frame and the form tighten so the details fit. The Turnstile
   widget names itself, so its label is for screen readers only. */
@media (min-width: 1001px) and (min-height: 600px) and (max-height: 820px) {
  body:has(main > .gate) .top { padding-block: 14px; }
  body:has(main > .gate) .foot { padding-block: 14px; }
  main:has(> .gate) { padding-block: clamp(16px, 3svh, 32px); }
  .gate > .panel { padding: 24px 32px; }
  .gate .panel-head { margin-bottom: 18px; }
  .gate .form { gap: 14px; }
  .gate .field { gap: 7px; }
  .gate .field input { min-height: 48px; padding-block: 10px; }
  .gate #check-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}
/* "Talk now" and "Talk to human" share the row equally. */
.choose .btn { flex: 1 1 0; }

/* "Talk to human" (P21): the same panel holds the call and contact requests.
   client/start.ts animates the change; the second step bar fills as it lands. */
/* Where the page scrolls (phones, short windows), the requests make a tall panel, so
   the heading moves up to its top (start.ts animates the move). On a laptop or a
   desktop the panel scrolls inside itself and stays centred (below). */
@media (max-width: 1000px), (max-height: 599px) {
  .gate:has([data-panel-body][data-state="human"]) { align-items: start; }
}
.panel-body[data-state="human"] { display: flex; flex-direction: column; gap: 26px; }
.panel-body[data-state="human"] .panel-head { margin-bottom: 0; }
.panel-head h2:focus { outline: none; }
.panel-body[data-state="human"] .steps-bar i:last-child { transform-origin: left center; animation: fill-step 0.5s cubic-bezier(0.2, 0.7, 0.2, 1) 0.3s both; }
@keyframes fill-step { from { transform: scaleX(0); } }
.request-part { display: flex; flex-direction: column; gap: 18px; }
.request-part fieldset { border: 0; padding: 0; margin: 0; min-width: 0; }
.request-part legend { padding: 0; margin-bottom: 12px; }
.request-part .field textarea {
  width: 100%; min-height: 88px; max-height: 220px; padding: 13px 16px; resize: vertical;
  background: var(--field); border: 1px solid var(--field-line); border-radius: 0;
  color: var(--paper); font-family: var(--font-text); font-size: 17px; line-height: 1.5;
  transition: border-color 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease;
}
.request-part .field textarea:focus { outline: none; border-color: var(--paper); background: var(--field-focus); box-shadow: 0 0 0 1px var(--paper); }
.request-part .panel-actions .btn { flex: 1 1 auto; }
.request-more { border-top: 1px solid var(--hair-lit); padding-top: 22px; gap: 0; }
.request-more > form { margin-top: 20px; }
.request-part[data-state="sent"] { border-left: 2px solid var(--ok); padding: 2px 0 2px 18px; gap: 12px; }
label.slot:has(input:disabled) { opacity: 0.3; cursor: not-allowed; }
label.slot:has(input:disabled) input { cursor: not-allowed; }

/* ---------- the Talk now dialog ---------- */
.confirm {
  margin: auto; width: min(500px, calc(100vw - 32px)); max-height: calc(100svh - 32px);
  border: 1px solid var(--hair-lit); border-radius: 0; background: var(--raised); color: var(--paper);
  padding: clamp(24px, 3.4vw, 40px);
  box-shadow: inset 0 1px 0 var(--edge), 0 8px 24px var(--shade-1), 0 40px 96px var(--shade-2);
  opacity: 0; transform: translateY(14px) scale(0.98);
  transition: opacity 0.2s ease, transform 0.32s cubic-bezier(0.2, 0.7, 0.2, 1), overlay 0.32s allow-discrete, display 0.32s allow-discrete;
}
.confirm[open] { opacity: 1; transform: none; }
@starting-style { .confirm[open] { opacity: 0; transform: translateY(14px) scale(0.98); } }
.confirm::backdrop {
  background: rgba(10, 10, 10, 0); backdrop-filter: blur(0);
  transition: background 0.25s ease, backdrop-filter 0.25s ease, overlay 0.32s allow-discrete, display 0.32s allow-discrete;
}
.confirm[open]::backdrop { background: rgba(10, 10, 10, 0.5); backdrop-filter: blur(4px); }
@starting-style { .confirm[open]::backdrop { background: rgba(10, 10, 10, 0); backdrop-filter: blur(0); } }
.confirm-body { display: flex; flex-direction: column; gap: 14px; }
.confirm-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 6px; }
.confirm-close {
  flex: none; display: inline-grid; place-items: center; width: 40px; height: 40px; margin: -6px -8px 0 0;
  border: 1px solid transparent; background: none; color: var(--gray); cursor: pointer; transition: color 0.2s ease, border-color 0.2s ease;
}
.confirm-close:hover { color: var(--paper); border-color: var(--hair-lit); }
.confirm-close:focus-visible { outline: 2px solid var(--paper); outline-offset: 2px; }
.confirm-close svg { width: 20px; height: 20px; }
.confirm .btn svg { width: 20px; height: 20px; flex: none; }
.confirm h2 { display: flex; align-items: center; gap: 12px; padding-top: 2px; font-size: 24px; font-weight: 600; letter-spacing: -0.015em; text-transform: none; }
.confirm p { font-size: 17px; line-height: 1.55; color: var(--body); text-wrap: pretty; }
.confirm p.small { font-size: 14px; color: var(--gray); }
.confirm .actions { margin-top: 12px; }
.confirm .actions .btn { flex: 1 1 0; }
@media (prefers-reduced-motion: reduce) {
  .confirm, .confirm::backdrop { transition: none; }
  .panel-body[data-state="human"] .steps-bar i:last-child { animation: none; }
}

/* The form: the one thing to do on the page, so it is the one raised surface. */
.panel {
  border: 1px solid var(--hair-lit); background: var(--raised); padding: clamp(22px, 3vw, 40px);
  box-shadow: inset 0 1px 0 var(--edge), 0 4px 12px var(--shade-1), 0 24px 56px var(--shade-2);
}
.panel-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 28px; }
.panel-head h2 { font-size: 24px; font-weight: 600; letter-spacing: -0.015em; }
.form { display: flex; flex-direction: column; gap: 22px; }
.field { display: flex; flex-direction: column; gap: 9px; min-width: 0; }
.field input {
  width: 100%; min-height: 54px; padding: 13px 16px;
  background: var(--field); border: 1px solid var(--field-line); border-radius: 0;
  color: var(--paper); font-size: 18px; line-height: 1.5;
  transition: border-color 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease;
}
@media (hover: hover) { .field input:hover { border-color: var(--gray); } }
.field input:focus { outline: none; border-color: var(--paper); background: var(--field-focus); box-shadow: 0 0 0 1px var(--paper); }
.field input[aria-invalid="true"] { border-color: var(--error); }
.field-error { font-size: 15px; color: var(--error); }
.check { min-height: 65px; }
/* The honeypot. Off screen rather than display:none, as on the enquiry form. */
.trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.alert { border: 1px solid var(--error-line); background: var(--error-bg); color: var(--error-ink); padding: 14px 16px; font-size: 16px; }
.notice { border: 1px solid var(--hair); color: var(--body); padding: 14px 16px; font-size: 16px; }
.open-session { margin-bottom: 22px; }
/* P24: the email code. */
[data-state="code"] > .notice, [data-state="code"] > .alert { margin-bottom: 22px; }
.code-sent { margin-bottom: 22px; font-size: 16px; color: var(--body); overflow-wrap: anywhere; }
.code-sent strong { color: var(--paper); font-weight: 600; }
.field .code-input { font-size: 24px; letter-spacing: 0.3em; font-variant-numeric: tabular-nums; }
[data-state="code"] .form + .form { margin-top: 14px; }
.small { font-size: 14px; color: var(--gray); }
.small a { color: var(--paper); }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 12px;
  min-height: 54px; padding: 14px 28px; border: 1px solid var(--paper); border-radius: 0;
  background: var(--paper); color: var(--ink); font-size: 17px; font-weight: 600; text-decoration: none; white-space: nowrap;
  transition: transform 0.25s ease, background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}
.btn:hover { transform: translateY(-2px); }
.btn:disabled { opacity: 0.55; cursor: default; transform: none; }
.btn.ghost { background: transparent; color: var(--paper); border-color: var(--hair-lit); }
.btn.ghost:hover { border-color: var(--paper); }
.btn.wide { width: 100%; }
.btn svg { width: 20px; height: 20px; flex: none; }
.actions { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
@media (prefers-reduced-motion: reduce) { .btn, .btn:hover { transition: none; transform: none; } }

/* ---------- plain states: busy, ended, not found ---------- */
.state { max-width: 720px; display: flex; flex-direction: column; gap: 24px; }
.state p { font-size: 20px; color: var(--body); }

/* ---------- the conversation ---------- */
/* One panel, the stage, holds the whole conversation. #talk carries the state in
   data-phase (ready, connecting, live, ended, over), data-mode (voice, text) and
   data-view (orb, chat), and talk/ui.ts hides what a state does not need.
   The conversation page fits the window, as an app does. The page never scrolls:
   the messages, the blueprint and the panels scroll inside the stage, and the
   composer and the controls stay at the bottom. The footer is left off this page. */
body:has(main > .talk) { height: 100svh; height: 100dvh; overflow: hidden; }
body:has(main > .talk) > .foot { display: none; }
main:has(> .talk) { flex: 1; min-height: 0; display: flex; flex-direction: column; padding-top: clamp(16px, 3svh, 36px); padding-bottom: clamp(14px, 2.4svh, 28px); }
.talk {
  flex: 1; min-height: 0; width: 100%; max-width: 1180px; margin: 0 auto; display: flex; flex-direction: column; gap: clamp(12px, 2svh, 22px);
  /* The caption type, which the caption window (below, .orb-main) counts in. */
  --cap-size: clamp(18px, 1.8vw, 21px);
  --cap-lh: calc(var(--cap-size) * 1.42);
  --you-lh: 24px;
}
/* The heading says what to do on this page; the session's limits sit to the right. */
.talk-head { display: flex; justify-content: space-between; align-items: flex-end; flex-wrap: wrap; gap: 8px 32px; }
.talk-title { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; min-width: 0; }
.talk-head h1 { font-size: clamp(22px, 2.3vw, 30px); line-height: 1.2; letter-spacing: -0.01em; text-transform: none; font-weight: 600; text-wrap: balance; }
.talk-head .meta-row { font-size: 14px; }
.meta-row { display: flex; flex-wrap: wrap; gap: 8px 22px; font-size: 15px; color: var(--gray); }
.meta-row strong { color: var(--paper); font-weight: 600; }

/* The stage takes the height the heading leaves. */
.stage {
  flex: 1; min-height: 0; display: flex; flex-direction: column;
  border: 1px solid var(--hair-lit); background: var(--stage);
}
.stage-bar {
  display: flex; justify-content: space-between; align-items: center; gap: 12px;
  min-height: 60px; padding: 10px 12px 10px clamp(18px, 3vw, 28px); border-bottom: 1px solid var(--hair);
}
.bar-actions { display: flex; gap: 8px; }
.stage-note { font-size: 14px; color: var(--gray); margin-top: -6px; }

/* The state: a square that is green while the microphone is open, solid while the
   agent speaks, pulsing grey while something is on its way, and hollow when muted. */
.status { display: inline-flex; align-items: center; gap: 10px; font-size: 12px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: var(--strong); white-space: nowrap; }
.status::before { content: ""; flex: none; width: 8px; height: 8px; background: var(--hair-lit); border: 1px solid transparent; transition: background-color 0.3s ease, border-color 0.3s ease; }
.status[data-state="listening"]::before, .status[data-state="connected"]::before { background: var(--ok); }
.status[data-state="speaking"]::before { background: var(--paper); animation: pulse 1.2s ease-in-out infinite; }
.status[data-state="connecting"]::before, .status[data-state="thinking"]::before, .status[data-state="replying"]::before { background: var(--gray); animation: pulse 1s ease-in-out infinite; }
.status[data-state="muted"]::before { background: transparent; border-color: var(--paper); }
.status[data-state="failed"]::before, .status[data-state="lost"]::before, .status[data-state="microphone"]::before { background: var(--error); }
@keyframes pulse { 50% { opacity: 0.3; } }

/* ---- voice: the orb and captions ---- */
/* The orb takes the height the captions leave, up to 300px, so the orb, the
   agent's line and the person's words always fit without scrolling. The view is
   a size container so the orb can read that height (cqh). */
.orb-view {
  flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; container-type: size;
  /* safe: a tall view starts at the top instead of being cut off above. */
  display: flex; flex-direction: column; align-items: center; justify-content: safe center;
  gap: 14px; padding: clamp(12px, 2.4vw, 24px) clamp(18px, 4vw, 48px) 10px; text-align: center;
}
.orb-main {
  width: 100%; display: flex; flex-direction: column; align-items: center; gap: 16px;
  /* The caption window (talk/ui.ts, captions). --cap-lines is how many lines of
     the agent's line it shows: three, or five when the line is longer
     (data-long-caption), and the orb gives up the height. Under it, two lines of
     the person's own words. --cap-area is the height all of that reserves. */
  --cap-lines: 3;
  --you-lines: 2;
  --cap-area: calc(var(--cap-lines) * var(--cap-lh) + 10px + var(--you-lines) * var(--you-lh));
}
.talk[data-long-caption][data-phase="live"] .orb-main { --cap-lines: 5; }
.talk:is([data-phase="ready"], [data-phase="ended"], [data-phase="over"]) .orb-main { --cap-lines: 2; --you-lines: 0; }
/* A short stage keeps the orb by showing fewer lines at a time. */
@container (max-height: 420px) {
  .orb-main { --you-lines: 1; }
  .talk[data-long-caption][data-phase="live"] .orb-main { --cap-lines: 4; }
}
@container (max-height: 320px) {
  .talk[data-long-caption][data-phase="live"] .orb-main { --cap-lines: 3; }
}
.orb-frame {
  width: clamp(72px, min(64cqw, 100cqh - var(--cap-area) - 16px), 300px); aspect-ratio: 1; flex: none;
  transition: width 0.5s cubic-bezier(0.2, 0.7, 0.2, 1);
}
.orb { display: block; width: 100%; height: 100%; }
/* On a light page the orb's glow is white on white; a soft shadow lifts it instead. */
:root[data-theme="light"] .orb { filter: drop-shadow(0 10px 18px rgba(0, 0, 0, 0.16)) drop-shadow(0 2px 4px rgba(0, 0, 0, 0.12)); }
.captions { width: 100%; max-width: 46ch; height: var(--cap-area); flex: none; display: flex; flex-direction: column; align-items: center; gap: 10px; transition: height 0.5s cubic-bezier(0.2, 0.7, 0.2, 1); }
/* The agent's line. A short one sits in the middle of the window; a longer one
   moves through it with the speech. Soft edges show there is more above or below. */
.caption-window {
  --fade: calc(var(--cap-lh) * 0.9);
  width: 100%; height: calc(var(--cap-lines) * var(--cap-lh)); flex: none;
  display: flex; flex-direction: column; justify-content: safe center;
  overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none;
  transition: height 0.5s cubic-bezier(0.2, 0.7, 0.2, 1);
}
.caption-window::-webkit-scrollbar { display: none; }
.caption-window:focus-visible { outline-offset: 6px; }
.caption-window[data-above] { -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 var(--fade)); mask-image: linear-gradient(to bottom, transparent 0, #000 var(--fade)); }
.caption-window[data-below] { -webkit-mask-image: linear-gradient(to top, transparent 0, #000 var(--fade)); mask-image: linear-gradient(to top, transparent 0, #000 var(--fade)); }
.caption-window[data-above][data-below] {
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 var(--fade), #000 calc(100% - var(--fade)), transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 var(--fade), #000 calc(100% - var(--fade)), transparent 100%);
}
.caption { font-size: var(--cap-size); font-weight: 400; line-height: var(--cap-lh); letter-spacing: -0.01em; color: var(--strong); text-wrap: pretty; }
.caption:empty { display: none; }
/* The person's words, newest at the bottom: a longer turn loses its first lines
   off the top instead of pushing the agent's line away. */
.caption-you {
  max-height: calc(var(--you-lines) * var(--you-lh)); overflow: hidden; flex: none;
  display: flex; flex-direction: column; justify-content: flex-end;
  font-family: var(--font-text); font-size: 16px; line-height: var(--you-lh); color: var(--gray); max-width: 46ch;
}
.caption-you[data-clipped] { -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 var(--you-lh)); mask-image: linear-gradient(to bottom, transparent 0, #000 var(--you-lh)); }
.caption-you.final { color: var(--body); }
.talk[data-phase="ended"] .caption, .talk[data-phase="over"] .caption, .talk[data-phase="ready"] .caption { color: var(--gray); }
.fresh { animation: rise 0.4s ease both; }
@keyframes rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/* ---- text: the chat ---- */
.chat-view { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.log {
  flex: 1; min-height: 0; list-style: none; overflow-y: auto; overscroll-behavior: contain;
  display: flex; flex-direction: column; gap: 18px; padding: clamp(18px, 3vw, 30px);
  /* Earlier messages fade out under the bar as they scroll away. */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 18px);
  mask-image: linear-gradient(to bottom, transparent 0, #000 18px);
}
/* An empty chat shows the agent as a small orb until the first line arrives. */
.log:empty { justify-content: center; align-items: center; }
.log:empty::before { content: ""; flex: none; width: 76px; height: 76px; }
/* Mercury: liquid metal reflecting a bright sky over a dark horizon. */
.talk[data-orb="mercury"] .log:empty::before {
  background:
    radial-gradient(ellipse 46% 26% at 36% 27%, rgba(255, 255, 255, 0.95), rgba(255, 255, 255, 0) 100%),
    radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 0) 64%, rgba(255, 255, 255, 0.3) 97%),
    radial-gradient(ellipse 150% 105% at 50% -4%, #dedede 0%, #a2a2a2 36%, #121212 48%, #3a3a3a 53%, #2a2a2a 66%, #444444 84%, #181818 100%);
  background-blend-mode: normal, screen, normal;
}
.msg { display: flex; animation: rise 0.3s ease both; }
.msg .said { font-family: var(--font-text); font-size: 17px; line-height: 1.55; white-space: pre-wrap; overflow-wrap: anywhere; }
.msg.user { justify-content: flex-end; }
.msg.user .said { max-width: min(78%, 680px); padding: 11px 16px; background: var(--wash-strong); border: 1px solid var(--hair-lit); color: var(--paper); }
/* The person's words while they are still speaking, in a voice conversation. */
.msg.user.pending .said { color: var(--gray); border-style: dashed; }
/* The agent: plain text after the brand's square dot. */
.msg.agent { gap: 14px; align-items: flex-start; }
.msg.agent::before { content: ""; flex: none; width: 8px; height: 8px; margin-top: 10px; background: var(--paper); }
.msg.agent .said { max-width: min(86%, 780px); color: var(--strong); }
.msg.agent .said:empty { display: none; }
/* A square cursor while the reply streams in. */
.msg.streaming .said::after { content: ""; display: inline-block; width: 0.5em; height: 1.05em; margin-left: 3px; vertical-align: -0.16em; background: var(--paper); animation: blink 1s steps(1) infinite; }
@keyframes blink { 50% { opacity: 0; } }
.typing .dots { display: inline-flex; gap: 6px; padding-top: 7px; }
.typing .dots i { width: 7px; height: 7px; background: var(--paper); opacity: 0.2; animation: wave 1.2s ease-in-out infinite; }
.typing .dots i:nth-child(2) { animation-delay: 0.15s; }
.typing .dots i:nth-child(3) { animation-delay: 0.3s; }
@keyframes wave { 30% { opacity: 1; transform: translateY(-3px); } 60%, 100% { opacity: 0.2; transform: none; } }

/* ---- the dock: the composer, the start choice and the controls ---- */
.dock { display: flex; flex-direction: column; align-items: stretch; gap: 14px; padding: 4px clamp(18px, 3vw, 28px) clamp(18px, 3vw, 28px); }
.talk[data-view="chat"] .dock { border-top: 1px solid var(--hair); padding-top: clamp(14px, 2vw, 20px); }
.talk[data-view="orb"] .dock > * { width: min(100%, 560px); margin: 0 auto; }

.composer { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px; align-items: end; }
.composer textarea {
  display: block; width: 100%; height: 56px; min-height: 56px; max-height: 176px; resize: none; overflow-y: auto;
  padding: 15px 16px; background: var(--field); border: 1px solid var(--field-line); border-radius: 0;
  color: var(--paper); font-family: var(--font-text); font-size: 17px; line-height: 1.5;
  transition: border-color 0.2s ease, background-color 0.2s ease;
}
.composer textarea::placeholder { color: var(--gray); opacity: 1; }
.composer textarea:focus { outline: none; border-color: var(--paper); background: var(--field-focus); box-shadow: 0 0 0 1px var(--paper); }
.composer textarea:disabled { opacity: 0.6; }
.send {
  width: 56px; height: 56px; display: grid; place-items: center; flex: none;
  border: 1px solid var(--paper); border-radius: 0; background: var(--paper); color: var(--ink);
  transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}
.send svg { width: 22px; height: 22px; }
.send:disabled { background: transparent; color: var(--gray); border-color: var(--hair-lit); cursor: default; }

.choice { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }

.controls { display: flex; justify-content: center; gap: 10px; }
.control {
  flex: 1 1 0; max-width: 132px; min-height: 76px; padding: 10px 12px;
  display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: 7px;
  border: 1px solid var(--hair-lit); border-radius: 0; background: transparent; color: var(--paper);
  font-size: 15px; font-weight: 600;
  transition: border-color 0.2s ease, background-color 0.2s ease, color 0.2s ease;
}
.control svg { width: 22px; height: 22px; }
@media (hover: hover) { .control:hover { border-color: var(--paper); } }
.control:disabled { opacity: 0.55; cursor: default; }
.control[aria-pressed="true"] { background: var(--paper); border-color: var(--paper); color: var(--ink); }
[data-mute] svg + svg, [data-mute][aria-pressed="true"] svg:first-of-type { display: none; }
[data-mute][aria-pressed="true"] svg + svg { display: block; }

.btn.small { min-height: 40px; padding: 8px 14px; gap: 8px; font-size: 15px; }
.btn.small svg { width: 16px; height: 16px; }

/* Local development only: the fake has no speech recognition, so a person types
   what they would say. */
.simulated { border: 1px dashed var(--hair-lit); padding: 12px; display: flex; flex-direction: column; gap: 8px; }
.simulated textarea { height: 48px; min-height: 48px; padding: 11px 14px; font-size: 16px; }
.simulated .send { width: 48px; height: 48px; }

.ended { display: flex; flex-direction: column; gap: 20px; }
/* After a conversation: "Conversation ended", then the summary. A step in a done
   list shows a loading circle until it is done, then a tick in a green square; the
   summary's pending card uses one (pages.tsx, PendingCard). */
.ended-progress { display: flex; flex-direction: column; gap: 14px; text-align: left; }
.ended-title { font-size: 22px; font-weight: 600; line-height: 1.25; letter-spacing: -0.01em; color: var(--strong); }
.ended-title:focus { outline: none; }
.done-list { list-style: none; border-top: 1px solid var(--hair-lit); }
.done-list li { display: flex; align-items: center; gap: 14px; padding: 14px 0; border-bottom: 1px solid var(--hair); font-size: 17px; text-align: left; overflow-wrap: anywhere; color: var(--body); transition: color 0.3s ease; }
.done-list li[data-done] { color: var(--strong); }
.step-mark {
  position: relative; flex: none; width: 16px; height: 16px;
  border: 2px solid var(--hair-lit); border-top-color: var(--paper); border-radius: 50%;
  animation: step-spin 0.8s linear infinite;
}
.done-list li[data-done] .step-mark { border-color: var(--ok); border-radius: 0; background: var(--ok); animation: step-tick 0.36s cubic-bezier(0.16, 1, 0.3, 1); }
.done-list li[data-done] .step-mark::after {
  content: ""; position: absolute; left: 3.5px; top: 0; width: 5px; height: 9px;
  border: solid #ffffff; border-width: 0 2px 2px 0; transform: rotate(45deg);
}
.done-list li[data-state="stopped"] .step-mark { animation: none; border-color: var(--gray); border-radius: 0; }
@keyframes step-spin { to { transform: rotate(360deg); } }
@keyframes step-tick { from { transform: scale(0.5); opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .step-mark, .done-list li[data-done] .step-mark { animation: none; }
}

/* ---- the panels the agent opens: the blueprint, and a call or contact request ---- */
/* A panel is a card in the chat log (li.panel-item), or sits in the sheet beside the
   orb. data-sheet on #talk says the sheet is open. Cards size their insides to
   their own width, so one card works in the chat and in the narrower sheet. */
.msg.panel-item { display: block; padding-left: 22px; }
.msg.panel-item:empty { display: none; }
.sheet { width: 100%; display: flex; flex-direction: column; gap: 16px; text-align: left; }
.talk[data-sheet] .orb-view { display: grid; grid-template-columns: minmax(0, clamp(260px, 32%, 360px)) minmax(0, 1fr); align-items: start; justify-content: stretch; column-gap: clamp(20px, 3vw, 36px); }
/* The orb and its captions stay in sight beside a long panel, and so do Mute, Type
   and End. Beside a panel the agent's words matter more than the orb: the orb
   shrinks, and the agent's line takes the rest of the column's height (100cqh is
   the view's height), so a long line reads in full rather than three lines at a
   time. The window grows with the line, so the person's words stay under it. */
.talk[data-sheet] { --cap-size: 18px; }
.talk[data-sheet] .orb-main { padding-top: clamp(8px, 2vw, 24px); position: sticky; top: 0; height: 100cqh; }
.talk[data-sheet] .orb-frame { width: clamp(64px, 26cqh, 150px); }
.talk[data-sheet] .captions { flex: 1; min-height: 0; height: auto; }
.talk[data-sheet] .caption-window { flex: 0 1 auto; height: auto; min-height: 0; }
@container (max-height: 320px) {
  .talk[data-sheet] .orb-main { gap: 10px; padding-top: 4px; }
  .talk[data-sheet] .orb-frame { width: 52px; }
}
.talk[data-sheet][data-view="orb"][data-phase="live"] .dock {
  position: sticky; bottom: 0; z-index: 1; padding-top: 14px;
  background: var(--stage); border-top: 1px solid var(--hair);
}
/* A field that takes focus scrolls clear of the controls. */
html:has(.talk[data-sheet][data-view="orb"][data-phase="live"]) { scroll-padding-bottom: 150px; }
.sheet > .panel-card { animation: rise 0.3s ease both; }

.panel-card {
  container-type: inline-size;
  display: flex; flex-direction: column; gap: 18px;
  border: 1px solid var(--hair-lit); background: var(--raised); padding: clamp(16px, 2.4vw, 26px);
  text-align: left; transition: border-color 0.3s ease;
}
.panel-card:focus { outline: none; border-color: var(--paper); }
.panel-card[data-state="sent"] { border-color: var(--ok-line); }
.panel-card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.panel-title { font-size: 20px; font-weight: 600; line-height: 1.25; letter-spacing: -0.01em; }
.panel-tag { flex: none; font-size: 11px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink); background: var(--paper); padding: 3px 8px; }
.panel-card .label, .panel-card .field > label {
  font-size: 12px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: var(--gray);
}
.panel-card fieldset { border: 0; padding: 0; margin: 0; min-width: 0; }
.panel-card legend { padding: 0; margin-bottom: 12px; }
.panel-card .field input, .panel-card .field textarea {
  width: 100%; min-height: 48px; padding: 11px 14px;
  background: var(--field); border: 1px solid var(--field-line); border-radius: 0;
  color: var(--paper); font-family: var(--font-text); font-size: 16px; line-height: 1.5; resize: vertical;
  transition: border-color 0.2s ease, background 0.2s ease;
}
.panel-card .field textarea { min-height: 72px; max-height: 200px; }
.panel-card .field input:focus, .panel-card .field textarea:focus { outline: none; border-color: var(--paper); background: var(--field-focus); box-shadow: 0 0 0 1px var(--paper); }
.panel-card .field input[aria-invalid="true"] { border-color: var(--error); }
.request-form { display: flex; flex-direction: column; gap: 20px; }
.panel-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.panel-actions .btn { min-height: 48px; padding: 11px 22px; font-size: 16px; }
.panel-card .alert { font-size: 15px; }

/* The blueprint: the brief on a faint drawing grid. */
.blueprint {
  background-color: var(--raised);
  background-image: linear-gradient(var(--grid-line) 1px, transparent 1px), linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 24px 24px; background-position: -1px -1px;
}
.map { border-top: 1px solid var(--hair-lit); }
.map > div { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 16px; padding: 12px 0; border-bottom: 1px solid var(--hair); transition: background-color 0.4s ease; }
.map dt { font-size: 12px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--gray); padding-top: 3px; }
.map dd { font-family: var(--font-text); font-size: 16px; line-height: 1.5; color: var(--strong); overflow-wrap: anywhere; white-space: pre-line; }
.map dd ul { list-style: none; display: flex; flex-direction: column; gap: 6px; white-space: normal; }
.map dd li { display: flex; gap: 10px; }
.map dd li::before { content: ""; flex: none; width: 6px; height: 6px; margin-top: 9px; background: var(--paper); }
/* What the agent changed in its last correction. */
.map > div[data-changed] { background: var(--wash); box-shadow: inset 2px 0 0 var(--paper); padding-left: 12px; padding-right: 8px; }
@container (max-width: 520px) {
  .map > div { grid-template-columns: minmax(0, 1fr); gap: 4px; }
  .map dt { padding-top: 0; }
}

/* Preferred times: a row per day, its slots as chips (availability.ts). A chosen
   chip fills solid. Two columns of days where the card is wide. */
.label-row { display: flex; width: 100%; justify-content: space-between; align-items: baseline; gap: 12px; }
.count { font-family: var(--font-text); font-size: 14px; color: var(--gray); font-variant-numeric: tabular-nums; }
.slot-days { display: grid; grid-template-columns: minmax(0, 1fr); column-gap: 28px; border-top: 1px solid var(--hair-lit); }
.slot-day { display: grid; grid-template-columns: 84px minmax(0, 1fr); align-items: center; gap: 10px; padding: 7px 0; border-bottom: 1px solid var(--hair); }
.slot-date { font-family: var(--font-text); font-size: 15px; color: var(--paper); white-space: nowrap; }
.slot-date span { color: var(--gray); }
.slot-chips { display: grid; grid-template-columns: repeat(auto-fill, minmax(40px, 1fr)); gap: 5px; }
.slot {
  min-height: 40px; padding: 0 4px; display: grid; place-items: center;
  border: 1px solid var(--hair-lit); border-radius: 0; background: var(--wash); color: var(--paper);
  font-family: var(--font-text); font-size: 14px; font-variant-numeric: tabular-nums;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.slot[aria-pressed="true"] { background: var(--paper); border-color: var(--paper); color: var(--ink); font-weight: 600; }
.slot[aria-disabled="true"] { opacity: 0.3; cursor: not-allowed; }
@media (hover: hover) { .slot:not([aria-disabled="true"]):hover { border-color: var(--paper); } }
.times .field-error { margin-top: 10px; }
@container (min-width: 640px) {
  .slot-days { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* A phone: a day's four slots still fit on one row. */
@container (max-width: 400px) {
  .slot-day { grid-template-columns: 76px minmax(0, 1fr); gap: 8px; }
  .slot-date { font-size: 14px; }
  .slot { padding: 0 2px; font-size: 13px; }
}

/* How to reach the person: two square radio options. */
.options { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.option {
  display: flex; align-items: flex-start; gap: 12px; min-width: 0; padding: 13px 14px;
  border: 1px solid var(--hair-lit); cursor: pointer; transition: border-color 0.2s ease, background-color 0.2s ease;
}
.option:has(input:checked) { border-color: var(--paper); background: var(--wash); }
.option input {
  appearance: none; flex: none; width: 18px; height: 18px; margin: 3px 0 0; border: 1px solid var(--gray); border-radius: 0; background: transparent;
}
.option input:checked { border-color: var(--paper); background: var(--paper); box-shadow: inset 0 0 0 4px var(--ink); }
.option input:focus-visible { outline: 2px solid var(--paper); outline-offset: 3px; }
.option-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; font-size: 16px; font-weight: 600; }
.option-detail { font-family: var(--font-text); font-size: 14px; font-weight: 400; color: var(--gray); overflow-wrap: anywhere; }
.channel [data-phone-field] { margin-top: 14px; }
.summary-block { display: flex; flex-direction: column; gap: 8px; padding-left: 14px; border-left: 1px solid var(--hair-lit); }
.summary-block p { font-family: var(--font-text); font-size: 16px; line-height: 1.5; color: var(--strong); overflow-wrap: anywhere; }
@container (max-width: 520px) {
  .options { grid-template-columns: minmax(0, 1fr); }
}

/* A sent request. */
.request-done { display: flex; flex-direction: column; gap: 14px; }
.request-done:focus { outline: none; }
.done-state { display: flex; align-items: center; gap: 12px; font-size: 18px; font-weight: 600; }
.done-state::before { content: ""; flex: none; width: 12px; height: 12px; background: var(--ok); }
.done-times { list-style: none; border-top: 1px solid var(--hair-lit); }
.done-times li { padding: 11px 0; border-bottom: 1px solid var(--hair); font-family: var(--font-text); font-size: 16px; }
.done-channel { font-family: var(--font-text); font-size: 16px; color: var(--strong); overflow-wrap: anywhere; }

@media (prefers-reduced-motion: reduce) {
  .sheet > .panel-card { animation: none; }
  .panel-card, .map > div, .slot, .option { transition: none; }
}

@media (prefers-reduced-motion: reduce) {
  .fresh, .msg, .log:empty::before { animation: none; }
  .orb-frame, .captions, .caption-window, .sw::before { transition: none; }
  .status::before { animation: none !important; }
  .typing .dots i { animation: none; opacity: 0.7; }
  .msg.streaming .said::after { animation: none; }
}

/* ---------- the summary (P19) ---------- */
/* After the last conversation: the brief, the request and the conversation. */
.summary { max-width: 1180px; margin: 0 auto; display: flex; flex-direction: column; gap: clamp(16px, 2.6svh, 30px); }
.summary .meta-row a { color: var(--paper); }
.summary-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 440px); gap: clamp(16px, 2.4vw, 28px); align-items: start; }
.summary-main, .summary-side { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
details.panel-card > summary, .request-more > summary { cursor: pointer; list-style: none; display: flex; justify-content: space-between; align-items: center; gap: 12px; }
details.panel-card > summary::-webkit-details-marker, .request-more > summary::-webkit-details-marker { display: none; }
details.panel-card > summary::after, .request-more > summary::after { content: "+"; font-weight: 400; color: var(--gray); }
details.panel-card[open] > summary::after, .request-more[open] > summary::after { content: "\2212"; }
.transcript-lines { list-style: none; display: flex; flex-direction: column; gap: 12px; max-height: 60svh; overflow-y: auto; overscroll-behavior: contain; }
.transcript-lines li { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: 12px; font-family: var(--font-text); font-size: 15px; line-height: 1.5; }
.transcript-lines .who { color: var(--gray); font-size: 13px; padding-top: 2px; }
.done-times { list-style: none; display: flex; flex-direction: column; gap: 8px; font-family: var(--font-text); font-size: 16px; }
/* The summary's time chips are checkboxes, so the form works without JavaScript. */
label.slot { position: relative; display: inline-flex; align-items: center; justify-content: center; }
label.slot input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
label.slot:has(input:checked) { background: var(--paper); border-color: var(--paper); color: var(--ink); font-weight: 600; }
label.slot:has(input:focus-visible) { outline: 2px solid var(--paper); outline-offset: 2px; }
@media (max-width: 900px) {
  .summary-grid { grid-template-columns: minmax(0, 1fr); }
  .transcript-lines li { grid-template-columns: minmax(0, 1fr); gap: 2px; }
}

/* A very short window lets the page scroll, so the stage keeps a usable height. */
@media (max-height: 560px) {
  body:has(main > .talk) { height: auto; min-height: 100svh; overflow: visible; }
  .stage { min-height: 460px; }
}

/* ---------- narrow screens ---------- */
@media (max-width: 1000px) {
  .gate { grid-template-columns: minmax(0, 1fr); grid-template-areas: "intro" "panel"; }
  .gate .panel { max-width: 620px; }
}
/* With a panel open on a narrow screen, the orb and the agent's line become a strip
   pinned to the top of the stage, so the person can read the panel and still
   follow what the agent says. */
@media (max-width: 760px) {
  .talk[data-sheet] { --cap-size: 16px; --you-lh: 22px; }
  .talk[data-sheet][data-phase] .orb-main { --cap-lines: 2; --you-lines: 1; }
  .talk[data-sheet] .orb-view { display: flex; flex-direction: column; align-items: stretch; justify-content: flex-start; padding-top: 0; }
  .talk[data-sheet] .orb-main {
    position: sticky; top: 0; z-index: 2; flex-direction: row; align-items: center; gap: 14px; height: auto;
    margin: 0 calc(-1 * clamp(18px, 4vw, 48px)); padding: 10px clamp(18px, 4vw, 48px) 12px; width: auto;
    background: var(--stage); border-bottom: 1px solid var(--hair);
  }
  .talk[data-sheet] .orb-frame { width: 52px; }
  .talk[data-sheet] .captions { align-items: stretch; text-align: left; max-width: none; flex: 1; min-width: 0; height: auto; gap: 4px; }
  .talk[data-sheet] .caption-window { flex: none; height: calc(var(--cap-lines) * var(--cap-lh)); }
  .talk[data-sheet] .caption-you { font-size: 14px; }
}
@media (max-width: 640px) {
  body { font-size: 17px; }
  .top { padding-top: 18px; padding-bottom: 18px; }
  .top-meta .hide-sm { display: none; }
  .actions .btn { width: 100%; }
  .talk { gap: 22px; }
  .talk-head { gap: 8px; }
  .stage-note { margin-top: -10px; }
  .choice { grid-template-columns: minmax(0, 1fr); }
  .stage-bar { min-height: 56px; }
  .msg.user .said { max-width: 86%; }
  .msg.agent .said { max-width: 100%; }
  .msg.agent { gap: 12px; }
  .log { gap: 16px; }
  .msg.panel-item { padding-left: 0; }
  .panel-card { padding: 16px 14px; }
  .panel-actions .btn { flex: 1 1 auto; }
}
