/* Wren design system.
   Two environments, one token layer:
     kiosk   - waiting-room tablet. Calm, generous, large touch targets.
     portal  - clinician workstation. Dense, information-first, scannable.

   Conventions used throughout, so the system stays legible:
     Radius   panels 14px, controls 10px, pills 999px. No other values.
     Colour   a neutral grey ramp, locked to one dark theme. The accent is
              brightness, not hue. Red and amber appear only for real clinical
              state (red flags, triage) and never for decoration.
     Motion   restrained by choice. This is read by people in pain and by
              clinicians between patients; nothing moves without a reason.
     Type     Geist, a free neo-grotesque in the Akzidenz line, self-hosted as
              one variable file per family. Self-hosted rather than CDN-linked
              because clinic hardware is often offline. */

/* ------------------------------------------------------------------ type */
/* Geist Sans and Geist Mono, SIL Open Font License 1.1 (Vercel).
   One variable file covers every weight the system uses, so the whole type
   ramp costs two requests and about 115KB. */
@font-face {
  font-family: "Geist";
  src: url("/fonts/Geist-Variable.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Geist Mono";
  src: url("/fonts/GeistMono-Variable.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* ---------------------------------------------------------------- tokens */
:root {
  /* One locked theme. The palette is a true neutral grey ramp: no hue at all,
     so nothing shifts warm or cool between surfaces. */
  color-scheme: dark;

  --bg: #242424;
  --surface: #2f2f2f;
  --surface-2: #353535;
  --surface-3: #424242;

  --ink: #ececec;
  --ink-2: #b4b4b4;
  --ink-3: #9d9d9d;

  /* --line is a decorative hairline. --line-2 draws the boundary of a
     control (inputs, secondary buttons, chips) and therefore has to clear
     WCAG 3:1 against the surface behind it, so it sits noticeably lighter. */
  --line: #3d3d3d;
  --line-2: #7e7e7e;

  /* Monochrome accent: a primary action is the brightest thing on the screen,
     not the most colourful. Colour is reserved for clinical meaning below. */
  --accent: #ececec;
  --accent-hover: #ffffff;
  --accent-soft: #3a3a3a;
  --accent-ink: #242424;

  --clinic: #1c1c1c;
  --clinic-ink: #ececec;

  /* Identity only, and only on the header mark. Deliberately petrol: it sits
     nowhere near the red/amber/green that carry clinical meaning, so it can
     never be misread as state. Nothing else on the page uses it. */
  --brand: #5fb0c9;

  /* Clinical state only. These stay chromatic on purpose: a red flag or an
     urgent triage level must never be a shade of grey. */
  --alert: #e8836f;
  --alert-soft: #3a2622;
  --caution: #dfb877;
  --caution-soft: #383025;
  --ok: #7fc9a0;

  --focus: #ececec;

  --shadow-1: 0 1px 2px rgba(0, 0, 0, .3);
  --shadow-2: 0 2px 4px rgba(0, 0, 0, .28), 0 8px 20px rgba(0, 0, 0, .32);
  --shadow-3: 0 8px 16px rgba(0, 0, 0, .35), 0 24px 56px rgba(0, 0, 0, .45);

  --r-panel: 14px;
  --r-control: 10px;
  --r-pill: 999px;

  --s1: .25rem;  --s2: .5rem;   --s3: .75rem;  --s4: 1rem;
  --s5: 1.25rem; --s6: 1.5rem;  --s7: 2rem;    --s8: 2.5rem;
  --s9: 3rem;    --s10: 4rem;

  --ease: cubic-bezier(.16, 1, .3, 1);
  --fast: 120ms;
  --slow: 260ms;

  --sans: "Geist", system-ui, -apple-system, "Helvetica Neue", Helvetica, Arial, sans-serif;
  --mono: "Geist Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  font-family: var(--sans);
}

/* ------------------------------------------------------------- resets */
* { box-sizing: border-box; }

html, body {
  margin: 0;
  min-height: 100%;
}

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

button, input, textarea, select { font: inherit; color: inherit; }
h1, h2, h3, p { margin: 0; }
svg { display: block; }

/* The UA rule for [hidden] is display:none, and ANY author display rule beats
   it. Every panel toggled with .hidden in JS needs this or it never hides. */
[hidden] { display: none !important; }

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: 4px;
}
:focus:not(:focus-visible) { outline: none; }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Icons inherit colour and scale with their label's font-size. */
.icon {
  width: 1.15em;
  height: 1.15em;
  flex: none;
  fill: currentColor;
  pointer-events: none;
}
.icon-lg { width: 1.5em; height: 1.5em; }

/* --------------------------------------------------------- clinic bar */
/* Sticky, quiet, sentence case. A full-width slab of colour in wide-tracked
   caps reads as an old hospital intranet; the header should recede and let
   the chart lead. Colour here is limited to the brand mark: a coloured band
   would be the largest coloured thing on screen while meaning nothing, and
   colour in this app means triage. */
.clinic-bar {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--s4);
  height: 3.5rem;
  padding: 0 var(--s5);
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  color: var(--ink);
  font-size: .9rem;
  font-weight: 560;
  letter-spacing: -.005em;
}

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .clinic-bar {
    background: color-mix(in srgb, var(--surface) 78%, transparent);
    backdrop-filter: blur(14px) saturate(150%);
    -webkit-backdrop-filter: blur(14px) saturate(150%);
  }
}

.clinic-bar > span { display: inline-flex; align-items: center; gap: var(--s2); min-width: 0; }
.clinic-bar > span:first-child .icon { color: var(--brand); }

/* The right slot is context, not a second title, so it sits as a quiet chip. */
.clinic-bar > span:last-child {
  color: var(--ink-2);
  font-size: .78rem;
  font-weight: 500;
  padding: .28rem .7rem;
  border-radius: var(--r-pill);
  background: var(--surface-3);
  border: 1px solid var(--line);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.clinic-bar > span:last-child .icon { color: var(--ink-3); }

/* ============================================================== KIOSK */
/* The kiosk runs light, the console stays dark, and each page is internally
   consistent so neither one flips theme mid-scroll. This is not a preference:
   a waiting room is daylit, often by a window, and a dark tablet in glare is
   hardest on exactly the older patients who need it most. The console is the
   opposite case, read for hours in a consulting room.

   Same neutral ramp, inverted. Every pair below clears WCAG AA. */
body.kiosk {
  color-scheme: light;

  --bg: #f7f7f7;
  --surface: #ffffff;
  --surface-2: #fafafa;
  --surface-3: #ececec;

  --ink: #242424;
  --ink-2: #5f5f5f;
  --ink-3: #6b6b6b;

  --line: #e4e4e4;
  --line-2: #8f8f8f;

  --accent: #242424;
  --accent-hover: #000000;
  --accent-soft: #ececec;
  --accent-ink: #ffffff;

  --brand: #10566b;

  --alert: #8c3418;
  --alert-soft: #fbeae4;
  --caution: #6f4a0c;
  --caution-soft: #fdf3e0;
  --ok: #1b5c3f;

  --focus: #242424;

  --shadow-1: 0 1px 2px rgba(36, 36, 36, .06);
  --shadow-2: 0 2px 4px rgba(36, 36, 36, .05), 0 8px 20px rgba(36, 36, 36, .07);
  --shadow-3: 0 8px 16px rgba(36, 36, 36, .08), 0 24px 56px rgba(36, 36, 36, .12);
}

body.kiosk {
  /* A single soft wash lifting the top of the page away from the header.
     There used to be a 48px vertical rule here, meant as squared clinic paper.
     On the old pale palette the two greys were near-identical so it never
     showed; on a dark ground it read as a rendering artefact, not texture. */
  background: linear-gradient(180deg, var(--surface-2) 0, var(--bg) 22rem);
  background-attachment: fixed;
  min-height: 100vh;
}

.kiosk-shell {
  min-height: calc(100vh - 3.5rem);
  display: flex;
  flex-direction: column;
  max-width: 44rem;
  margin: 0 auto;
  padding: var(--s7) var(--s5) var(--s6);
}

.checkin-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  box-shadow: var(--shadow-2);
  padding: var(--s8) var(--s7) var(--s7);
  width: 100%;
  position: relative;
  overflow: hidden;
}
/* A hairline of light along the top edge, the way a raised surface catches
   it. In a monochrome system this is the whole vocabulary of elevation. */
.checkin-card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--line-2) 20%, var(--line-2) 80%, transparent);
}

/* A quiet wayfinding pill, not a shouted section mark. */
.kiosk-mark {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  font-size: .78rem;
  font-weight: 550;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: var(--r-pill);
  padding: .3rem .75rem;
  margin-bottom: var(--s6);
}

.name-badge {
  display: block;
  margin: 0 0 var(--s4);
  color: var(--accent);
  font-size: .95rem;
  font-weight: 600;
  letter-spacing: .01em;
}

.kiosk-hero { text-align: center; }

.wren-hero {
  border-radius: 50%;
  width: 108px;
  height: 108px;
  object-fit: cover;
  margin: 0 auto var(--s5);
  display: block;
  background: var(--accent-soft);
  box-shadow: 0 0 0 1px var(--line), var(--shadow-2);
}

.kiosk-hero h1 {
  font-size: clamp(1.9rem, 5vw, 2.5rem);
  line-height: 1.1;
  letter-spacing: -.02em;
  font-weight: 650;
  margin-bottom: var(--s2);
}

.kiosk-hero .kiosk-lead {
  color: var(--ink-2);
  font-size: 1.06rem;
  line-height: 1.65;
  max-width: 34rem;
  margin: 0 auto;
  text-wrap: pretty;
}

.kiosk-actions {
  margin-top: var(--s8);
  display: flex;
  justify-content: center;
}

.kiosk-foot {
  margin-top: auto;
  padding-top: var(--s7);
  display: flex;
  align-items: flex-start;
  gap: var(--s3);
  color: var(--ink-2);
  font-size: .9rem;
  line-height: 1.6;
  max-width: 40rem;
}
.kiosk-foot .icon { color: var(--alert); margin-top: .15em; }

/* --------------------------------------------------------- controls */
.btn-primary,
.btn-speak {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  border-radius: var(--r-control);
  padding: .7rem 1.15rem;
  min-height: 44px;
  font-size: .95rem;
  font-weight: 550;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--fast) var(--ease),
              border-color var(--fast) var(--ease),
              transform var(--fast) var(--ease),
              box-shadow var(--fast) var(--ease);
}

.btn-primary {
  background: var(--accent);
  color: var(--accent-ink);
  border: 1px solid var(--accent);
  box-shadow: var(--shadow-1);
}
.btn-primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn-primary:active { transform: translateY(1px); box-shadow: none; }

.btn-speak {
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--line-2);
}
.btn-speak:hover { background: var(--surface-3); border-color: var(--accent); color: var(--accent); }
.btn-speak:active { transform: translateY(1px); }

@keyframes pulse { 50% { opacity: .35; } }

button[disabled], .btn-primary[disabled], .btn-speak[disabled] {
  opacity: .5;
  cursor: not-allowed;
  transform: none;
}

.kiosk .btn-primary { padding: .85rem 1.6rem; font-size: 1.02rem; min-height: 52px; }

/* ------------------------------------------------------ intake chat */
.intake-shell { max-width: 46rem; }

/* An identity row, not a profile card. Three stacked lines of text beside an
   avatar is a forum post header; the name is the only thing that needs weight,
   the role sits under it quietly, and the safety line becomes a badge so it is
   read rather than skimmed past as a third line of grey. */
.intake-head {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding-bottom: var(--s4);
  margin-bottom: var(--s5);
  border-bottom: 1px solid var(--line);
}
.staff-id { min-width: 0; }
.intake-head .wren-chip { width: 40px; height: 40px; }

.wren-chip {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  object-fit: cover;
  flex: none;
  background: var(--accent-soft);
  box-shadow: 0 0 0 1px var(--line);
}

.staff-name { font-weight: 640; font-size: 1rem; letter-spacing: -.015em; line-height: 1.25; }
.staff-role { color: var(--ink-3); font-size: .82rem; font-weight: 450; line-height: 1.3; }

.staff-hint {
  margin-left: auto;
  flex: none;
  display: inline-flex;
  align-items: center;
  padding: .3rem .7rem;
  border-radius: var(--r-pill);
  background: var(--surface-3);
  border: 1px solid var(--line);
  color: var(--ink-2);
  font-size: .76rem;
  font-weight: 500;
  white-space: nowrap;
}

.chat-log {
  display: flex;
  flex-direction: column;
  gap: var(--s4);
  flex: 1;
  padding: var(--s2) 0 var(--s5);
  overflow-y: auto;
  scroll-behavior: smooth;
}

.msg-row {
  display: flex;
  align-items: flex-end;
  gap: var(--s3);
  max-width: 100%;
  animation: rise var(--slow) var(--ease) both;
}
.you-row { justify-content: flex-end; }
.them-row .wren-chip { width: 30px; height: 30px; align-self: flex-end; }

@keyframes rise {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

.bubble {
  max-width: min(34rem, 82%);
  padding: .8rem 1.05rem;
  border-radius: var(--r-panel);
  font-size: 1.02rem;
  line-height: 1.6;
  text-wrap: pretty;
}
.bubble.them {
  background: var(--surface);
  border: 1px solid var(--line);
  border-bottom-left-radius: 4px;
  box-shadow: var(--shadow-1);
}
/* The patient's own words sit on a raised grey, not a bright fill. A pure
   white block shouted louder than anything Wren says back. */
.bubble.you {
  background: var(--surface-3);
  color: var(--ink);
  border: 1px solid var(--line-2);
  border-bottom-right-radius: 4px;
}
.bubble.staff {
  background: var(--alert-soft);
  border: 1px solid color-mix(in srgb, var(--alert) 40%, transparent);
  color: var(--alert);
  font-weight: 550;
  max-width: 100%;
}

/* Thinking state. The pause after someone types something hard to say is the
   worst moment in the whole flow, so it gets a sentence saying what is
   happening, lit by a slow sweep. One indicator, not two. */
.thinking {
  display: inline-flex;
  align-items: center;
  padding: .8rem 1.1rem;
}

/* Fallback first: plain readable text. The gradient sweep is layered on only
   where background-clip:text actually works, so nothing ever goes invisible. */
.shimmer-text {
  font-size: 1.02rem;
  line-height: 1.5;
  color: var(--ink-2);
}
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .shimmer-text {
    background-image: linear-gradient(100deg,
      var(--ink-3) 28%,
      var(--ink) 48%,
      var(--ink-3) 68%);
    background-size: 220% 100%;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    -webkit-text-fill-color: transparent;
    animation: shimmer-text 1.9s linear infinite;
  }
}
@keyframes shimmer-text {
  from { background-position: 170% 0; }
  to   { background-position: -70% 0; }
}

/* ------------------------------------------------------ photo preview */
/* Seeing the photo you just sent is the difference between "did that work?"
   and knowing it did. The thumbnail is the message, so the bubble is mostly
   image with the caption tucked under it. */
.photo-bubble {
  padding: .4rem;
  display: flex;
  flex-direction: column;
  gap: .4rem;
  max-width: 15rem;
}
.chat-photo {
  display: block;
  width: 100%;
  max-height: 13rem;
  object-fit: cover;
  border-radius: 10px;
  background: var(--surface-3);
}
.photo-caption { font-size: .82rem; color: var(--ink-2); padding: 0 .25rem .15rem; }

/* -------------------------------------------------------------- voice */
/* A listening indicator. It deliberately does NOT open its own microphone:
   an amplitude meter needs a second getUserMedia capture alongside
   SpeechRecognition, and two concurrent captures make the recognition session
   abort on many setups. Losing dictation to animate a circle is a bad trade,
   so the orb breathes on its own. Monochrome, so it reads the same on the
   light kiosk and the dark console. */
.voice-panel {
  display: flex;
  align-items: center;
  gap: var(--s4);
  padding: var(--s2) var(--s2) var(--s4);
  margin-bottom: var(--s2);
  border-bottom: 1px solid var(--line);
  animation: rise var(--slow) var(--ease) both;
}

.voice-orb {
  position: relative;
  width: 56px;
  height: 56px;
  flex: none;
  border-radius: 50%;
  overflow: hidden;
  isolation: isolate;
  background: var(--surface-3);
  box-shadow: 0 0 0 1px var(--line), var(--shadow-2);
  animation: orb-breathe 2.6s var(--ease) infinite;
}
@keyframes orb-breathe {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.06); }
}

/* Two counter-rotating gradients, blurred into each other. The blur is what
   makes it read as fluid rather than as a spinning wheel. */
.voice-orb::before,
.voice-orb::after {
  content: "";
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
}
.voice-orb::before {
  inset: -35%;
  background: conic-gradient(from 0deg, #000, #fff, #6a6a6a, #111, #fff, #000);
  filter: blur(9px);
  opacity: .85;
  animation: orb-drift-a 7s linear infinite;
}
.voice-orb::after {
  inset: -20%;
  background:
    radial-gradient(circle at 62% 34%, rgba(255, 255, 255, .95), transparent 52%),
    conic-gradient(from 210deg, #fff, #2a2a2a, #d9d9d9, #fff);
  filter: blur(11px);
  opacity: .55;
  animation: orb-drift-b 11s linear infinite reverse;
}

@keyframes orb-drift-a { to { transform: rotate(360deg); } }
@keyframes orb-drift-b { to { transform: rotate(360deg) scale(1.08); } }

.voice-label { font-size: .92rem; color: var(--ink-2); line-height: 1.5; }
.voice-label strong { display: block; color: var(--ink); font-weight: 600; }

/* A failed attempt keeps the panel and explains itself, rather than vanishing
   and leaving a message somewhere else on the page. */
.voice-panel.is-error { border-bottom-color: color-mix(in srgb, var(--alert) 45%, transparent); }
.voice-panel.is-error .voice-label strong { color: var(--alert); }
.voice-panel.is-error .voice-orb { animation: none; opacity: .35; }

@media (prefers-reduced-motion: reduce) {
  .voice-orb { animation: none; transform: none; }
  .voice-orb::before,
  .voice-orb::after { animation: none; }
}

/* -------------------------------------------------- structured prompts */
.prompt-host {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  padding: var(--s5);
  margin-bottom: var(--s4);
  box-shadow: var(--shadow-1);
  animation: rise var(--slow) var(--ease) both;
}
.prompt-q { font-weight: 600; margin-bottom: var(--s4); font-size: 1.02rem; line-height: 1.5; }
.prompt-row { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; }
.prompt-row:has(.body-map) { width: 100%; justify-content: center; }

.chip-btn {
  background: var(--surface-2);
  border: 1px solid var(--line-2);
  color: var(--ink);
  border-radius: var(--r-pill);
  padding: .6rem 1.05rem;
  min-height: 44px;
  cursor: pointer;
  font-size: .96rem;
  transition: background var(--fast) var(--ease), border-color var(--fast) var(--ease), transform var(--fast) var(--ease);
}
.chip-btn:hover { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
.chip-btn:active { transform: translateY(1px); }

.prompt-input {
  background: var(--surface);
  border: 1px solid var(--line-2);
  border-radius: var(--r-control);
  padding: .65rem .85rem;
  min-height: 44px;
  min-width: 12rem;
  flex: 1;
}
.prompt-input:focus-visible { border-color: var(--accent); }

.body-map {
  display: block;
  width: min(100%, 280px);
  height: auto;
  min-width: 200px;
  margin: 0 auto;
}
.body-silhouette {
  fill: var(--surface-3);
  stroke: none;
  pointer-events: none;
}
.body-silhouette .body-neck,
.body-silhouette .body-arm,
.body-silhouette .body-leg {
  fill: none;
  stroke: var(--surface-3);
  stroke-linecap: round;
}
.body-neck { stroke-width: 16; }
.body-arm { stroke-width: 14; }
.body-leg { stroke-width: 17; }
.body-map-label {
  fill: var(--ink-2);
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .02em;
  pointer-events: none;
}
.body-hot {
  fill: transparent;
  stroke: none;
  cursor: pointer;
  outline: none;
  pointer-events: all;
  transition: fill var(--fast) var(--ease), fill-opacity var(--fast) var(--ease), stroke var(--fast) var(--ease);
}
.body-hot-stroke {
  fill: none;
  stroke: transparent;
  stroke-width: 22;
  stroke-linecap: round;
}
.body-hot:hover,
.body-hot:focus-visible,
.body-hot.is-selected {
  fill: var(--accent);
  fill-opacity: .22;
}
.body-hot:hover .body-hot-stroke,
.body-hot:focus-visible .body-hot-stroke,
.body-hot.is-selected .body-hot-stroke,
.body-hot.body-hot-stroke:hover,
.body-hot.body-hot-stroke:focus-visible,
.body-hot.body-hot-stroke.is-selected {
  fill: none;
  stroke: var(--accent);
  stroke-opacity: .35;
}
.body-hot:focus-visible {
  filter: drop-shadow(0 0 3px var(--accent));
}

@media (max-width: 480px) {
  /* Prevent the figure from forcing a horizontal scroll on narrow tablets. */
  .body-map { min-width: 0; width: min(100%, 240px); }
}

@media (prefers-reduced-motion: reduce) {
  .body-hot { transition: none; }
}

/* ---------------------------------------------------------- composer */
/* Text on top, controls under a hairline. Kept snug on purpose: the field
   claims no height it is not using, so the card does not read as empty. */
.body-map-page { align-items: center; justify-content: center; }
.body-map-demo { max-width: 38rem; }
.body-map-intro {
  color: var(--ink-2);
  line-height: 1.5;
  margin: calc(var(--s4) * -1) 0 var(--s4);
}
.body-map-selection {
  color: var(--ink-2);
  font-size: .9rem;
  line-height: 1.4;
  margin-top: var(--s3);
  min-height: 1.25rem;
  text-align: center;
}
.composer {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  padding: var(--s3);
  box-shadow: var(--shadow-2);
  transition: border-color var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
/* The whole composer takes the focus ring, because the textarea has no border
   of its own to show it on. */
.composer:focus-within {
  border-color: var(--ink-3);
  box-shadow: var(--shadow-3);
}

.composer textarea {
  width: 100%;
  border: none;
  background: none;
  resize: none;
  font-size: 1.02rem;
  line-height: 1.5;
  /* Snug: the field should not reserve height it is not using yet. */
  min-height: 2.1rem;
  max-height: 200px;
  padding: .35rem .25rem .5rem;
}
.composer textarea:focus { outline: none; }
.composer textarea::placeholder { color: var(--ink-3); }

/* A hairline, inset by the composer's own padding, so it separates the text
   from the controls without drawing a hard rule across the whole card. */
.composer-actions {
  display: flex;
  align-items: center;
  gap: var(--s2);
  border-top: 1px solid var(--line);
  padding-top: var(--s2);
}
.composer-actions .send-btn { margin-left: auto; }

/* Round, 44px, icon only. Labels on these read as a toolbar from a decade ago
   and pushed Send off to the far edge of a tablet. */
.icon-btn,
.send-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex: none;
  padding: 0;
  border-radius: var(--r-pill);
  cursor: pointer;
  transition: background var(--fast) var(--ease),
              color var(--fast) var(--ease),
              border-color var(--fast) var(--ease),
              transform var(--fast) var(--ease);
}
.icon-btn .icon,
.send-btn .icon { width: 1.25em; height: 1.25em; }

.icon-btn {
  background: transparent;
  border: 1px solid var(--line-2);
  color: var(--ink-2);
}
.icon-btn:hover { background: var(--surface-3); color: var(--ink); }
.icon-btn:active { transform: scale(.94); }

.icon-btn.is-listening {
  background: var(--alert-soft);
  border-color: var(--alert);
  color: var(--alert);
}
.icon-btn.is-listening .icon { animation: pulse 1.4s var(--ease) infinite; }

.send-btn {
  background: var(--accent);
  color: var(--accent-ink);
  border: 1px solid var(--accent);
}
.send-btn:hover:not([disabled]) { background: var(--accent-hover); border-color: var(--accent-hover); }
.send-btn:active:not([disabled]) { transform: scale(.94); }
/* Nothing to send yet: present but plainly inert, not a greyed-out ghost. */
.send-btn[disabled] {
  background: var(--surface-3);
  border-color: var(--line);
  color: var(--ink-3);
  cursor: default;
  opacity: 1;
  transform: none;
}

#status {
  margin-top: var(--s3);
  color: var(--ink-2);
  font-size: .88rem;
  min-height: 1.2em;
  display: flex;
  align-items: center;
  gap: var(--s2);
}
#status.is-error { color: var(--alert); }

/* ============================================================= PORTAL */
html:has(body.portal) {
  /* Lock the viewport so body is the only scrollport. A flex-column body
     with min-height: 100vh inside a short iframe (teleprompter, laptop)
     reported 100vh, clipped the queue title, and had nothing to scroll. */
  height: 100%;
  overflow: hidden;
}

body.portal {
  display: block;
  background: var(--bg);
  height: 100%;
  overflow-x: hidden;
  overflow-y: auto;
}

.queue-screen,
#patientScreen {
  /* Fill the app frame even while a cached brief is loading; otherwise the
     teleprompter exposes an empty dark lower half beneath the short content. */
  min-height: calc(100vh - 3.5rem);
  box-sizing: border-box;
}

.portal-banner {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--s5);
  flex-wrap: wrap;
  padding: var(--s6) var(--s7);
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
.portal-banner h1 { font-size: 1.6rem; letter-spacing: -.025em; font-weight: 650; }
.portal-banner .sub { color: var(--ink-3); font-size: .84rem; margin-top: .3rem; line-height: 1.5; }
.portal-banner-actions { display: flex; gap: var(--s2); align-items: center; }

.triage-banner {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  margin-top: var(--s3);
  padding: .35rem .8rem;
  border-radius: var(--r-pill);
  background: var(--surface-3);
  border: 1px solid var(--line);
  color: var(--ink-2);
  font-size: .84rem;
  font-weight: 550;
}
.triage-banner.is-urgent {
  background: var(--alert-soft);
  border-color: color-mix(in srgb, var(--alert) 40%, transparent);
  color: var(--alert);
}
.triage-banner.is-soon {
  background: var(--caution-soft);
  border-color: color-mix(in srgb, var(--caution) 40%, transparent);
  color: var(--caution);
}

.portal-grid {
  display: grid;
  grid-template-columns: 16rem minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.15fr);
  gap: 1px;
  background: var(--line);
  flex: 1;
  align-items: start;
}
.portal-rail, .portal-col {
  background: var(--bg);
  padding: var(--s6) var(--s5);
  min-height: 100%;
  min-width: 0;
}
.portal-rail { background: var(--surface-2); }

/* Sentence case with an accent icon reads as a heading. Wide-tracked caps
   read as a filing cabinet, which is the look this console was stuck in. */
.brief-col {
  /* Give the synthesis output a quiet focal wash without turning clinical
     status into decoration or changing the portal's neutral theme. */
  background:
    radial-gradient(circle at 50% 0%, color-mix(in srgb, var(--brand) 5%, transparent), transparent 24rem),
    var(--bg);
}
.portal-grid h2 {
  font-size: .95rem;
  letter-spacing: -.01em;
  color: var(--ink);
  font-weight: 620;
  margin-bottom: var(--s4);
  display: flex;
  align-items: center;
  gap: var(--s2);
}
.portal-grid h2 .icon { color: var(--accent); }
.portal-grid h2:not(:first-child) { margin-top: var(--s7); }

.rail-note { color: var(--ink-3); font-size: .8rem; line-height: 1.5; margin-bottom: var(--s3); }

/* An action that belongs to a section heading rather than the page. */
.btn-inline {
  margin-left: auto;
  padding: .25rem .6rem;
  min-height: 30px;
  font-size: .78rem;
  font-weight: 500;
}
.btn-inline.is-done { border-color: var(--ok); color: var(--ok); }

.appt {
  display: flex;
  flex-direction: column;
  gap: .3rem;
  width: 100%;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-control);
  padding: var(--s3) var(--s4);
  margin-bottom: var(--s2);
  cursor: pointer;
  transition: border-color var(--fast) var(--ease), box-shadow var(--fast) var(--ease), transform var(--fast) var(--ease);
}
.appt:hover { border-color: var(--accent); transform: translateX(2px); }
.appt strong { font-family: var(--mono); font-size: .78rem; color: var(--ink-3); font-weight: 500; }
.appt span { font-weight: 600; font-size: .95rem; }
.appt em { font-style: normal; color: var(--ink-2); font-size: .85rem; line-height: 1.45; }
.appt.selected {
  border-color: var(--accent);
  background: var(--accent-soft);
  box-shadow: inset 3px 0 0 var(--accent);
}
.appt:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

/* Waiting time carries more clinical weight than a check-in timestamp, so it
   is the figure that gets the monospace treatment and sits on the same line. */
.appt-when { display: flex; align-items: baseline; gap: var(--s2); }
.appt-wait { color: var(--ink-2); font-weight: 550; }
.appt-wait.is-long { color: var(--caution); }

/* --------------------------------------------------------- chart data */
.chart-block { display: flex; flex-direction: column; gap: var(--s4); }

.chart-row {
  display: grid;
  grid-template-columns: 8.5rem minmax(0, 1fr);
  gap: var(--s4);
  align-items: start;
  padding-bottom: var(--s4);
  border-bottom: 1px solid var(--line);
  font-size: .92rem;
  line-height: 1.55;
}
.chart-row:last-child { border-bottom: none; padding-bottom: 0; }

/* Field labels stay small and quiet, but lose the wide caps tracking that
   made every row look like a form from 1998. */
.label {
  color: var(--ink-3);
  font-size: .78rem;
  letter-spacing: 0;
  font-weight: 550;
  padding-top: .2rem;
}

.chips { display: flex; flex-wrap: wrap; gap: var(--s2); }

.chip {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  background: var(--surface-3);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  padding: .22rem .65rem;
  font-size: .82rem;
  color: var(--ink-2);
}
.chip.private {
  background: var(--alert-soft);
  border-color: color-mix(in srgb, var(--alert) 35%, transparent);
  color: var(--alert);
  font-weight: 550;
}
.kind-chip { font-style: normal; color: var(--ink-2); font-size: .72rem; margin-left: .3rem; }

.look { color: var(--ink-2); font-size: .88rem; line-height: 1.6; }
.look-block { margin-top: var(--s3); }
.look-block strong { font-size: .82rem; font-weight: 600; letter-spacing: -.005em; color: var(--ink-2); }

.evidence-list {
  list-style: none;
  padding: 0;
  margin: var(--s2) 0 0;
  display: flex;
  flex-direction: column;
  gap: .3rem;
}
.evidence-list li {
  font-size: .88rem;
  color: var(--ink-2);
  padding-left: var(--s4);
  position: relative;
  line-height: 1.5;
}
.evidence-list li::before {
  content: "";
  position: absolute;
  left: 0; top: .55em;
  width: 6px; height: 1px;
  background: var(--line-2);
}

.prior-fold {
  margin-top: var(--s5);
  border: 1px solid var(--line);
  border-radius: var(--r-control);
  background: var(--surface);
  padding: var(--s3) var(--s4);
}
.prior-fold summary {
  cursor: pointer;
  font-size: .86rem;
  font-weight: 550;
  color: var(--accent);
  list-style: none;
}
.prior-fold summary::-webkit-details-marker { display: none; }
.prior-fold[open] summary { margin-bottom: var(--s4); }
.prior-fold label {
  display: block;
  font-size: .74rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
  font-weight: 600;
  margin-bottom: var(--s1);
}
.prior-fold input, .prior-fold textarea {
  width: 100%;
  background: var(--surface-2);
  border: 1px solid var(--line-2);
  border-radius: var(--r-control);
  padding: .55rem .7rem;
  margin-bottom: var(--s3);
  font-size: .9rem;
  resize: vertical;
}

/* ------------------------------------------------------- exact chat */
.gp-chat { display: flex; flex-direction: column; gap: var(--s3); }
.gp-turn { display: flex; flex-direction: column; gap: .25rem; }
.gp-turn-patient { align-items: flex-start; }
.gp-turn-wren { align-items: flex-start; opacity: .82; }
.turn-label {
  font-size: .68rem;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--ink-3);
  font-weight: 600;
}
.gp-chat .bubble { font-size: .9rem; padding: .6rem .8rem; max-width: 100%; }
.gp-chat .bubble.you { background: var(--accent-soft); color: var(--ink); border: 1px solid var(--line); }

/* ------------------------------------------------------ differential */
.banner {
  background: var(--caution-soft);
  border: 1px solid color-mix(in srgb, var(--caution) 35%, transparent);
  color: var(--caution);
  border-radius: var(--r-control);
  padding: var(--s3) var(--s4);
  font-size: .82rem;
  line-height: 1.55;
  margin-bottom: var(--s4);
  display: flex;
  gap: var(--s2);
}
.banner .icon { margin-top: .1em; }

.dx-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  padding: var(--s5);
  margin-bottom: var(--s3);
  box-shadow: var(--shadow-1);
  transition: box-shadow var(--slow) var(--ease), border-color var(--slow) var(--ease);
}
.dx-card:hover { box-shadow: var(--shadow-2); border-color: var(--line-2); }

.dx-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s3);
  margin-bottom: var(--s3);
}
.dx-head strong { font-size: 1.02rem; font-weight: 620; letter-spacing: -.01em; }

.dx-pct {
  font-family: var(--mono);
  font-size: 1.35rem;
  font-weight: 500;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
}

.dx-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  margin-top: var(--s4);
  padding-top: var(--s4);
  border-top: 1px solid var(--line);
}
.dx-actions button { padding: .4rem .75rem; min-height: 36px; font-size: .84rem; }

#rankHistory .look { font-family: var(--mono); font-size: .78rem; }

/* ------------------------------------------------------------ graph */
.graph-wrap {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  padding: var(--s4);
  overflow-x: auto;
}
.graph-wrap svg { width: 100%; min-width: 560px; height: auto; }
.graph-edge { stroke: var(--line-2); stroke-width: 1.5; }
.graph-node { fill: var(--accent-soft); stroke: var(--accent); stroke-width: 1.5; cursor: pointer; transition: fill var(--fast) var(--ease); }
.graph-node:hover { fill: var(--accent); }
.graph-label { fill: var(--ink-2); font-size: 10px; font-family: var(--sans); pointer-events: none; }

/* ------------------------------------------------------- ref panel */
.ref-panel {
  position: fixed;
  top: 0; right: 0; bottom: 0;
  width: min(30rem, 100vw);
  background: var(--surface);
  border-left: 1px solid var(--line);
  box-shadow: var(--shadow-3);
  padding: var(--s6);
  overflow-y: auto;
  z-index: 40;
  animation: slide-in var(--slow) var(--ease) both;
}
@keyframes slide-in { from { transform: translateX(16px); opacity: 0; } to { transform: none; opacity: 1; } }

.ref-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--s4);
  margin-bottom: var(--s3);
}
.ref-head h2 { font-size: 1.1rem; letter-spacing: -.01em; }
.ref-disc { color: var(--ink-3); font-size: .8rem; line-height: 1.5; margin-bottom: var(--s5); }
.ref-h3 { font-size: .88rem; font-weight: 620; letter-spacing: -.01em; color: var(--ink); margin: var(--s5) 0 var(--s3); }

.guide-block { margin-top: var(--s4); }
.cite-card {
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-control);
  padding: var(--s4);
  margin-bottom: var(--s2);
}
.cite-card strong { display: block; font-size: .92rem; line-height: 1.45; margin-bottom: .3rem; }
.cite-card a { color: var(--ink); font-size: .8rem; word-break: break-all; text-decoration: underline; text-underline-offset: 2px; }
.cite-meta { font-family: var(--mono); font-size: .76rem; color: var(--ink-3); margin-bottom: .3rem; }

/* ================================================ states: load/empty/error */
/* Skeletons mirror the shape of what is coming, so the layout does not jump. */
.skel {
  background: linear-gradient(90deg, var(--surface-3) 25%, var(--surface-2) 37%, var(--surface-3) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.4s ease-in-out infinite;
  border-radius: 6px;
}
@keyframes shimmer { from { background-position: 100% 0; } to { background-position: 0 0; } }

.skel-block { padding: var(--s1) 0; }
.skel-line { height: 12px; margin-bottom: var(--s2); }
.skel-line.w-40 { width: 40%; }
.skel-line.w-60 { width: 60%; }
.skel-line.w-80 { width: 80%; }
.skel-chip { height: 24px; width: 5.5rem; border-radius: var(--r-pill); }
.skel-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  padding: var(--s5);
  margin-bottom: var(--s3);
}
.skel-row { display: flex; gap: var(--s2); margin-top: var(--s3); }

.state {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s2);
  padding: var(--s6) var(--s5);
  border: 1px dashed var(--line-2);
  border-radius: var(--r-panel);
  background: var(--surface-2);
  color: var(--ink-2);
  font-size: .88rem;
  line-height: 1.6;
}
.state .icon { color: var(--ink-3); }
.state strong { color: var(--ink); font-size: .95rem; font-weight: 600; }
.state.is-error { border-color: color-mix(in srgb, var(--alert) 40%, transparent); background: var(--alert-soft); color: var(--alert); }
.state.is-error strong, .state.is-error .icon { color: var(--alert); }
.state .btn-speak { margin-top: var(--s2); }

.spinner {
  width: 14px; height: 14px;
  border: 2px solid var(--line-2);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin .7s linear infinite;
  flex: none;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* A degraded model transport is clinical information, not a toast. */
.conn-note {
  display: flex;
  align-items: center;
  gap: var(--s2);
  padding: .4rem .8rem;
  border-radius: var(--r-pill);
  background: var(--caution-soft);
  border: 1px solid color-mix(in srgb, var(--caution) 35%, transparent);
  color: var(--caution);
  font-size: .8rem;
  font-weight: 550;
}

/* ========================================================= DEMO SWITCHER */
body.demo-switcher {
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--bg);
}

.demo-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--s5);
  flex-wrap: wrap;
  padding: var(--s4) var(--s6);
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  color: var(--ink);
}
.demo-brand { display: flex; align-items: baseline; gap: var(--s3); flex-wrap: wrap; }
.demo-brand strong { font-size: 1rem; letter-spacing: -.015em; font-weight: 620; }
.demo-brand span { font-size: .8rem; color: var(--ink-3); }
.demo-note { font-size: .78rem; color: var(--ink-3); max-width: 34rem; line-height: 1.5; }

.demo-tabs {
  display: flex;
  gap: var(--s2);
  padding: var(--s3) var(--s6);
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  overflow-x: auto;
  flex: none;
}
.demo-tab {
  border: 1px solid var(--line-2);
  background: var(--surface);
  color: var(--ink-2);
  border-radius: var(--r-pill);
  padding: .35rem .85rem;
  font-size: .84rem;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--fast) var(--ease), color var(--fast) var(--ease), border-color var(--fast) var(--ease);
}
.demo-tab:hover { border-color: var(--accent); color: var(--accent); }
.demo-tab.api-tab { font-family: var(--mono); font-size: .78rem; }
.demo-tab.is-on { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }

.demo-stage { flex: 1; display: flex; min-height: 0; overflow: hidden; }

.demo-frame {
  flex: 1;
  width: 100%;
  height: 100%;
  border: none;
  background: var(--surface);
}

.demo-split { flex: 1; display: flex; gap: 1px; background: var(--line); min-height: 0; }
.demo-pane { flex: 1; display: flex; flex-direction: column; min-width: 0; background: var(--surface); }
.demo-pane-label {
  padding: var(--s2) var(--s4);
  font-size: .76rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-3);
  border-bottom: 1px solid var(--line);
  background: var(--surface-2);
}
.demo-pane iframe { flex: 1; width: 100%; border: none; }

.demo-api { flex: 1; overflow-y: auto; padding: var(--s6); }
.demo-api h2 { font-size: 1.15rem; margin-bottom: var(--s2); }
.demo-api .path { font-family: var(--mono); font-size: .84rem; color: var(--ink-2); margin-bottom: var(--s2); }
.demo-api .blurb { color: var(--ink-2); font-size: .88rem; line-height: 1.6; margin-bottom: var(--s4); max-width: 52rem; }
.demo-api textarea {
  width: 100%;
  max-width: 42rem;
  min-height: 7rem;
  font-family: var(--mono);
  font-size: .82rem;
  background: var(--surface-2);
  border: 1px solid var(--line-2);
  border-radius: var(--r-control);
  padding: var(--s3);
  margin-bottom: var(--s3);
}
.demo-api pre {
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-control);
  padding: var(--s4);
  font-family: var(--mono);
  font-size: .8rem;
  line-height: 1.6;
  overflow-x: auto;
  margin-top: var(--s4);
  color: var(--ink-2);
}
.demo-err { color: var(--alert); font-size: .84rem; margin-top: var(--s2); }

/* ======================================================== responsive */
@media (max-width: 1180px) {
  .portal-grid { grid-template-columns: 14rem minmax(0, 1fr) minmax(0, 1fr); }
  .portal-grid .brief-col { grid-column: 2 / -1; }
}

@media (max-width: 860px) {
  .portal-grid { grid-template-columns: minmax(0, 1fr); }
  .portal-grid .brief-col { grid-column: auto; }
  .portal-rail, .portal-col { padding: var(--s5) var(--s4); }
  .portal-banner { padding: var(--s5) var(--s4); }
  .ref-panel { width: 100vw; }
  .chart-row { grid-template-columns: minmax(0, 1fr); gap: var(--s1); }
  .demo-split { flex-direction: column; }
}

@media (max-width: 620px) {
  /* The badge wraps under the name rather than squeezing it. */
  .intake-head { flex-wrap: wrap; }
  .staff-hint { margin-left: 0; width: 100%; justify-content: center; }
  .kiosk-shell { padding: var(--s5) var(--s4) var(--s4); }
  .checkin-card { padding: var(--s6) var(--s5); }
  .bubble { max-width: 88%; }
  .composer textarea { font-size: 1rem; }
  .clinic-bar { font-size: .68rem; padding: 0 var(--s4); }
  .clinic-bar span:last-child { display: none; }
}

/* Motion is a courtesy, never a requirement. Everything above degrades to
   static without losing meaning, including the thinking and listening cues. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .skel { background: var(--surface-3); }
  /* The sweep is decorative; the sentence is the information. Drop the
     gradient entirely so the text is painted normally, never transparent. */
  .shimmer-text {
    background-image: none;
    color: var(--ink-2);
    -webkit-text-fill-color: currentColor;
  }
}

/* ============================================================== print */
/* A brief that cannot be printed does not reach the paper notes. Print drops
   the dark ground, the navigation, and every control the page offers, leaving
   the chart and the ranked list on white. */
@media print {
  :root {
    --bg: #ffffff;
    --surface: #ffffff;
    --surface-2: #ffffff;
    --surface-3: #f1f1f1;
    --ink: #000000;
    --ink-2: #2b2b2b;
    --ink-3: #4f4f4f;
    --line: #c9c9c9;
    --line-2: #8c8c8c;
    --accent: #000000;
    --accent-ink: #ffffff;
    --accent-soft: #f1f1f1;
    --shadow-1: none;
    --shadow-2: none;
    --shadow-3: none;
  }

  body { background: #fff; color: #000; }

  /* Chrome, controls and anything not part of the record. */
  .clinic-bar,
  .portal-rail,
  .portal-banner-actions,
  .prior-fold,
  .dx-actions,
  .ref-panel,
  .graph-wrap,
  .composer,
  .prompt-host,
  .btn-inline,
  #status { display: none !important; }

  .portal-grid { display: block; background: none; gap: 0; }
  .portal-col { padding: 0 0 var(--s5); min-height: 0; background: none; }
  .portal-banner { padding: 0 0 var(--s4); }

  /* Never split a diagnosis away from its evidence across a page break. */
  .dx-card,
  .chart-row,
  .gp-turn { break-inside: avoid; }

  .dx-card { box-shadow: none; }
  .skel { display: none; }

  /* On paper a link has to carry its own destination. */
  .cite-card a[href]::after {
    content: " (" attr(href) ")";
    font-size: .75em;
    color: #4f4f4f;
  }
}

/* ---- Check-in: identity before symptoms -------------------------------- */
/* Age and sex are asked because they change what the findings mean, so the
   card explains why rather than presenting an unexplained form. */
.check-in {
  display: flex;
  flex-direction: column;
  gap: 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  padding: 24px;
  margin: auto 0;
}

.check-in-title {
  margin: 0;
  font-size: 1.15rem;
  font-weight: 650;
  color: var(--ink);
}

.check-in-note {
  margin: 0;
  color: var(--muted, var(--ink));
  opacity: .75;
  font-size: .92rem;
  line-height: 1.5;
}

.check-in-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: 1 1 0;
}

.check-in-field > span {
  font-size: .85rem;
  font-weight: 600;
  opacity: .8;
}

.check-in-field input,
.check-in-field select {
  font: inherit;
  color: var(--ink);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r-control);
  padding: 11px 12px;
  min-height: 44px;
}

.check-in-field input:focus-visible,
.check-in-field select:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

.check-in-row {
  display: flex;
  gap: 12px;
}

.check-in-foot {
  margin: 0;
  font-size: .8rem;
  opacity: .6;
}

/* Keep the handoff action quiet until a visit is active, then keep it
   discoverable on a shared tablet without competing with the conversation. */
.check-in-reset {
  display: flex;
  justify-content: flex-end;
  margin: 0 0 10px;
}

@media (max-width: 420px) {
  .check-in-row { flex-direction: column; }
}

/* A safety prompt is not a ranking. It must not read as one. */
.safety-prompt {
  border-left: 3px solid var(--caution, var(--line));
  background: var(--caution-soft, var(--surface));
}

.safety-prompt .dx-head { align-items: center; }

.look-list {
  margin: 8px 0 0;
  padding-left: 18px;
  font-size: .9rem;
  line-height: 1.55;
  opacity: .85;
}

.check-in-error {
  margin: 0;
  color: var(--alert, #b42318);
  background: var(--alert-soft, transparent);
  border-radius: var(--r-control);
  padding: 10px 12px;
  font-size: .9rem;
}

.check-in-field input[aria-invalid="true"],
.check-in-field select[aria-invalid="true"] {
  border-color: var(--alert, #b42318);
}

/* ---- Screen 1: the waiting room ---------------------------------------- */
/* A clinician picks a person before reading a chart, so the queue is a
   destination rather than a rail beside whoever happened to be selected. */
.queue-screen {
  /* min-height: 0 so a leftover flex ancestor cannot squash the title. */
  max-width: 1100px;
  margin: 0 auto;
  padding: 28px 24px 48px;
  min-height: 0;
}

.queue-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}

.queue-head h1 { margin: 0 0 4px; }

.queue-groups {
  display: flex;
  flex-direction: column;
  gap: 26px;
  margin-top: 22px;
}

.queue-group-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 10px;
  font-size: .82rem;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  opacity: .7;
}

.queue-group-count {
  font-size: .78rem;
  letter-spacing: 0;
  padding: 1px 8px;
  border-radius: var(--r-pill);
  background: var(--line);
  opacity: .9;
}

/* Urgency is a border, not a shout. Colouring whole rows would make the
   routine ones look wrong rather than making the urgent ones look urgent. */
.queue-group.is-emergency .queue-group-head { color: var(--alert); opacity: 1; }
.queue-group.is-emergency .appt { border-left: 3px solid var(--alert); }
.queue-group.is-urgent .queue-group-head { color: var(--caution); opacity: 1; }
.queue-group.is-urgent .appt { border-left: 3px solid var(--caution); }

.queue-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(288px, 1fr));
  gap: 12px;
}

.queue-list .appt { width: 100%; }

.appt-who { display: flex; flex-direction: column; gap: 2px; }
.appt-name { font-weight: 620; }
.appt-meta { font-size: .82rem; opacity: .65; }
.chip.is-ready { color: var(--ok, inherit); }

/* ---- Screen 2: one patient --------------------------------------------- */
.patient-grid {
  display: grid;
  grid-template-columns: minmax(320px, 1fr) minmax(420px, 1.35fr);
  gap: 20px;
  padding: 0 24px 48px;
  align-items: start;
}

.btn-back { margin-bottom: 10px; }

/* The graph is the auditable part of the product. It was three nodes in a
   scrolling rail; here it gets the width to be read. */
.graph-wrap-lg { min-height: 320px; }
.graph-wrap-lg svg { width: 100%; height: auto; }

.chat-fold,
.rank-fold,
.prior-fold { margin-top: 18px; }

.chat-fold > summary,
.rank-fold > summary,
.prior-fold > summary {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  font-weight: 600;
  padding: 10px 0;
}

@media (max-width: 900px) {
  .patient-grid { grid-template-columns: 1fr; }
  .queue-list { grid-template-columns: 1fr; }
}

/* A closed visit stays listed -- "did I see them?" is asked ten minutes
   later -- but must not compete with the people still waiting. */
.appt.is-seen { opacity: .55; }
.appt.is-seen .appt-name { text-decoration: line-through; }

/* Neither of these is a ranking, so neither may look like one. */
.coverage-card { border-left: 3px solid var(--line); }
.establish-card { border-left: 3px solid var(--accent-soft, var(--line)); }

/* Presenter teleprompter: cue column plus persistent product frames. */
body.teleprompter {
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--bg);
}
.tele-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--s4);
  flex-wrap: wrap;
  padding: var(--s3) var(--s5);
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
.tele-controls { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }
.tele-status { font-size: .78rem; color: var(--ink-3); max-width: 22rem; }
.tele-shell { flex: 1; display: flex; min-height: 0; }
.tele-cue {
  width: 22rem;
  flex: none;
  overflow-y: auto;
  padding: var(--s5);
  border-right: 1px solid var(--line);
  background: var(--surface);
}
.tele-beat-meta {
  font-size: .72rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: var(--s3);
}
.tele-lines { list-style: none; padding: 0; margin: 0 0 var(--s5); }
.tele-lines li {
  font-size: 1.05rem;
  line-height: 1.45;
  color: var(--ink-3);
  margin-bottom: var(--s4);
}
.tele-lines li.is-now { color: var(--ink); font-size: 1.2rem; font-weight: 620; }
.tele-lines li.is-past { opacity: .45; }
.tele-you-do h2 {
  font-size: .72rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: var(--s2);
}
.tele-you-do li { font-size: .88rem; line-height: 1.5; color: var(--ink-2); margin-bottom: var(--s2); }
.tele-stage { flex: 1; display: flex; min-width: 0; min-height: 0; position: relative; background: var(--bg); }
.tele-frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: none;
  background: var(--surface);
  opacity: 0;
  pointer-events: none;
  /* iframe document scrolls; this is the fallback if a UA hides that. */
  overflow: auto;
}
.tele-frame.is-on { opacity: 1; pointer-events: auto; }
.tele-cloud {
  position: absolute;
  inset: 0;
  overflow: auto;
  padding: var(--s4);
  box-sizing: border-box;
  display: grid;
  place-items: center;
  /* Keep the approved screen recording framed without altering its pixels. */
  background: var(--bg);
  opacity: 0;
  pointer-events: none;
}
.tele-cloud.is-on { opacity: 1; pointer-events: auto; }
.tele-cloud-video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  border: 0;
}
.tele-blank {
  position: absolute;
  inset: 0;
  background: var(--bg);
  opacity: 0;
  pointer-events: none;
}
.tele-blank.is-on { opacity: 1; pointer-events: auto; }
.tele-arch {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: #0b1c1e;
  opacity: 0;
  pointer-events: none;
}
.tele-arch.is-on { opacity: 1; pointer-events: auto; }

/* Full presenter script: readable on a laptop, compact enough to print. */
body.script-page {
  min-height: 100vh;
  margin: 0;
  background: var(--bg);
  color: var(--ink);
}
.script-bar {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: var(--s5);
  padding: var(--s5) max(var(--s5), 5vw);
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
.script-kicker,
.script-subtitle,
.script-status {
  color: var(--ink-3);
}
.script-kicker {
  margin: 0 0 var(--s2);
  font-size: .72rem;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.script-bar h1 {
  margin: 0;
  font-size: clamp(1.8rem, 4vw, 3rem);
}
.script-subtitle {
  margin: var(--s2) 0 0;
}
.script-actions {
  display: flex;
  align-items: center;
  gap: var(--s3);
  flex: none;
}
.script-main {
  width: min(54rem, calc(100% - 2 * max(var(--s4), 5vw)));
  margin: 0 auto;
  padding: var(--s5) 0 8rem;
}
.script-disclaimer {
  padding: var(--s3) var(--s4);
  border-left: 3px solid var(--accent);
  background: var(--surface);
  color: var(--ink-2);
  line-height: 1.5;
}
.script-tools {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(16rem, 1fr);
  gap: var(--s4);
  margin: var(--s5) 0;
}
.script-recorder,
.script-skip {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  padding: var(--s4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.script-recorder h2,
.script-skip h2 {
  margin: 0;
  font-size: 1rem;
}
.script-recorder p,
.script-skip p {
  margin: var(--s1) 0 0;
  color: var(--ink-3);
  font-size: .85rem;
  line-height: 1.45;
}
.script-recorder-controls {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
}
.script-recorder-controls > * {
  min-height: 2.4rem;
}
.script-recorder audio {
  width: 100%;
  height: 2.4rem;
}
.script-beat.is-focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 18%, transparent);
}
.script-status {
  font-size: .8rem;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.full-script {
  display: flex;
  flex-direction: column;
  gap: var(--s4);
}
.script-beat {
  padding: var(--s5);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  break-inside: avoid;
}
.script-beat-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s4);
  padding-bottom: var(--s3);
  border-bottom: 1px solid var(--line);
}
.script-beat h2 {
  margin: 0;
  font-size: 1.35rem;
  text-transform: capitalize;
}
.script-beat-meta {
  margin: 0;
  color: var(--ink-3);
  font-size: .74rem;
  letter-spacing: .04em;
  text-align: right;
  text-transform: uppercase;
}
.script-lines {
  padding: var(--s4) 0 var(--s2);
}
.script-lines p {
  margin: 0 0 var(--s4);
  font-size: 1.15rem;
  line-height: 1.65;
}
.script-lines p:last-child {
  margin-bottom: 0;
}
.script-presenter-notes {
  padding: var(--s3) var(--s4);
  background: var(--bg);
  border-radius: var(--radius-sm);
}
.script-presenter-notes h3 {
  margin: 0 0 var(--s2);
  color: var(--ink-3);
  font-size: .72rem;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.script-presenter-notes ul {
  margin: 0;
  padding-left: 1.2rem;
}
.script-presenter-notes li {
  margin: 0 0 var(--s2);
  color: var(--ink-2);
  line-height: 1.5;
}
.script-presenter-notes li:last-child {
  margin-bottom: 0;
}
.script-take {
  margin-top: var(--s4);
  padding-top: var(--s4);
  border-top: 1px solid var(--line);
}
.script-take h3 {
  margin: 0 0 var(--s1);
  font-size: .85rem;
}
.script-take-file {
  margin: 0 0 var(--s3);
  color: var(--ink-3);
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: .75rem;
}
.script-take-status {
  margin: var(--s2) 0 0;
  color: var(--ink-3);
  font-size: .8rem;
}
.script-audio-beat {
  width: 100%;
  height: 2.4rem;
  margin-top: var(--s3);
}
.script-pause {
  display: flex;
  align-items: center;
  gap: var(--s3);
  min-height: 3rem;
  padding: var(--s3) var(--s4);
  border: 1px dashed var(--line-strong, var(--line));
  border-radius: var(--radius-sm);
  color: var(--ink-2);
  break-inside: avoid;
}
.script-pause strong {
  color: var(--ink-3);
  font-size: .75rem;
  letter-spacing: .08em;
  white-space: nowrap;
}
.script-pause.is-slide-change {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
}
.script-pause.is-slide-change strong {
  color: var(--accent);
}
.script-pause-action {
  color: var(--ink-3);
  font-size: .9rem;
}
.script-loading,
.script-error,
.script-noscript {
  padding: var(--s4);
  background: var(--surface);
  color: var(--ink-2);
}

/* Phones stack the title and keep transition cues visible without scrolling
   horizontally. */
@media (max-width: 700px) {
  .script-bar {
    align-items: flex-start;
    flex-direction: column;
  }
  .script-tools {
    grid-template-columns: 1fr;
  }
  .script-actions {
    width: 100%;
  }
  .script-actions > * {
    flex: 1;
    text-align: center;
  }
  .script-beat-header {
    align-items: flex-start;
    flex-direction: column;
  }
  .script-beat-meta {
    text-align: left;
  }
  .script-pause {
    align-items: flex-start;
    flex-direction: column;
    gap: var(--s2);
  }
}

/* A printed copy is the editing-room handout: remove navigation and preserve
   every beat plus each explicit pause marker. */
@media print {
  body.script-page {
    background: #fff;
    color: #000;
  }
  .script-bar {
    padding: 0 0 1rem;
    border: 0;
  }
  .script-actions,
  .script-status,
  .script-tools {
    display: none;
  }
  .script-main {
    width: 100%;
    padding: 1rem 0;
  }
  .script-disclaimer,
  .script-beat,
  .script-pause {
    box-shadow: none;
    background: #fff;
  }
  .script-beat {
    border-color: #bbb;
  }
  .script-lines p {
    font-size: 1rem;
  }
  .script-pause {
    margin: .5rem 0;
  }
}
