/* SeamLess — v0.13
 *
 * Light and dark, following the system unless the clinician says otherwise.
 * (Until 2026-08-21 this read "one committed light theme, no toggle", on the
 * argument that a design serving both schemes serves neither. Withdrawn: a
 * consulting room's light changes through the day and nobody gets to choose
 * it. The tokens carry the theme; no component below redefines a colour.)
 * The superseded argument, kept because it is still the reason to be careful:
 * a design that has to work in both
 * schemes ends up working well in neither, so this picks one and commits.
 *
 * No framework and no build step: this file is read top to bottom, so it is
 * ordered tokens → shell → cards → card contents → sign-in, and nothing later
 * reaches back to undo something earlier.
 */

:root {
  /* Light, and the SeamLess purple back. Declared here so the browser themes
     scrollbars, the search field's clear button and the canvas itself. */
  color-scheme: light;
  accent-color: #5d4ee0;

  /* Neutrals biased toward the accent, so the greys read as chosen rather
     than inherited. Nothing here is a pure grey. */
  --void:        #b3a8d8;   /* outside the shell */
  --ground:      #d3cbec;   /* the shell body -- the panels sit ON this */
  --panel:       #faf9fe;   /* cards -- off-white, tinted to the accent */
  --panel-2:     #f0edfa;   /* tiles inside cards */
  --panel-3:     #e4dff5;   /* hover, avatar ground */
  /* Ground for a did-you-mean row: a shade off the panel, enough to read as
     a separate group without competing with the accent. */
  /* Three literals that had spread through the sheet by repetition rather
     than by decision: text on an accent fill (7 uses), the near-black bed a
     radiograph sits on (6), and the input ground (8). Named, so the next use
     is a choice. */
  --on-accent:   #fbfaff;
  --film-bed:    #16141f;
  --field:       #fdfcff;
  --suggest-bg:  #f6f3fd;

  /* Added 2026-08-21, when dark stopped being owed and started being built.
     Every one of these was a literal somewhere in the sheet -- a translucent
     white, a gradient stop, a shadow -- and a literal is exactly what a second
     theme cannot redefine. Shadows carry their channels separately so the
     alpha stays at the call site: a panel shadow and a hover shadow want the
     same ink at different strengths. */
  --panel-a:     rgba(250, 249, 254, 0.86);  /* panel, floated over something */
  --stage-hi:    #eeeafa;                    /* the lit centre of the stage */
  --stripe-a:    #e8e4f6;                    /* the "reserved" hatch */
  --stripe-b:    #f2effb;
  --bed-1:       #e2ddf4;                    /* the film bed gradient */
  --bed-2:       #ebe7f8;
  --bed-3:       #f2effb;
  --ink-4:       #736d8c;                    /* placeholders. 4.8:1 on --field;
                                                the #8b85a3 it replaces was 3.4:1 */
  --accent-deep: #4a37bd;                    /* initials on an accent tile */
  --accent-2:    #9b8cf5;                    /* second and third chart series */
  --accent-3:    #c3b8fa;
  --ok-line:     #bfe6d4;
  --shadow-rgb:  26 24 38;
  --accent-rgb:  93 78 224;
  --line:        #ddd6f2;
  --line-soft:   #e7e2f6;

  --ink:         #1a1826;
  --ink-2:       #4a4560;
  --ink-3:       #67617f;   /* 5.0:1 on the tile ground, where it mostly sits */

  /* #7c6cf0 is 3.3:1 on white and cannot legally hold white button text, so
     fills are two steps darker. Same hue; the brand survives the move. */
  --accent:      #5d4ee0;   /* fills; white on this is 5.8:1 */
  --accent-hi:   #4f3fd4;
  --accent-ink:  #5340cf;   /* the purple as TEXT on white, 7.0:1 */
  --accent-bg:   #efecfd;
  --accent-line: #d5cdf6;

  --ok:          #17724e;
  --ok-bg:       #e3f6ed;
  --warn:        #8a5300;
  --warn-bg:     #fdf0dc;
  --info-ink:    #12559e;
  --info-bg:     #e4eefb;
  --bad-ink:     #a3123a;
  --bad-bg:      #fdeaef;
  /* The border and the dot for the same family, which had no tokens because
     nothing had drawn a failure surface until the assistant needed one. */
  --bad-line:    #f2c9d5;
  --bad:         #c01741;

  --scroll:      #b9afd9;

  /* Elevation. Two layers each: a hairline contact shadow and a soft cast one,
     both offset -- a zero-offset halo is decoration, not depth. The cast layer
     is tinted violet rather than grey so it belongs to this ground. */
  --shadow-1:
    0 1px 2px rgba(38, 26, 92, 0.10),
    0 10px 22px -10px rgba(46, 34, 120, 0.30);
  --shadow-2:
    0 2px 4px rgba(38, 26, 92, 0.10),
    0 18px 36px -14px rgba(46, 34, 120, 0.34),
    0 44px 72px -40px rgba(46, 34, 120, 0.30);

  /* Kept so anything still reaching for the old names resolves. */
  --card:        var(--panel);
  --card-2:      var(--panel-2);
  --rail:        var(--ground);
  --accent-dim:  var(--accent-ink);

  --r:           14px;
  --r-sm:        9px;

  --sans: "Inter var", Inter, -apple-system, BlinkMacSystemFont, "Segoe UI",
          Roboto, "Helvetica Neue", Arial, sans-serif;
}

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

button, input { font: inherit; color: inherit; }

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

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

.muted { color: var(--ink-2); }
.small { font-size: 13px; }
.accent { color: var(--accent-dim); }

/* ----------------------------------------------------------------- shell */

/* The top-nav shell. Sections are body systems now, so they read across rather
   than down, and the workspace is three columns: who the patient is, the body,
   and what was found. Palette is the mockup's -- blue-black ground, one blue
   doing all the work, generous radii. */

/* .centred sets display:grid on the sign-in, which beats the UA stylesheet's
   [hidden] rule -- without this the signed-in app renders BELOW a still-visible
   sign-in screen. */
.screen { min-height: 100%; }
.screen[hidden] { display: none; }

.app {
  height: 100dvh;
  padding: 18px;
  overflow: hidden;
  background: var(--void);
}

.shell {
  height: 100%;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--ground);
  border: 1px solid rgba(252, 251, 255, 0.65);
  border-radius: 22px;
  overflow: hidden;
  box-shadow: var(--shadow-2);
}

/* ------------------------------------------------------------------ topnav */

.topnav {
  flex: none;
  display: flex;
  align-items: center;
  gap: 22px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--line-soft);
}

.brand { display: flex; align-items: center; gap: 11px; flex: none; }
.brand b { font-size: 19px; font-weight: 600; letter-spacing: -0.02em; }
/* The mark is a circle of colour that turns. A conic gradient rotated by
   transform costs one composited layer; animating the gradient itself would
   repaint every frame. The hues stay inside the violet-indigo family so it
   reads as this product rather than as a generic rainbow loader. */
.brand-mark {
  width: 34px; height: 34px;
  border-radius: 50%;
  flex: none;
  position: relative;
}
.brand-mark:not(.is-live) { overflow: hidden; }
/* No fill and no ring: the orb carries its own alpha, so anything painted
   behind it fills the transparent corners back in and flattens it into a
   disc. The fallback below supplies its own colour when there is no canvas. */
.brand-mark:not(.is-live) {
  background: var(--accent);
  box-shadow: 0 3px 10px -3px rgb(var(--accent-rgb) / 0.5);
}
.brand-mark svg { display: none; }        /* the asterisk it replaces */

.brand-mark::before {
  content: "";
  position: absolute;
  inset: -35%;
  background: conic-gradient(from 0deg,
    #4f3fd4, #7c6cf0, #a78bfa, #c46ff0, #7c6cf0, #5d4ee0, #4f3fd4);
  animation: mark-turn 9s linear infinite;
  will-change: transform;
}

/* A single specular highlight, so it reads as an object catching light rather
   than as a flat spinning swatch. */
.brand-mark::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background:
    radial-gradient(circle at 34% 26%, rgba(253,252,255,0.6), transparent 52%),
    radial-gradient(circle at 70% 82%, rgba(28,16,80,0.28), transparent 55%);
}

@keyframes mark-turn { to { transform: rotate(1turn); } }

.tabs {
  display: flex;
  align-items: center;
  gap: 2px;
  flex: 1;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }

.tab {
  padding: 9px 15px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--ink-2);
  font: inherit;
  font-size: 15px;
  white-space: nowrap;
  cursor: pointer;
  transition: color 130ms ease-out, background 130ms ease-out;
}
.tab:hover { color: var(--ink); background: var(--panel-2); }
.tab.is-active { background: var(--accent); color: var(--on-accent); font-weight: 500; }
.tab.is-active:hover { background: var(--accent-hi); }

.topnav-end { display: flex; align-items: center; gap: 8px; flex: none; }

.icon-btn {
  width: 38px; height: 38px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: var(--panel-2);
  color: var(--ink-2);
  cursor: pointer;
  transition: background 130ms ease-out, color 130ms ease-out;
}
.icon-btn:hover { background: var(--panel-3); color: var(--ink); }
.icon-btn svg { width: 19px; height: 19px; }
.icon-btn.sm { width: 28px; height: 28px; background: transparent; }
.icon-btn.sm svg { width: 16px; height: 16px; }
.icon-btn.sm:hover { background: var(--panel-2); }

/* Every icon in the sprite is stroke-only on one weight. */
svg use, .sprite g { fill: none; stroke: currentColor; stroke-width: 1.75;
                     stroke-linecap: round; stroke-linejoin: round; }

.avatar {
  border-radius: 50%;
  background: var(--panel-3);
  color: var(--ink-2);
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.03em;
  flex: none;
  width: 34px; height: 34px;
}
.avatar.me { border: 0; cursor: pointer; font: inherit; font-size: 12px; font-weight: 600; }
.avatar.lg { width: 52px; height: 52px; border-radius: 14px; font-size: 15px;
             background: var(--accent-bg); color: var(--accent-ink); }

.account { position: relative; }
.account-menu {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  z-index: 40;
  min-width: 210px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--panel);
  box-shadow: var(--shadow-2);
}
.account-menu[hidden] { display: none; }
.account-menu b { font-size: 15px; font-weight: 500; }
.account-menu > span { font-size: 13px; }
.account-menu button {
  margin-top: 11px;
  padding: 9px 13px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: transparent;
  color: var(--ink-2);
  font: inherit;
  font-size: 14px;
  cursor: pointer;
}
.account-menu button:hover { border-color: var(--accent-line); color: var(--ink); }


/* --------------------------------------------------------------- the mark */

/* The logo is the orb -- the same shader the assistant opens on, at 34px.
   One object, two sizes, so the thing that greets you in the chat and the
   thing in the corner are recognisably the same.
 *
 * The conic-gradient ::before / ::after below stay as the fallback: they are
 * what a machine with no WebGL sees, and they are what paints for the frame or
 * two before the canvas mounts. `.is-live` hides them once the orb is real, so
 * the two are never composited on top of each other. */
.brand-mark.is-live::before,
.brand-mark.is-live::after,
.panel .mark-glyph.is-live::before,
.panel .mark-glyph.is-live::after { content: none; }

.brand-mark canvas,
.panel .mark-glyph canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* --------------------------------------------------------------- workspace */

.workspace {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 320px minmax(0, 1fr) 360px;
  grid-auto-rows: minmax(0, 1fr);
  gap: 14px;
  padding: 14px;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: thin;
  scrollbar-color: var(--scroll) transparent;
}
.workspace[hidden] { display: none; }

/* The floors. Below these a panel stops being readable, so the workspace
   scrolls instead of shrinking it further. */
.col          { min-height: 260px; }
.stage        { min-height: 340px; }
.col-right    { min-height: 300px; }
.card.wide    { min-height: 220px; }
.home-left > .card { min-height: 200px; }

.col {
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--scroll) transparent;
}

/* The board's .card is a fixed-height flex child that clips its own overflow.
   In these columns a card sizes to its content and the COLUMN scrolls, so both
   of those have to be undone or the last tile in each card is cut off. */
.col > .card {
  box-shadow: var(--shadow-1);
  flex: none;
  overflow: visible;
  padding: 16px;
  border-radius: 18px;
  background: var(--panel);
  border: 1px solid var(--line-soft);
}

/* --------------------------------------------------------- left-hand cards */

.card-top {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 14px;
}
.card-top h2 { margin: 0; font-size: 17px; font-weight: 600; letter-spacing: -0.015em; }
.corner[hidden] { display: none; }
.corner { margin-left: 0; }
.card-top .corner:first-of-type { margin-left: auto; }
.corner {
  width: 30px; height: 30px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 9px;
  background: transparent;
  color: var(--ink-3);
  cursor: pointer;
}
.corner:hover { background: var(--panel-2); color: var(--ink); }
.corner svg { width: 16px; height: 16px; }

.ident { display: flex; align-items: center; gap: 13px; margin-bottom: 14px; }
.ident-text { display: flex; flex-direction: column; min-width: 0; }
.ident-text b { font-size: 19px; font-weight: 600; letter-spacing: -0.02em; }
.ident-text span { font-size: 13.5px; }

.stats { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.stat {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 11px 12px;
  border-radius: 13px;
  background: var(--panel-2);
}
.stat-icon {
  width: 32px; height: 32px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  background: var(--accent-bg);
  color: var(--accent-ink);
  flex: none;
}
.stat-icon svg { width: 17px; height: 17px; }
.stat-text { display: flex; flex-direction: column; min-width: 0; }
.stat-text span { font-size: 11.5px; color: var(--ink-3); }
.stat-text b { font-size: 14.5px; font-weight: 500; letter-spacing: -0.01em; }

/* Appointments. The active one is the encounter the right panel is showing,
   so the highlight is a statement of what you are looking at, not decoration. */
.visit-list { display: flex; flex-direction: column; gap: 8px; }
.visit-row {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 11px 12px;
  border: 0;
  border-radius: 13px;
  background: var(--panel-2);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background 130ms ease-out;
}
.visit-row:hover { background: var(--panel-3); }
.visit-row .avatar { width: 30px; height: 30px; font-size: 10.5px; }
.visit-text { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.visit-text span { font-size: 11.5px; color: var(--ink-3); }
.visit-text b { font-size: 14.5px; font-weight: 500; letter-spacing: -0.01em;
                overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.visit-row svg { width: 16px; height: 16px; color: var(--ink-3); flex: none; }

.visit-row.is-active { background: var(--accent); }
.visit-row.is-active .visit-text span { color: rgba(251,250,255,0.92); }
.visit-row.is-active .visit-text b { color: var(--on-accent); }
.visit-row.is-active .avatar { background: rgba(251,250,255,0.22); color: var(--on-accent); }
.visit-row.is-active:hover { background: var(--accent-hi); }

/* Results. A chip for the analyte, the number large, the reading underneath. */
.labs { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.lab {
  padding: 12px;
  border-radius: 13px;
  background: var(--panel-2);
  display: flex;
  flex-direction: column;
  gap: 7px;
  min-width: 0;
}
.lab-top { display: flex; }
.lab-chip {
  padding: 3px 9px;
  border-radius: 7px;
  background: var(--accent-bg);
  color: var(--accent-ink);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  line-height: 1.35;
  max-width: 100%;
}
.lab-val {
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.015em;
  font-variant-numeric: tabular-nums;
}
.lab-val small { font-size: 11.5px; font-weight: 400; color: var(--ink-3); margin-left: 3px; }
.lab-note { font-size: 12.5px; color: var(--ink-3); }
.lab.is-high .lab-chip { background: var(--warn-bg); color: var(--warn); }
.lab.is-high .lab-note { color: var(--warn); }
.lab.is-low  .lab-chip { background: var(--info-bg); color: var(--info-ink); }
.lab.is-low  .lab-note { color: var(--info-ink); }
.lab.is-crit .lab-chip { background: var(--bad-bg); color: var(--bad-ink); }
.lab.is-crit .lab-note { color: var(--bad-ink); }

.by {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-top: 13px;
  padding-top: 13px;
  border-top: 1px solid var(--line-soft);
  font-size: 12.5px;
  color: var(--ink-3);
}
.by[hidden] { display: none; }
.by .avatar { width: 24px; height: 24px; font-size: 9.5px; }
.by time { margin-left: auto; font-variant-numeric: tabular-nums; }

/* -------------------------------------------------------------- the stage */

.stage {
  box-shadow: var(--shadow-1);
  position: relative;
  min-width: 0;
  min-height: 0;
  border-radius: 18px;
  background:
    radial-gradient(ellipse 70% 60% at 50% 42%, var(--stage-hi) 0%, var(--panel) 76%);
  border: 1px solid var(--line-soft);
  overflow: hidden;
}

.seg {
  position: absolute;
  top: 16px; left: 16px; right: 16px;
  z-index: 3;
  display: flex;
  gap: 4px;
  padding: 5px;
  border-radius: 14px;
  background: var(--panel-a);
  backdrop-filter: blur(14px);
  border: 1px solid var(--line);
}
.seg-item {
  flex: 1;
  padding: 10px 12px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: var(--ink-2);
  font: inherit;
  font-size: 14.5px;
  cursor: pointer;
  white-space: nowrap;
  transition: background 130ms ease-out, color 130ms ease-out;
}
.seg-item:hover { color: var(--ink); }
.seg-item.is-active {
  background: var(--accent-bg);
  color: var(--accent-ink);
  font-weight: 500;
  box-shadow: inset 0 0 0 1px var(--accent-line);
}

.round {
  width: 40px; height: 40px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--panel-a);
  backdrop-filter: blur(10px);
  color: var(--ink-2);
  cursor: pointer;
  transition: color 130ms ease-out, border-color 130ms ease-out;
}
.round:hover { color: var(--ink); border-color: var(--line); }
.round svg { width: 18px; height: 18px; }
.round.tl { position: absolute; top: 84px; left: 16px; z-index: 3; }

.zoom {
  position: absolute;
  bottom: 16px; left: 16px;
  z-index: 3;
  display: flex;
  flex-direction: column;
  gap: 9px;
}

/* The model slot. Drawn as a reserved space with its own frame -- an empty
   panel here would read as a failed load, which is the one thing a placeholder
   must not do. */
.model { position: absolute; inset: 0; display: grid; place-items: center; padding: 92px 24px 24px; }
.model-slot[hidden] { display: none; }
.model-slot {
  max-width: 340px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 9px;
  padding: 30px 26px;
  border: 1.5px dashed var(--accent-line);
  border-radius: 18px;
  background: var(--panel-a);
}
.model-badge {
  padding: 3px 10px;
  border-radius: 999px;
  border: 1px solid var(--accent-line);
  background: var(--accent-bg);
  color: var(--accent-ink);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}
.model-slot b { font-size: 18px; font-weight: 600; letter-spacing: -0.015em; }
.model-slot p { margin: 0; font-size: 13.5px; color: var(--ink-2); line-height: 1.5; }
.model-region { color: var(--ink-3) !important; font-size: 12.5px !important; }
.model-region em { font-style: normal; color: var(--accent-ink); }

/* The model itself, once limb.js has it. The canvas is absolutely placed so it
   fills the padding box the slot is centred in -- host.clientWidth/Height then
   measures exactly what the canvas covers, which is what the resize observer
   feeds the camera aspect. */
.model-canvas {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  cursor: grab;
  /* OrbitControls listens for pointer events; without this the browser claims
     the drag for scrolling on a touchscreen and the model never turns. */
  touch-action: none;
}
.model-canvas:active { cursor: grabbing; }
.model-canvas:focus-visible { outline: 2px solid var(--accent); outline-offset: -3px; }
.model.is-live { padding: 0; }

/* The name of whatever was last clicked. It rides the top band, under the stage
   tabs: the bottom of this panel already belongs to the zoom cluster and the
   SOAP card, and a readout that covers the open note to tell you what you just
   clicked has taken more than it gave. Opaque rather than translucent, because
   it is read against a moving 3D scene. */
.model-pick {
  position: absolute;
  left: 50%;
  top: 78px;
  z-index: 3;
  margin: 0;
  max-width: min(340px, calc(100% - 160px));
  padding: 7px 15px;
  border: 1px solid var(--accent-line);
  border-radius: 999px;
  background: var(--panel);
  box-shadow: 0 8px 22px -12px rgb(var(--shadow-rgb) / 0.5);
  color: var(--accent-ink);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.35;
  text-align: center;
  transform: translateX(-50%);
}
/* Two lines: the structure, then the system it belongs to. The group is the
   quieter of the two -- it is context for the name, not a second answer. */
.model-pick b { display: block; font-weight: 600; }
.model-pick span {
  display: block;
  margin-top: 1px;
  color: var(--ink-3);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.01em;
}

/* The assistant's anatomy marks, listed beside the colours it used on the body.
   The swatch is the join between the word and the structure -- a list of names
   alone says nothing about which one is which colour. */
.mark-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }
.mark-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px 4px 8px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--panel-2);
  font-size: 12px;
  font-weight: 550;
  color: var(--ink-2);
}
.act-btn.sm { padding: 5px 11px; font-size: 12px; }

.settings { width: 292px; max-height: 460px; }
.set-body { overflow-y: auto; scrollbar-width: thin; padding: 12px 13px 14px; display: flex; flex-direction: column; gap: 14px; }
.set-sec { display: flex; flex-direction: column; gap: 7px; }
.set-sec h4 {
  margin: 0;
  font-size: 10.5px;
  font-weight: 650;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.set-facts { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 3px 12px; font-size: 12.5px; }
.set-facts dt { color: var(--ink-3); }
.set-facts dd { margin: 0; color: var(--ink); text-align: right; }

/* A small menu hung off an icon button. */
.menu-wrap { position: relative; display: inline-flex; }
.menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 30;
  min-width: 184px;
  padding: 5px;
  border: 1px solid var(--line);
  border-radius: 11px;
  background: var(--panel);
  box-shadow: var(--shadow-2);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.menu[hidden] { display: none; }
.menu button {
  padding: 7px 10px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--ink-2);
  font: inherit;
  font-size: 12.5px;
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
}
.menu button:hover { background: var(--panel-2); color: var(--ink); }

/* Pinned. The block is lifted out of source order rather than moved in the DOM,
   so nothing that reads the panel by position has to know about it. */
.detail-body.has-pin { display: flex; flex-direction: column; }
.block.is-pinned { order: -1; }
#ov-pin[aria-pressed="true"] { background: var(--accent-bg); color: var(--accent-ink); }

/* ------------------------------------------------------------ the calendar */

.appts { display: flex; flex-direction: column; min-height: 0; }
.appt-seg { position: static; transform: none; margin: 0 auto 0 18px; }
.appt-pane { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.appt-pane[hidden] { display: none; }

/* An honest empty pane: a slot that says what is coming, not a blank box that
   reads as a failed fetch. */
.slot-note {
  margin: auto;
  max-width: 420px;
  padding: 26px 28px;
  text-align: center;
  border: 1.5px dashed var(--accent-line);
  border-radius: 18px;
  background: var(--accent-bg);
}
.slot-note b { display: block; font-size: 16px; font-weight: 600; margin-bottom: 7px; }
.slot-note p { margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--ink-2); }
.slot-note code { font-size: 12.5px; padding: 1px 4px; border-radius: 5px; background: var(--panel-2); }

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

.cal-week {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 10px;
  padding: 4px 2px 2px;
  overflow-y: auto;
  scrollbar-width: thin;
  align-items: start;
}

.cal-day {
  min-width: 0;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line-soft);
  border-radius: 13px;
  background: var(--panel-2);
  overflow: hidden;
}
.cal-day.is-today { border-color: var(--accent-line); background: var(--accent-bg); }

.cal-day-head {
  display: flex;
  align-items: baseline;
  gap: 7px;
  padding: 9px 11px 8px;
  border-bottom: 1px solid var(--line-soft);
}
.cal-day-head b {
  font-size: 10.5px;
  font-weight: 650;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.cal-date { font-size: 16px; font-weight: 600; font-variant-numeric: tabular-nums; }
.cal-day.is-today .cal-date { color: var(--accent-ink); }
/* The count sits right, so the eye can run down the row of columns and see
   which day is heavy without reading any of them. */
.cal-n {
  margin-left: auto;
  font-style: normal;
  font-size: 11px;
  font-weight: 600;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

.cal-list { display: flex; flex-direction: column; gap: 6px; padding: 8px; }
.cal-none {
  margin: 0;
  padding: 8px 3px 10px;
  text-align: center;
  font-size: 11.5px;
  color: var(--ink-3);
}

/* A booking. Room now for all four things a diary row is asked: when, who,
   what, where. */
.cal-ev {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 9px;
  border: 1px solid var(--line-soft);
  border-left: 3px solid var(--accent);
  border-radius: 9px;
  background: var(--panel);
  color: var(--ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color 120ms ease-out, transform 120ms ease-out;
}
.cal-ev:hover { border-color: var(--accent-line); transform: translateY(-1px); }
.cal-ev:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.cal-ev-top { display: flex; align-items: baseline; gap: 6px; }
.cal-ev time {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--accent-ink);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.cal-tag {
  margin-left: auto;
  font-style: normal;
  font-size: 9.5px;
  font-weight: 650;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-3);
  white-space: nowrap;
}
.cal-ev b {
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.25;
  overflow-wrap: anywhere;
}
.cal-ev span { font-size: 11px; color: var(--ink-3); line-height: 1.3; overflow-wrap: anywhere; }

/* Status in the rail, because the fill already says "a booking" and a whole
   card that changes colour reads as a different kind of thing. */
.cal-ev.is-completed { border-left-color: var(--ok); }
.cal-ev.is-confirmed { border-left-color: var(--ok); }
.cal-ev.is-no_show   { border-left-color: var(--bad); }
.cal-ev.is-cancelled { border-left-color: var(--ink-3); opacity: 0.6; }
.cal-ev.is-cancelled b { text-decoration: line-through; }
.cal-ev.is-checked_in, .cal-ev.is-in_progress { border-left-color: var(--warn); }

/* Seven columns need about 1100px to hold a name. Below that the week wraps to
   a grid of days rather than shrinking each one past legibility. */
@media (max-width: 1180px) {
  .cal-week { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (max-width: 820px) {
  .cal-week { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ------------------------------------------------ the WhatsApp link + chats */

.wa-state { display: flex; align-items: center; gap: 7px; font-size: 12.5px; }
.wa-state b { font-weight: 600; }
.wa-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--ink-3); flex: 0 0 auto; }
.wa-dot.is-linked { background: var(--ok); }
.wa-dot.is-pairing { background: var(--warn); }
.wa-dot.is-failed, .wa-dot.is-logged_out { background: var(--bad); }

/* A white quiet zone is part of how a QR decodes, so the image keeps its own
   ground in both themes rather than inheriting the panel's. */
.wa-qr {
  display: block;
  width: 100%;
  max-width: 220px;
  margin: 4px auto 2px;
  border-radius: 10px;
  background: #fff;
  padding: 8px;
}

/* Issued once and never retrievable, so it gets room to be read and copied
   rather than being tucked into a note nobody notices. */
.wa-secret {
  margin: 8px 0 4px;
  padding: 10px 11px;
  display: flex;
  flex-direction: column;
  gap: 7px;
  border: 1px solid var(--warn);
  border-radius: 11px;
  background: var(--warn-bg);
}
.wa-secret b { font-size: 11px; font-weight: 650; letter-spacing: 0.06em; text-transform: uppercase; color: var(--warn); }
.wa-secret code {
  font-size: 11.5px;
  line-height: 1.4;
  overflow-wrap: anywhere;
  padding: 7px 8px;
  border-radius: 7px;
  background: var(--panel);
  border: 1px solid var(--line);
  user-select: all;
}

/* Urgents. Loud enough to be found, not so loud the list stops meaning
   anything when there are four of them. */
.urgent-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding: 4px 2px;
}
.urgent {
  padding: 12px 14px;
  border: 1px solid var(--bad-line);
  border-left: 4px solid var(--bad);
  border-radius: 12px;
  background: var(--bad-bg);
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.urgent-top { display: flex; align-items: baseline; gap: 9px; }
.urgent-top b { font-size: 14px; font-weight: 600; }
.urgent-top time { margin-left: auto; font-size: 11px; color: var(--ink-3); }
.urgent-tag {
  font-style: normal;
  font-size: 10px;
  font-weight: 650;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--bad-ink);
}
.urgent-why { margin: 0; font-size: 12.5px; color: var(--ink-2); }
/* What they actually said, in their words. */
.urgent-said { margin: 0; font-size: 12.5px; font-style: italic; color: var(--ink); }

/* The reply box. */
.chat-send { display: flex; gap: 8px; padding: 10px 12px; border-top: 1px solid var(--line-soft); }
.chat-send input {
  flex: 1;
  min-width: 0;
  padding: 9px 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--field);
  color: var(--ink);
  font: inherit;
  font-size: 13px;
}
.chat-send input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.chats { flex-direction: row; gap: 12px; min-height: 0; }
.chat-list {
  flex: 0 0 268px;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 2px;
}
.chat-row {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 9px 11px;
  border: 1px solid var(--line-soft);
  border-radius: 11px;
  background: var(--panel-2);
  color: var(--ink-2);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.chat-row:hover { background: var(--panel-3); }
.chat-row.is-open { border-color: var(--accent-line); background: var(--accent-bg); }
.chat-row-top { display: flex; align-items: baseline; gap: 8px; }
.chat-row b { font-size: 13px; font-weight: 600; color: var(--ink); }
.chat-unread {
  margin-left: auto;
  font-style: normal;
  min-width: 17px;
  padding: 1px 5px;
  border-radius: 999px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 10.5px;
  font-weight: 700;
  text-align: center;
}
.chat-who { font-size: 11px; color: var(--ink-3); }
.chat-snip {
  font-size: 12px;
  color: var(--ink-3);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.chat-row time { font-size: 10.5px; color: var(--ink-3); }

.chat-thread {
  flex: 1;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line-soft);
  border-radius: 13px;
  background: var(--panel-2);
  overflow: hidden;
}
.chat-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 11px 14px;
  border-bottom: 1px solid var(--line-soft);
}
.chat-head b { font-size: 14px; font-weight: 600; }
.chat-head span { font-size: 11.5px; color: var(--ink-3); }
.chat-head .ghost { margin-left: auto; }

.chat-log {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 13px;
}
/* Theirs left, ours right — the arrangement every messaging app has trained
   everyone on, so which side said what needs no legend. */
.chat-msg { max-width: 76%; display: flex; flex-direction: column; gap: 2px; }
.chat-msg.is-inbound { align-self: flex-start; }
.chat-msg.is-outbound { align-self: flex-end; align-items: flex-end; }
.chat-msg p {
  margin: 0;
  padding: 8px 11px;
  border-radius: 13px;
  font-size: 13px;
  line-height: 1.45;
  overflow-wrap: anywhere;
}
.chat-msg.is-inbound p { background: var(--panel); border: 1px solid var(--line-soft); border-bottom-left-radius: 5px; }
.chat-msg.is-outbound p { background: var(--accent); color: var(--on-accent); border-bottom-right-radius: 5px; }
.chat-msg time { font-size: 10.5px; color: var(--ink-3); padding: 0 3px; }

@media (max-width: 1080px) {
  .chats { flex-direction: column; }
  .chat-list { flex: 0 0 auto; max-height: 190px; }
}

/* ------------------------------------------------------------- the bell */

.bell-wrap { position: relative; }

/* The unread count. Sits on the bell rather than beside it, because the header
   is a fixed row and a badge that changes the button's width shifts everything
   after it every time one is read. */
.bell-dot {
  position: absolute;
  top: -2px; right: -2px;
  min-width: 16px; height: 16px;
  padding: 0 4px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  background: var(--bad);
  color: var(--on-accent);
  font-size: 10px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.bell-dot[hidden] { display: none; }

.alerts {
  position: absolute;
  top: calc(100% + 9px);
  right: 0;
  z-index: 40;
  width: 320px;
  max-height: 380px;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--panel);
  box-shadow: var(--shadow-2);
  overflow: hidden;
}
.alerts[hidden] { display: none; }

.alerts-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 11px 13px;
  border-bottom: 1px solid var(--line-soft);
}
.alerts-top b { font-size: 13px; font-weight: 650; }

.alerts-list { overflow-y: auto; scrollbar-width: thin; padding: 6px; }

.alert {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 9px 10px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: var(--ink-2);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.alert:hover { background: var(--panel-2); }
.alert b { font-size: 12.5px; font-weight: 600; color: var(--ink); }
.alert-body { font-size: 12px; line-height: 1.42; color: var(--ink-3); }
.alert time { font-size: 11px; color: var(--ink-3); }

/* Unread. A dot rather than a bolder weight: the subject is already bold, and
   two levels of bold in a 320px column stops meaning anything. */
.alert.is-new { position: relative; padding-left: 20px; }
.alert.is-new::before {
  content: "";
  position: absolute;
  left: 8px; top: 14px;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent);
}

/* The assistant's example questions. Phrasings, not commands: what a clinician
   needs to learn is how to ask, and the model picks the tool from that. */
.ask-quick { display: flex; flex-direction: column; gap: 5px; margin-top: 14px; width: 100%; }
.ask-group { display: flex; flex-direction: column; gap: 5px; margin-top: 10px; }
.ask-group h5 {
  margin: 0 0 1px;
  font-size: 10px;
  font-weight: 650;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.ask-eg {
  width: 100%;
  padding: 7px 11px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--panel-2);
  color: var(--ink-2);
  font: inherit;
  font-size: 12.5px;
  line-height: 1.35;
  text-align: left;
  cursor: pointer;
  transition: background 120ms ease-out, color 120ms ease-out, border-color 120ms ease-out;
}
.ask-eg:hover { background: var(--accent-bg); border-color: var(--accent-line); color: var(--accent-ink); }
.ask-eg:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ask-help .act-top b { font-size: 13px; }

.mark-dot {
  width: 9px; height: 9px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgb(var(--shadow-rgb) / 0.18);
}

/* ---------------------------------------------------------------- dark mode
 *
 * PRODUCT.md carried "Light is built; dark is owed" for a day. This is the
 * debt. The room's light changes through the day and the clinician does not
 * get to choose it, so the product follows the system unless they say
 * otherwise.
 *
 * Three states, not two. An explicit choice stamps data-theme on the root; the
 * default "system" setting stamps nothing, and only prefers-color-scheme
 * separates light from dark there. So the dark values are declared TWICE --
 * once under the media query, guarded so an explicit light choice still beats
 * a dark OS, and once under the attribute so the toggle wins in both
 * directions. Nothing below redefines a component, only tokens: a colour whose
 * only definition sits inside one of these blocks is a colour that vanishes in
 * the third state.
 *
 * Every text pair here was measured, not eyeballed. The tightest is --ink-3 on
 * --panel-2 at 5.0:1.
 *
 * One thing worth saying out loud: #7c6cf0, the original brand purple, was
 * demoted to #5d4ee0 because it is 3.3:1 on white and could not legally hold
 * button text. That constraint is a LIGHT-ground constraint. Here the fill can
 * move back toward the brand -- and the hover goes deeper rather than
 * brighter, because on a dark ground a lighter hover is where white text goes
 * to die (4.2:1 measured, against 6.1:1 for the deeper one).
 */
:root:not([data-theme="light"]) {
  @media (prefers-color-scheme: dark) {
    color-scheme: dark;
    accent-color: #7c6cf0;

    --void:        #08070d;
    --ground:      #14121d;
    --panel:       #1c1a28;
    --panel-2:     #23202f;
    --panel-3:     #2c2839;
    --on-accent:   #fbfaff;
    --film-bed:    #0a0910;   /* a radiograph wants the darkest ground there is */
    --field:       #232030;
    --suggest-bg:  #262234;
    --line:        #332e45;
    --line-soft:   #292538;

    --ink:         #f1eff8;
    --ink-2:       #bcb6ce;
    --ink-3:       #948da9;
    --ink-4:       #8f88a6;

    --accent:      #6355e4;
    --accent-hi:   #574ad0;   /* deeper on hover, not brighter -- see above */
    --accent-ink:  #a99bff;
    --accent-bg:   #241f3d;
    --accent-line: #3d3465;
    --accent-deep: #c9bcff;
    --accent-2:    #9b8cf5;
    --accent-3:    #6f61c9;

    --ok:          #54cfa0;
    --ok-bg:       #10281f;
    --ok-line:     #1f5040;
    --warn:        #e5a95c;
    --warn-bg:     #2c2010;
    --info-ink:    #84b8f2;
    --info-bg:     #111f38;
    --bad-ink:     #ff92aa;
    --bad-bg:      #2d1019;
    --bad-line:    #4f2030;
    --bad:         #f2597c;

    --scroll:      #3b3550;
    --panel-a:     rgba(28, 26, 40, 0.88);
    --stage-hi:    #262138;
    --stripe-a:    #201d2c;
    --stripe-b:    #262233;
    --bed-1:       #14121f;
    --bed-2:       #1a1727;
    --bed-3:       #201c2e;

    /* Shadows stop being a tint and become an absence of light. */
    --shadow-rgb:  0 0 0;
    --accent-rgb:  124 108 240;
    --shadow-1:
      0 1px 2px rgba(0, 0, 0, 0.40),
      0 10px 22px -10px rgba(0, 0, 0, 0.60);
    --shadow-2:
      0 2px 4px rgba(0, 0, 0, 0.44),
      0 18px 36px -14px rgba(0, 0, 0, 0.60),
      0 44px 72px -40px rgba(0, 0, 0, 0.56);
  }
}

/* The toggle, in both directions. Same tokens; see the note above. */
:root[data-theme="dark"] {
  color-scheme: dark;
  accent-color: #7c6cf0;

  --void:        #08070d;
  --ground:      #14121d;
  --panel:       #1c1a28;
  --panel-2:     #23202f;
  --panel-3:     #2c2839;
  --on-accent:   #fbfaff;
  --film-bed:    #0a0910;   /* a radiograph wants the darkest ground there is */
  --field:       #232030;
  --suggest-bg:  #262234;
  --line:        #332e45;
  --line-soft:   #292538;

  --ink:         #f1eff8;
  --ink-2:       #bcb6ce;
  --ink-3:       #948da9;
  --ink-4:       #8f88a6;

  --accent:      #6355e4;
  --accent-hi:   #574ad0;   /* deeper on hover, not brighter -- see above */
  --accent-ink:  #a99bff;
  --accent-bg:   #241f3d;
  --accent-line: #3d3465;
  --accent-deep: #c9bcff;
  --accent-2:    #9b8cf5;
  --accent-3:    #6f61c9;

  --ok:          #54cfa0;
  --ok-bg:       #10281f;
  --ok-line:     #1f5040;
  --warn:        #e5a95c;
  --warn-bg:     #2c2010;
  --info-ink:    #84b8f2;
  --info-bg:     #111f38;
  --bad-ink:     #ff92aa;
  --bad-bg:      #2d1019;
  --bad-line:    #4f2030;
  --bad:         #f2597c;

  --scroll:      #3b3550;
  --panel-a:     rgba(28, 26, 40, 0.88);
  --stage-hi:    #262138;
  --stripe-a:    #201d2c;
  --stripe-b:    #262233;
  --bed-1:       #14121f;
  --bed-2:       #1a1727;
  --bed-3:       #201c2e;

  /* Shadows stop being a tint and become an absence of light. */
  --shadow-rgb:  0 0 0;
  --accent-rgb:  124 108 240;
  --shadow-1:
    0 1px 2px rgba(0, 0, 0, 0.40),
    0 10px 22px -10px rgba(0, 0, 0, 0.60);
  --shadow-2:
    0 2px 4px rgba(0, 0, 0, 0.44),
    0 18px 36px -14px rgba(0, 0, 0, 0.60),
    0 44px 72px -40px rgba(0, 0, 0, 0.56);
}

/* ------------------------------------------------- the model control panel */

.round.tl2 { position: absolute; top: 132px; left: 16px; z-index: 4; }

/* Everything the clinician can do to the model. Sits over the stage rather than
   beside it: the three columns of Overview are already spoken for, and a
   control for the thing you are looking at belongs on top of it. */
.model-panel {
  position: absolute;
  top: 84px;
  left: 68px;
  z-index: 5;
  width: 236px;
  max-height: calc(100% - 116px);
  overflow-y: auto;
  scrollbar-width: thin;
  padding: 14px 15px 16px;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--panel);
  box-shadow: 0 20px 44px -20px rgb(var(--shadow-rgb) / 0.55);
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.model-panel[hidden] { display: none; }

.mp-head { display: flex; align-items: center; justify-content: space-between; }
.mp-head b { font-size: 14px; font-weight: 650; letter-spacing: -0.01em; }

.mp-sec { display: flex; flex-direction: column; gap: 7px; }
.mp-sec h4 {
  margin: 0;
  font-size: 10.5px;
  font-weight: 650;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.mp-row { display: flex; flex-wrap: wrap; gap: 6px; }
.mp-col { flex-direction: column; flex-wrap: nowrap; }

.mp-btn {
  flex: 1 1 auto;
  min-height: 30px;
  padding: 6px 11px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--panel-2);
  color: var(--ink-2);
  font: inherit;
  font-size: 12.5px;
  font-weight: 550;
  text-align: center;
  cursor: pointer;
  transition: background 120ms ease-out, color 120ms ease-out, border-color 120ms ease-out;
}
.mp-btn:hover:not(:disabled) { background: var(--panel-3); color: var(--ink); }
.mp-btn[aria-pressed="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}
.mp-btn[aria-pressed="true"]:hover { background: var(--accent-hi); color: var(--on-accent); }
/* A layer this atlas does not carry. Disabled and labelled, not hidden: the
   skeleton holds no vessels, and saying so beats a button that does nothing. */
.mp-btn:disabled { opacity: 0.4; cursor: default; }
.mp-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* The named tissue rows, which carry a count. */
.mp-wide { display: flex; align-items: center; justify-content: space-between; gap: 8px; text-align: left; }
.mp-count {
  font-style: normal;
  font-size: 11px;
  font-weight: 500;
  opacity: 0.72;
  font-variant-numeric: tabular-nums;
}

.mp-note { margin: 0; font-size: 11.5px; line-height: 1.45; color: var(--ink-3); }

/* Fullscreen. The stage becomes the window, so the panel ground has to be
   painted -- a transparent stage in fullscreen shows the browser's black. */
.stage.is-full { border-radius: 0; border: 0; background: var(--panel); }
.stage.is-full .model { padding: 0; }

@media (max-width: 1180px) {
  .model-panel { left: 16px; top: 132px; width: 214px; }
  .round.tl2 { top: 84px; left: 64px; }
}


/* The hotspot cluster. In the mockup these sit on the body; until the model
   lands they hold their place at the right edge of the stage. */
.hotspots {
  position: absolute;
  right: 22px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
  display: flex;
  flex-direction: column;
  gap: 11px;
}
.hot {
  width: 44px; height: 44px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  cursor: pointer;
  box-shadow: 0 6px 18px -6px rgb(var(--accent-rgb) / 0.55);
  transition: transform 130ms ease-out, background 130ms ease-out;
}
.hot:hover { background: var(--accent-hi); transform: translateY(-1px); }
.hot svg { width: 20px; height: 20px; }
/* A layer switched off. Muted, not removed: the cluster has to keep saying
   which layers exist, not only which are showing. */
.hot[aria-pressed="false"] {
  background: var(--panel);
  color: var(--ink-3);
  box-shadow: 0 0 0 1.5px var(--line), 0 4px 12px -9px rgb(var(--shadow-rgb) / 0.55);
}
.hot[aria-pressed="false"]:hover { background: var(--panel-3); color: var(--ink-2); }
.hot:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
/* Before the geometry is up there is nothing to switch. */
.hot:disabled { opacity: 0.45; cursor: default; }
.hot:disabled:hover { background: var(--accent); transform: none; }

/* -------------------------------------------------------- the right panel */

.col-right {
  box-shadow: var(--shadow-1);
  padding: 18px;
  border-radius: 18px;
  background: var(--panel);
  border: 1px solid var(--line-soft);
  gap: 0;
  overflow: hidden;          /* the body scrolls, not the panel */
}
.detail-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--scroll) transparent;
}
.detail-top, .add-entry { flex: none; }
.col-right[hidden] { display: none; }

.detail-top { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
.detail-top h2 {
  margin: 0;
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.02em;
}
.sentence::first-letter { text-transform: uppercase; }
.detail-top .icon-btn { margin-left: auto; background: transparent; }
.detail-top .icon-btn:hover { background: var(--panel-2); }

.detail-body { display: flex; flex-direction: column; gap: 14px; }

.block { padding: 15px; border-radius: 15px; background: var(--panel-2); }
.block-top { display: flex; align-items: center; gap: 4px; margin-bottom: 10px; }
.block-top h3 { margin: 0; flex: 1; font-size: 15.5px; font-weight: 600; letter-spacing: -0.01em; }

.block p { margin: 0 0 10px; font-size: 13.5px; color: var(--ink-2); line-height: 1.55; }
.block p:last-child { margin-bottom: 0; }

.detail-field { margin-bottom: 13px; }
.detail-field:last-child { margin-bottom: 0; }
.detail-field b { display: block; font-size: 13.5px; font-weight: 500; margin-bottom: 3px; }
.detail-field span { font-size: 13.5px; color: var(--ink-2); line-height: 1.5; }

/* Severity as a segmented meter: a clinician reads a count of filled blocks
   faster than a percentage, and the number is beside it either way. */
.sev-top { display: flex; align-items: baseline; gap: 10px; margin-bottom: 8px; }
.sev-top b { font-size: 13.5px; font-weight: 500; }
.sev-top span { margin-left: auto; font-size: 13.5px; font-variant-numeric: tabular-nums; color: var(--ink-2); }
.sev { display: flex; gap: 3px; }
.sev i {
  flex: 1;
  height: 9px;
  border-radius: 3px;
  background: var(--panel-3);
}
.sev i.on { background: var(--accent); }
.sev i.on.hot { background: var(--warn); }

.film { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 4px; scrollbar-width: thin; }
/* The strip used to hold four "no study" placards. It holds real thumbnails
 * now, so the tile has to behave as a button and letterbox the image -- the
 * striped ground stays as the empty state underneath. */
.film-shot:is(button) { cursor: zoom-in; padding: 0; overflow: hidden; }
.film-shot img { width: 100%; height: 100%; object-fit: contain; background: var(--film-bed); }
.film-shot:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.film-shot {
  flex: none;
  width: 74px;
  aspect-ratio: 3 / 4;
  border-radius: 9px;
  border: 1px solid var(--line);
  background: repeating-linear-gradient(115deg, var(--stripe-a) 0 6px, var(--stripe-b) 6px 12px);
  display: grid;
  place-items: center;
  color: var(--ink-3);
  font-size: 10.5px;
  text-align: center;
  padding: 6px;
}

.add-entry {
  margin-top: 14px;
  width: 100%;
  padding: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 1px solid var(--accent-line);
  border-radius: 13px;
  background: var(--accent-bg);
  color: var(--accent-ink);
  font: inherit;
  font-size: 14.5px;
  font-weight: 500;
  cursor: pointer;
  transition: background 130ms ease-out;
}
.add-entry:hover { background: var(--panel-3); }
.add-entry svg { width: 17px; height: 17px; }


/* ------------------------------------------- single-column views */

/* Appointments and Database are one wide card rather than three columns: both
   are lists you scan down, and squeezing them into the Overview grid would
   make a table read as a sidebar. */
.workspace.single { grid-template-columns: minmax(0, 1fr); }

.card.wide {
  box-shadow: var(--shadow-1);
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: 18px;
  border-radius: 18px;
  background: var(--panel);
  border: 1px solid var(--line-soft);
}
.card.wide .card-top { flex: none; }
.card-top .meta { color: var(--ink-3); font-size: 13px; }

.ghost.sm { padding: 7px 12px; font-size: 13px; border-radius: 9px; }
.flip { transform: rotate(180deg); }

/* An author class with `display` beats the UA's [hidden] rule at equal
   specificity, so `el.hidden = true` on one of these renders as nothing at
   all. Third time in this sheet; stated wherever it applies. */
.daynav[hidden] { display: none; }
.daynav { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.daynav b { min-width: 168px; text-align: center; font-size: 14.5px; font-weight: 500; }
.daynav .icon-btn { background: var(--panel-2); }

/* The diary. A time gutter with the booked slots against it, and the gaps
   drawn as gaps -- availability the schedule rules have not confirmed is a
   booking bug waiting to happen, so these are labelled for what they are. */
.diary {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--scroll) transparent;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-right: 4px;
}
.slot-row {
  display: grid;
  grid-template-columns: 74px minmax(0, 1fr) auto;
  align-items: center;
  gap: 16px;
  padding: 14px 16px;
  border-radius: 13px;
  background: var(--panel-2);
  border: 1px solid transparent;
}
.slot-row .t {
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
  font-size: 14px;
}
.slot-who { display: flex; align-items: center; gap: 11px; min-width: 0; }
.slot-who b { font-size: 15px; font-weight: 500; letter-spacing: -0.01em; }
.slot-who .mrn { color: var(--ink-3); font-size: 12.5px; }
.slot-kind {
  padding: 4px 11px;
  border-radius: 999px;
  background: var(--accent-bg);
  color: var(--accent-ink);
  font-size: 12.5px;
  white-space: nowrap;
}
.slot-row.gap {
  background: transparent;
  border-color: var(--line-soft);
  border-style: dashed;
}
.slot-row.gap .slot-who b { color: var(--ink-3); font-weight: 400; }
.slot-reason { color: var(--ink-3); font-size: 13px; }

/* ------------------------------------------------------------- the table */

.table-wrap {
  flex: 1;
  min-height: 0;
  overflow: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--scroll) transparent;
}
.table { width: 100%; border-collapse: collapse; font-size: 14.5px; }
.table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--panel);
  padding: 10px 14px;
  text-align: left;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-3);
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.table tbody tr { border-bottom: 1px solid var(--line-soft); cursor: pointer; }
.table tbody tr:hover { background: var(--panel-2); }
.table tbody tr:last-child { border-bottom: 0; }
.table td { padding: 12px 14px; vertical-align: middle; }
.table .who { display: flex; align-items: center; gap: 11px; min-width: 0; }
.table .who b { font-weight: 500; letter-spacing: -0.01em; }
.table .num { font-variant-numeric: tabular-nums; color: var(--ink-2); }
.table .go { width: 34px; text-align: right; color: var(--ink-3); }
.table .go svg { width: 16px; height: 16px; }

.pill {
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 12px;
  background: var(--panel-3);
  color: var(--ink-2);
  white-space: nowrap;
}
.pill.ok { background: var(--ok-bg); color: var(--ok); }

#db-new { margin-left: auto; }
.db-search { margin-left: 10px; }
.db-search input { width: 260px; }

/* -------------------------------------------------- the stage's SOAP tabs */

/* The four stage tabs were decorative. They now read the encounter's own SOAP
   note, so Intake / Assessment / Diagnosis / Plan show what was actually
   written under each -- and say plainly when a section is empty. */
.soap {
  position: absolute;
  /* clears the zoom column, which shares this corner */
  left: 70px; right: 16px; bottom: 16px;
  z-index: 2;
  max-height: 38%;
  overflow-y: auto;
  scrollbar-width: thin;
  padding: 15px 17px;
  border-radius: 15px;
  background: var(--panel-a);
  backdrop-filter: blur(14px);
  border: 1px solid var(--line);
}
.soap h4 {
  margin: 0 0 6px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.soap p { margin: 0; font-size: 14px; color: var(--ink-2); line-height: 1.55; }
.soap .dx { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 4px; }
.soap .dx span {
  padding: 5px 11px;
  border-radius: 999px;
  background: var(--accent-bg);
  color: var(--accent-ink);
  font-size: 13px;
}
.soap .dx span code {
  font-family: ui-monospace, Menlo, monospace;
  font-size: 11.5px;
  opacity: 0.75;
  margin-right: 5px;
}

/* ------------------------------------------------------------- home view */

.workspace.home { grid-template-columns: minmax(0, 1fr); }
.workspace.home .stage-head { display: flex; align-items: center; gap: 16px; margin-bottom: 4px; }
.stage-head .spacer { flex: 1; }

.crumbs {
  margin: 0;
  font-size: 21px;
  font-weight: 600;
  letter-spacing: -0.015em;
  display: flex;
  align-items: baseline;
  gap: 11px;
  min-width: 0;
}
.crumbs .sep { color: var(--ink-3); font-weight: 400; }
.crumb-current { color: var(--ink-2); font-weight: 400; }

.search input {
  width: 320px;
  max-width: 40vw;
  padding: 10px 15px;
  border-radius: 11px;
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--ink);
  font: inherit;
}
.search input::placeholder { color: var(--ink-3); }
.search input:focus { border-color: var(--accent-line); outline-offset: 1px; }

/* ------------------------------------------------------------------ cards */

.board {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-auto-rows: minmax(0, 1fr);
  gap: 22px;
  flex: 1;
  min-height: 0;
}
.board[hidden] { display: none; }

.pane { flex: 1; min-height: 0; display: flex; }
.pane[hidden] { display: none; }

.card {
  background: var(--card);
  border: 1px solid var(--line-soft);
  border-radius: var(--r);
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

.card-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 17px 20px 14px;
}
.card-head h2 {
  margin: 0;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.card-head .meta { margin-left: auto; color: var(--ink-3); font-size: 13px; }

.card-body { padding: 0 14px 14px; overflow: hidden; min-height: 0; }
.card-body.scroll {
  overflow-y: auto;
  /* The default dark scrollbar is a wide light-grey slab against near-black
     cards. Thin, tinted to the card, so it reads as an affordance and not as
     a column of content. */
  scrollbar-width: thin;
  scrollbar-color: var(--scroll) transparent;
}

.card-foot {
  margin: 0;
  padding: 12px 20px 16px;
  border-top: 1px solid var(--line-soft);
  color: var(--ink-3);
  font-size: 12px;
}

.empty { padding: 28px 8px; color: var(--ink-3); }
.empty p { margin: 0 0 6px; }

/* ---------------------------------------------------------- patient rows */

.row {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  padding: 12px 14px;
  border: 0;
  border-left: 3px solid transparent;
  border-radius: var(--r-sm);
  background: transparent;
  text-align: left;
  cursor: pointer;
  color: inherit;
}
.row:hover { background: var(--card-2); }

.row.is-active {
  background: var(--accent-bg);
  border-left-color: var(--accent);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
}

.row-text { min-width: 0; }
.row-name { font-size: 16px; font-weight: 500; letter-spacing: -0.01em; }
.row-sub { color: var(--ink-3); font-size: 13px; }

/* -------------------------------------------------------------- schedule */

.slot {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 13px 16px;
  margin-bottom: 8px;
  border-radius: var(--r-sm);
  border: 1px solid transparent;
  background: var(--accent-bg);
}
.slot-time { color: var(--ink-2); font-variant-numeric: tabular-nums; flex: none; }
.slot-name { font-weight: 500; }
.slot-kind { margin-left: auto; color: var(--accent-dim); font-size: 14px; }

.slot.is-free {
  background: transparent;
  border-color: var(--line-soft);
}
.slot.is-free .slot-name { color: var(--ink-3); font-weight: 400; }

/* -------------------------------------------------------------- messages */

.msg {
  padding: 14px 16px;
  margin-bottom: 10px;
  border-radius: var(--r-sm);
  background: var(--card-2);
}
.msg-top { display: flex; align-items: center; gap: 12px; }
.msg-top b { font-weight: 500; }
.msg-body { color: var(--ink-2); margin-top: 4px; }

.pill {
  margin-left: auto;
  padding: 3px 11px;
  border-radius: 999px;
  border: 1px solid var(--accent-line);
  color: var(--accent-dim);
  font-size: 12px;
  flex: none;
}

/* ---------------------------------------------------------------- visits */

.visit { display: flex; gap: 18px; padding: 10px 6px 16px; }
.visit-date {
  flex: none;
  width: 56px;
  color: var(--ink-3);
  font-size: 13px;
  padding-top: 2px;
  font-variant-numeric: tabular-nums;
}
.visit-title { font-size: 16px; font-weight: 500; letter-spacing: -0.01em; }
.visit-body { color: var(--ink-2); margin-top: 2px; }

/* --------------------------------------------------------------- imaging */

.tiles {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
  padding: 4px 6px;
}
.tile figcaption {
  margin-top: 8px;
  color: var(--ink-2);
  font-size: 13px;
  line-height: 1.35;
}

/* A study nobody has clicked is a rectangle of grey; drawing it as one is
   honest. The radial is what a thumbnail looks like before it loads, not a
   pretend scan -- an invented image on a chart is a different kind of lie. */
.tile-frame {
  aspect-ratio: 4 / 3;
  border-radius: 10px;
  background:
    radial-gradient(ellipse at 50% 45%, var(--bed-1) 0%, var(--bed-2) 55%, var(--bed-3) 100%);
  display: grid;
  place-content: center;
  gap: 4px;
  text-align: center;
  padding: 8px;
}
.tile-value {
  font-size: 19px;
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.015em;
  font-variant-numeric: tabular-nums;
}
.tile-unit { font-size: 11px; color: var(--ink-2); }
.tile-flag {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--warn);
}

#summary-body .ghost { margin: 16px 6px 4px; }

/* --------------------------------------------------------------- summary */

.summary-lead { color: var(--accent-dim); margin: 6px 6px 18px; }
.summary-list { list-style: none; margin: 0; padding: 0 6px; }
.summary-list li {
  position: relative;
  padding-left: 20px;
  margin-bottom: 9px;
  color: var(--ink-2);
}
.summary-list li::before {
  content: "";
  position: absolute;
  left: 4px; top: 0.62em;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--warn);
}

/* ------------------------------------------------------------- assistant */

/* Grows to fill the card so the composer sits at the bottom edge, where a chat
   input belongs, instead of floating under the last reply. */
/* The element is #ai-log with class "card-body scroll" -- this block was
   written as a CLASS selector and so has never matched anything. Everything
   below it assumed the flex column it declares: `gap` never applied, so
   messages had no spacing, and `.bubble.me { align-self: flex-end }` was inert,
   which is why the clinician's own question has never right-aligned. */
#ai-log {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 6px 6px 12px;
  min-height: 0;
}

.bubble {
  max-width: 68ch;
  padding: 11px 15px;
  border-radius: 12px;
  background: var(--panel-2);
  color: var(--ink-2);
  line-height: 1.55;
}
.bubble.me { align-self: flex-end; background: var(--accent); color: var(--on-accent); }
.bubble:not(.me):not(.tool) { align-self: flex-start; }
.bubble.tool { font-size: 12.5px; color: var(--ink-3); background: transparent; padding: 0 4px;
               font-variant-numeric: tabular-nums; }

/* The wordmark is the page's h1. Reset the user-agent heading box so it keeps
   sitting in the bar rather than pushing it open. */
h1.brand { margin: 0; font-size: inherit; font-weight: inherit; }

/* The composer wraps rather than overflowing. Below about 420px the clip, the
   input and Ask cannot share a line -- measured, the input pushed 78px and the
   button 149px past the panel, which is a broken composer, not a tight one. */
.ai-form { display: flex; flex-wrap: wrap; gap: 10px; padding: 12px 20px; border-top: 1px solid var(--line-soft); }
.ai-form input { min-width: 0; }
@media (max-width: 420px) {
  /* Input takes the full second row; the two buttons share the first. */
  .ai-form input { order: -1; flex: 1 0 100%; }
}
.ai-form input {
  flex: 1;
  padding: 11px 15px;
  border-radius: 10px;
  border: 1px solid var(--line);
  /* Not var(--ground): that is the darker lavender the panels sit on, and an
     input wearing it reads as disabled against a white card. */
  background: var(--field);
  color: var(--ink);
  transition: border-color 130ms ease-out, box-shadow 130ms ease-out;
}
.ai-form input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-bg);
}
.ai-form input::placeholder { color: var(--ink-4); }

/* --------------------------------------------------------------- buttons */

button {
  border-radius: 10px;
  cursor: pointer;
}

#signin-btn, #ai-send {
  padding: 11px 18px;
  border: 0;
  background: var(--accent);
  color: var(--on-accent);
  font-weight: 500;
}
#signin-btn:hover, #ai-send:hover { background: var(--accent-hi); }

.ghost {
  padding: 9px 14px;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--ink-2);
}
.ghost:hover { border-color: var(--accent-line); color: var(--ink); }
.ghost.small { padding: 6px 11px; font-size: 13px; }

/* --------------------------------------------------------------- sign in */

/* The sign-in keeps its own ground, one shade lighter than the shell's.
 *
 * This block predates the rest of the app being relit: the sign-in was light
 * while the board behind it was still dark, so every token was redeclared here
 * and nothing outside saw them. That relight has since happened, so the
 * light-to-dark cut this comment used to warn about is gone. What survives is
 * a deliberate difference in one value -- a sign-in with no shell around it
 * wants a lighter field than panels sitting ON a ground do.
 *
 * The accent moved for a measurable reason and stayed moved: #7c6cf0 on a
 * light ground is 3.3:1 and cannot legally hold white button text. Same hue,
 * darker. */
#signin {
  color-scheme: light;
  accent-color: #5d4ee0;

  --ground:      #e8e5f7;   /* the background colour, not an off-white */
  --card:        #faf9fe;
  --card-2:      #f0edfa;
  --line:        #ddd6f3;
  --line-soft:   #e7e2f7;

  --ink:         #1a1826;
  --ink-2:       #57526d;
  --ink-3:       #6f6987;

  --accent:      #5d4ee0;   /* fills; white on this is 5.8:1 */
  --accent-ink:  #5340cf;   /* the purple as text on white, 7.0:1 */
  --accent-bg:   #efecfd;
  --accent-line: #d5cdf6;

  background: var(--ground);
  color: var(--ink);
}

/* The sign-in screen re-declares its palette locally, which means the dark
   tokens at :root never reach it -- it would have stayed a white rectangle in
   an otherwise dark product, at the one moment the room is darkest. Same three
   states as the root block. */
#signin:where(:root:not([data-theme="light"]) *) {
  @media (prefers-color-scheme: dark) {
    color-scheme: dark;
    accent-color: #7c6cf0;
    --ground:      #100e18;
    --card:        #1c1a28;
    --card-2:      #23202f;
    --line:        #332e45;
    --line-soft:   #292538;
    --ink:         #f1eff8;
    --ink-2:       #bcb6ce;
    --ink-3:       #948da9;
    --accent:      #6355e4;
    --accent-ink:  #a99bff;
    --accent-bg:   #241f3d;
    --accent-line: #3d3465;
  }
}
:root[data-theme="dark"] #signin {
  color-scheme: dark;
  accent-color: #7c6cf0;
  --ground:      #100e18;
  --card:        #1c1a28;
  --card-2:      #23202f;
  --line:        #332e45;
  --line-soft:   #292538;
  --ink:         #f1eff8;
  --ink-2:       #bcb6ce;
  --ink-3:       #948da9;
  --accent:      #6355e4;
  --accent-ink:  #a99bff;
  --accent-bg:   #241f3d;
  --accent-line: #3d3465;
}

.centred { display: grid; place-items: center; padding: 40px 20px; }

.panel[hidden] { display: none; }
.panel {
  width: 100%;
  background: var(--card);
  border: 1px solid var(--line-soft);
  border-radius: var(--r);
  box-shadow: var(--shadow-2);
  padding: 28px 26px 24px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.panel.narrow { max-width: 392px; }
.panel h1 { margin: 0; font-size: 24px; font-weight: 600; letter-spacing: -0.02em; }
/* Same mark as the app shell, so sign-in is not a second logo. The base
   .mark / .mark-glyph rules went with the old rail, so both are declared
   here -- without flex:none the circle collapses to a sliver. */
.panel .mark {
  display: flex;
  align-items: center;
  gap: 11px;
}
.panel .mark b { font-size: 19px; font-weight: 600; letter-spacing: -0.015em; }

.panel .mark-glyph {
  flex: none;
  display: block;
  width: 26px; height: 26px;
  border: 0;
  border-radius: 50%;
  position: relative;
}
.panel .mark-glyph:not(.is-live) {
  overflow: hidden;
  background: var(--accent);
  box-shadow: 0 3px 10px -3px rgb(var(--accent-rgb) / 0.5);
}
.panel .mark-glyph::before {
  content: "";
  position: absolute;
  inset: -35%;
  background: conic-gradient(from 0deg,
    #4f3fd4, #7c6cf0, #a78bfa, #c46ff0, #7c6cf0, #5d4ee0, #4f3fd4);
  animation: mark-turn 9s linear infinite;
  will-change: transform;
}
.panel .mark-glyph::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background:
    radial-gradient(circle at 34% 26%, rgba(253,252,255,0.6), transparent 52%),
    radial-gradient(circle at 70% 82%, rgba(28,16,80,0.28), transparent 55%);
}
.panel .sub {
  margin: 5px 0 16px;
  display: flex;
  align-items: center;
  gap: 9px;
  flex-wrap: wrap;
  color: var(--ink-3);
  font-size: 13px;
}
.panel label { margin-top: 11px; font-size: 13px; color: var(--ink-2); }

.panel input {
  margin-top: 5px;
  padding: 11px 13px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--field);
  color: var(--ink);
  transition: border-color 130ms ease-out, box-shadow 130ms ease-out;
}
.panel input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-bg);
}
.panel input::placeholder { color: var(--ink-4); }

/* Chrome paints its own pale blue over an autofilled field and there is no
   property that overrides it -- the long-standing trick is an inset shadow
   large enough to cover the fill, with the caret and text colour set
   separately. Without this the one field a returning clinician actually uses
   is the only element on the screen wearing another design system's colour. */
.panel input:-webkit-autofill,
.panel input:-webkit-autofill:hover,
.panel input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--ink);
  -webkit-box-shadow: 0 0 0 100px var(--field) inset;
  box-shadow: 0 0 0 100px var(--field) inset;
  caret-color: var(--ink);
}
.panel input:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 100px var(--field) inset, 0 0 0 3px var(--accent-bg);
  box-shadow: 0 0 0 100px var(--field) inset, 0 0 0 3px var(--accent-bg);
}

.panel button { margin-top: 12px; }

#signin-btn { background: var(--accent); }
#signin-btn:hover { background: #4f3fd4; }
#signin-btn[disabled] { opacity: 0.55; cursor: default; }

#signin .ghost { color: var(--ink-2); border-color: var(--line); }
#signin .ghost:hover { border-color: var(--accent-line); color: var(--ink); }

#username-field { display: contents; }
#username-field[hidden] { display: none; }

/* The recognised clinician: a row that states a fact and gets out of the way
   of the one field still outstanding. */
.known {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 4px 0 6px;
  padding: 12px 13px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--card-2);
}
.known[hidden] { display: none; }
.known .avatar {
  background: var(--accent-bg);
  border: 1px solid var(--accent-line);
  color: var(--accent-deep);          /* one step darker than accent-ink for the initials */
  width: 38px; height: 38px;
  font-size: 13px;
}
.known-text { display: flex; flex-direction: column; min-width: 0; }
.known-text b { font-size: 15px; font-weight: 500; letter-spacing: -0.01em; }
.known-text span {
  color: var(--ink-3);
  font-size: 13px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.notyou {
  align-self: flex-start;
  margin-top: 12px;
  padding: 2px 0;
  border: 0;
  background: none;
  color: var(--ink-3);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--accent-line);
}
.notyou:hover { color: var(--accent-ink); text-decoration-color: var(--accent-ink); }
.notyou[hidden] { display: none; }

.tag {
  padding: 2px 9px;
  border-radius: 999px;
  border: 1px solid var(--accent-line);
  background: var(--accent-bg);
  color: var(--accent-ink);
  font-size: 12px;
  white-space: nowrap;
}

.error {
  margin: 12px 0 0;
  padding: 10px 13px;
  border-radius: var(--r-sm);
  background: var(--bad-bg);
  color: var(--bad-ink);
  font-size: 13.5px;
  line-height: 1.4;
}
.error[hidden] { display: none; }

.footnote { margin: 15px 0 0; color: var(--ink-3); font-size: 12px; }


/* An empty chat with nothing in it reads as broken. This says what the
   assistant can do and, just as importantly, what it may not touch. */
.ai-empty {
  margin: auto;
  max-width: 34ch;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 7px;
  color: var(--ink-3);
}
.ai-empty b { font-size: 15px; font-weight: 500; color: var(--ink-2); }
.ai-empty span { font-size: 13px; line-height: 1.5; }

/* ------------------------------------------------------------------- home */

/* Three panels of equal weight: what today holds, the assistant, and the shape
   of the practice's own data. Equal columns because none of the three is the
   one you always came for. */
.workspace.home3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* --- today's books --- */
.today-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--scroll) transparent;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.book {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 13px;
  border-radius: 13px;
  background: var(--panel-2);
}
.book .t {
  font-variant-numeric: tabular-nums;
  font-size: 14px;
  font-weight: 500;
  color: var(--accent-ink);
  flex: none;
}
.book-text { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.book-text b {
  font-size: 14.5px;
  font-weight: 500;
  letter-spacing: -0.01em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.book-text span { font-size: 12.5px; color: var(--ink-3); }
.book.next { background: var(--accent-bg); box-shadow: inset 0 0 0 1px var(--accent-line); }

/* --- the data --- */
.data-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--scroll) transparent;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.figures { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.figure {
  padding: 13px;
  border-radius: 13px;
  background: var(--panel-2);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.figure b {
  font-size: 25px;
  font-weight: 600;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.figure span { font-size: 12.5px; color: var(--ink-3); }

.dist { display: flex; flex-direction: column; gap: 9px; }
.dist h3 {
  margin: 0;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-3);
}
/* One bar, split by share. A stacked bar reads a composition faster than four
   numbers, and the numbers are in the legend underneath anyway. */
.bar {
  display: flex;
  height: 10px;
  border-radius: 999px;
  overflow: hidden;
  background: var(--panel-3);
}
.bar i { display: block; }
.bar i:nth-child(1) { background: var(--accent); }
.bar i:nth-child(2) { background: var(--accent-2); }
.bar i:nth-child(3) { background: var(--accent-3); }
.legend { display: flex; flex-direction: column; gap: 5px; }
.legend div { display: flex; align-items: center; gap: 8px; font-size: 13px; }
.legend i { width: 9px; height: 9px; border-radius: 3px; flex: none; }
.legend div:nth-child(1) i { background: var(--accent); }
.legend div:nth-child(2) i { background: var(--accent-2); }
.legend div:nth-child(3) i { background: var(--accent-3); }
.legend span { margin-left: auto; color: var(--ink-2); font-variant-numeric: tabular-nums; }


/* --- the left column: today, then what has been asked --- */
.home-left { gap: 14px; overflow: visible; }
.home-left > .card { flex: 1; min-height: 0; }

.hist-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--scroll) transparent;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.hist-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: 100%;
  padding: 10px 12px;
  border: 0;
  border-radius: 11px;
  background: var(--panel-2);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background 130ms ease-out;
}
.hist-item:hover { background: var(--panel-3); }
.hist-item b {
  font-size: 13.5px;
  font-weight: 500;
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.hist-item span { font-size: 11.5px; color: var(--ink-3); font-variant-numeric: tabular-nums; }

/* --- the orb --- */

/* The WebGL canvas fills this box, so the box IS the orb's size. Bigger than
   the CSS version it replaces: the shader has detail in it worth seeing. */
.oracle {
  position: relative;
  width: 168px;
  height: 168px;
  margin: 0 auto 6px;
  flex: none;
  border-radius: 50%;
  /* A bloom under the canvas rather than in it -- the shader's own alpha
     falls off at the rim, and this gives the falloff something to sit on
     against a light panel. */
  box-shadow: 0 10px 34px -12px rgb(var(--accent-rgb) / 0.5);
}
.oracle canvas { border-radius: 50%; }

/* --- filters on the data panel --- */
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 14px;
  flex: none;
}
.chip {
  padding: 6px 11px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--ink-2);
  font: inherit;
  font-size: 12.5px;
  cursor: pointer;
  transition: background 130ms ease-out, border-color 130ms ease-out, color 130ms ease-out;
}
.chip:hover { border-color: var(--accent-line); color: var(--ink); }
.chip[aria-pressed="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}
.chip .n { opacity: 0.7; margin-left: 5px; font-variant-numeric: tabular-nums; }

/* the filtered patients, listed under the figures */
.hits { display: flex; flex-direction: column; gap: 5px; }
.hits h3 {
  margin: 0 0 3px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.hit {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.hit:hover { background: var(--panel-2); }
.hit .avatar { width: 26px; height: 26px; font-size: 10px; }
.hit b { font-size: 13.5px; font-weight: 500; flex: 1; min-width: 0;
         overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hit span { font-size: 12.5px; color: var(--ink-3); font-variant-numeric: tabular-nums; }

/* --- the assistant, now Home's middle panel --- */
#home-ai .card-body { flex: 1; min-height: 0; padding: 0; }

/* ------------------------------------------------------------- link style */

/* Built in JS by the empty states, so it has no markup in index.html. */
.linkish {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  color: var(--accent-ink);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--accent-line);
}
.linkish:hover { text-decoration-color: var(--accent-ink); }


/* ------------------------------------------------------------------ trend */

/* Recessive grid, thin marks, text in ink tokens -- identity is carried by the
   coloured mark beside the label, never by colouring the label itself. */
.trend { display: flex; flex-direction: column; gap: 6px; }
.trend-svg {
  width: 100%;
  height: 132px;
  display: block;
  overflow: visible;
  touch-action: none;
}
.trend-grid { stroke: var(--line); stroke-width: 0.18; }
.trend-axis {
  fill: var(--ink-3);
  font-size: 2.6px;
  text-anchor: end;
  font-variant-numeric: tabular-nums;
}
.trend-line { fill: none; stroke-width: 0.7; stroke-linecap: round; stroke-linejoin: round; }
.trend-dot { stroke: var(--panel); stroke-width: 0.35; }
.trend-cross { stroke: var(--ink-3); stroke-width: 0.2; stroke-dasharray: 1 1; }

/* The reference band. Neutral on purpose -- it is the backdrop the values are
   read against, not a series, so it must never compete with the line. */
.trend-ref { fill: var(--ok-bg); opacity: 0.75; }
.trend-legend i.ref-swatch {
  background: var(--ok-bg);
  border: 1px solid var(--ok-line);
  border-radius: 2px;
  width: 14px;
  height: 9px;
}

.trend-dates {
  display: flex;
  justify-content: space-between;
  font-size: 11.5px;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.trend-legend { display: flex; gap: 14px; font-size: 12.5px; color: var(--ink-2); }
.trend-legend span { display: inline-flex; align-items: center; gap: 6px; }
.trend-legend i { width: 9px; height: 9px; border-radius: 3px; flex: none; }

.trend-tip {
  font-size: 12.5px;
  color: var(--ink);
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 6px 9px;
  font-variant-numeric: tabular-nums;
}
.trend-tip[hidden] { display: none; }
.trend-empty { margin: 0; font-size: 13.5px; color: var(--ink-3); }

.trend-pick { display: flex; gap: 5px; flex-wrap: wrap; }

/* --------------------------------------------------- assistant UI actions */

/* What the assistant did, as something you can act on rather than a line of
   log text. Every button here maps to a call the gateway already made. */
.act {
  align-self: stretch;
  max-width: 68ch;
  padding: 12px 13px;
  border: 1px solid var(--accent-line);
  border-radius: 12px;
  background: var(--accent-bg);
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.act-top { display: flex; align-items: center; gap: 9px; }
.act-top b { font-size: 14px; font-weight: 500; letter-spacing: -0.01em; }
.act-top .avatar { width: 26px; height: 26px; font-size: 10px; }
.act-row { display: flex; gap: 6px; flex-wrap: wrap; }
.act-btn {
  padding: 6px 11px;
  border: 1px solid var(--accent-line);
  border-radius: 8px;
  background: var(--panel);
  color: var(--accent-ink);
  font: inherit;
  font-size: 12.5px;
  cursor: pointer;
  transition: background 130ms ease-out;
}
.act-btn:hover { background: var(--panel-2); }
.act-btn[disabled] { opacity: 0.55; cursor: default; }
.act-note { margin: 0; font-size: 12.5px; color: var(--ink-2); line-height: 1.5; }


/* ------------------------------------------------------------------ modal */

.modal {
  width: min(560px, calc(100vw - 32px));
  max-height: calc(100dvh - 64px);
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--panel);
  color: var(--ink);
  box-shadow: var(--shadow-2);
}
.modal::backdrop { background: rgba(30, 22, 70, 0.42); backdrop-filter: blur(3px); }
/* Viewing, not filling in. A radiograph in a 560px form-width dialog comes out
 * barely larger than the thumbnail that opened it, which makes "open full
 * size" a lie. The grid columns inside modal-body are a form layout, so they
 * are dropped here too. */
.modal.roomy { width: min(960px, calc(100vw - 48px)); }
.modal.roomy .modal-body { display: block; }
.modal-form { display: flex; flex-direction: column; max-height: calc(100dvh - 64px); }
.modal-top { display: flex; align-items: center; gap: 12px; padding: 18px 20px 0; }
.modal-top h2 { margin: 0; flex: 1; font-size: 19px; font-weight: 600; letter-spacing: -0.02em; }
.modal-note {
  margin: 10px 20px 0;
  padding: 10px 12px;
  border-radius: var(--r-sm);
  background: var(--accent-bg);
  border: 1px solid var(--accent-line);
  color: var(--accent-ink);
  font-size: 13px;
  line-height: 1.5;
}
.modal-note[hidden] { display: none; }
.modal-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--scroll) transparent;
  padding: 16px 20px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
.modal-error {
  margin: 0 20px;
  padding: 10px 13px;
  border-radius: var(--r-sm);
  background: var(--bad-bg);
  color: var(--bad-ink);
  font-size: 13.5px;
}
.modal-error[hidden] { display: none; }
.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 9px;
  padding: 14px 20px 18px;
  border-top: 1px solid var(--line-soft);
}
.modal-actions .ghost, .modal-actions .go { width: auto; margin: 0; padding: 10px 18px; }

.f { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.f.wide { grid-column: 1 / -1; }
.f label { font-size: 13px; color: var(--ink-2); }
.f label .req { color: var(--bad-ink); }
.f input, .f select, .f textarea {
  width: 100%;
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--field);
  color: var(--ink);
  font: inherit;
  transition: border-color 130ms ease-out, box-shadow 130ms ease-out;
}
.f textarea { min-height: 96px; resize: vertical; line-height: 1.55; }
.f input:focus, .f select:focus, .f textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-bg);
}
.f .hint { font-size: 12px; color: var(--ink-3); }

/* ------------------------------------------------------------------ note */

/* The SOAP panel is editable while a visit is open and read-only once it is
   signed -- the database enforces that with a trigger, so the UI simply agrees
   with it rather than pretending to be the gate. */
.soap-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.soap-head h4 { margin: 0; flex: 1; }
.soap-tag {
  padding: 3px 9px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.soap-tag.open { background: var(--warn-bg); color: var(--warn); }
.soap-tag.locked { background: var(--ok-bg); color: var(--ok); }
.soap textarea {
  width: 100%;
  min-height: 66px;
  padding: 9px 11px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--field);
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  line-height: 1.55;
  resize: vertical;
}
.soap textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-bg);
}
.soap-actions { display: flex; align-items: center; gap: 8px; margin-top: 9px; }
.soap-actions .spacer { flex: 1; }
.soap-saved { font-size: 12.5px; color: var(--ink-3); }
.addenda { margin-top: 10px; display: flex; flex-direction: column; gap: 7px; }
.addendum {
  padding: 9px 11px;
  border-radius: 10px;
  background: var(--panel-2);
  border-left: 1px solid var(--accent-line);
}
.addendum b { display: block; font-size: 12px; color: var(--ink-3); font-weight: 500; margin-bottom: 2px; }
.addendum p { margin: 0; font-size: 13.5px; }

/* ----------------------------------------------------------------- review */

.review-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--scroll) transparent;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.draft {
  padding: 15px 16px;
  border-radius: 14px;
  background: var(--panel-2);
  border: 1px solid var(--line-soft);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.draft-top { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.draft-top b { font-size: 15px; font-weight: 600; letter-spacing: -0.01em; }
.draft-kind {
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--accent-bg);
  color: var(--accent-ink);
  font-size: 12px;
}
.draft-when { margin-left: auto; font-size: 12.5px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.draft-body {
  margin: 0;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink-2);
  white-space: pre-wrap;
}
.draft-meta {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  font-size: 12px;
  color: var(--ink-3);
  font-family: var(--mono, ui-monospace, Menlo, monospace);
}
.draft-actions { display: flex; gap: 7px; flex-wrap: wrap; }
.draft-status {
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 12px;
}
.draft-status.approved { background: var(--ok-bg); color: var(--ok); }
.draft-status.edited   { background: var(--warn-bg); color: var(--warn); }
.draft-status.rejected { background: var(--bad-bg); color: var(--bad-ink); }

@media (max-width: 560px) {
  .modal-body { grid-template-columns: 1fr; }
}

/* ------------------------------------------------------------ responsive */

@media (max-width: 1180px) {
  .board { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 820px) {
  /* Below this the board is one column, so the page scrolls as a page again
     and the fixed-height trick above would only trap the content. */
  .app { grid-template-columns: 1fr; height: auto; overflow: visible; }
  .stage { overflow: visible; }
  .board { grid-auto-rows: auto; }
  .card { min-height: 260px; }
  .rail { flex-direction: row; align-items: center; gap: 18px; overflow-x: auto; }
  .rail .nav { flex-direction: row; }
  .rail-foot { margin: 0 0 0 auto; flex-direction: row; align-items: center; }
  .who { border-top: 0; padding-top: 0; }
  .board { grid-template-columns: minmax(0, 1fr); }
  .stage { padding: 18px; }
  .search input { width: 100%; max-width: none; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* ------------------------------------------------------------ responsive */

/* The three-column workspace is a desk layout. It degrades in two steps: the
   detail panel drops under the stage first, then everything stacks and the
   shell stops being a floating tablet and becomes the page. */

@media (max-width: 1240px) {
  .workspace { grid-template-columns: 264px minmax(0, 1fr); }
  .workspace.home3 { grid-template-columns: 1fr 1fr; }
  .workspace.home3 > :last-child { grid-column: 1 / -1; }
  .col-right { grid-column: 1 / -1; min-height: 340px; }
}

/* Short windows. Nothing about a 600px-tall laptop is exotic, and three full
   panels do not fit one -- so the grid stops trying and the workspace scrolls. */
@media (max-height: 720px) {
  .workspace { grid-auto-rows: auto; }
  .col, .stage, .col-right, .card.wide { min-height: 300px; }
  .home-left > .card { min-height: 190px; }
}
@media (max-height: 560px) {
  .col, .stage, .col-right, .card.wide { min-height: 260px; }
}

@media (max-width: 860px) {
  .app { padding: 0; height: auto; overflow: visible; }
  .shell {
    height: auto;
    min-height: 100dvh;
    border: 0;
    border-radius: 0;
  }

  /* Brand and account hold the first row; the sections get a full-width
     scrolling row of their own instead of being crushed to nothing. */
  .topnav { flex-wrap: wrap; gap: 12px; padding: 12px 14px; }
  .brand { flex: 1; }
  .topnav-end { order: 2; }
  .tabs {
    order: 3;
    flex: 1 0 100%;
    padding-bottom: 2px;
    -webkit-overflow-scrolling: touch;
  }

  .home-left > .card { flex: none; min-height: 240px; }
  .workspace, .workspace.home3 {
    grid-template-columns: minmax(0, 1fr);
    grid-auto-rows: auto;
    padding: 12px;
    gap: 12px;
    overflow-y: visible;
  }
  .col { overflow: visible; }
  .col-right { max-height: none; }

  /* With the tab strip in normal flow, everything else in the stage has to be
     re-placed or it lands on top of it. Zoom and expand share the bottom-left,
     the hotspots keep their column at the right, and the note sits above both. */
  .stage { min-height: 520px; }
  .seg { position: static; margin-bottom: 0; }
  .seg-item { font-size: 13.5px; padding: 9px 8px; }
  .model { padding: 84px 76px 132px 20px; }

  .zoom { flex-direction: row; bottom: 14px; left: 14px; gap: 8px; }
  .round.tl { top: auto; bottom: 14px; left: 108px; }
  .hotspots {
    top: 84px;
    bottom: auto;
    right: 14px;
    left: auto;
    transform: none;
  }
  .hot { width: 40px; height: 40px; }
  .hot svg { width: 18px; height: 18px; }
  .soap { left: 14px; right: 14px; bottom: 68px; max-height: 34%; }

  .daynav { width: 100%; margin-left: 0; }
  .daynav b { flex: 1; min-width: 0; }
  .db-search { margin-left: 0; flex: 1 0 100%; }
  .db-search input { width: 100%; }
  .table { font-size: 13.5px; }
}

@media (max-width: 560px) {
  .stats { grid-template-columns: 1fr; }
  .labs { grid-template-columns: 1fr; }
  .slot-row { grid-template-columns: 60px minmax(0, 1fr); row-gap: 8px; }
  .slot-row .slot-kind { grid-column: 2; justify-self: start; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
  /* The mark stops turning. The orb handles reduced motion itself: it draws
     one frame and never starts its loop. */
  .brand-mark::before, .panel .mark-glyph::before { animation: none !important; }
}

/* Imaging ------------------------------------------------------------------
 * A film is dark and the panel is light, so each shot sits on its own near
 * black bed rather than bleeding into the card. The bed is a fixed shape and
 * the image is contained inside it, because a chest film and a wrist film have
 * different aspect ratios and a row of shots that each set their own height
 * reads as a mistake. */
.studies { display: flex; flex-direction: column; gap: 12px; }

.study {
  display: block;
  margin: 0;
  border: 1px solid var(--line-soft);
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--panel-2);
}

.study-shot {
  display: block;
  width: 100%;
  height: 260px;
  padding: 0;
  border: 0;
  background: var(--film-bed);
  cursor: zoom-in;
}
.study-shot img { width: 100%; height: 100%; object-fit: contain; display: block; }
.study-shot:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.study-cap {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 11px 0;
}
.study-cap b { font-size: 13px; }
.study-date { font-size: 11.5px; color: var(--ink-3); white-space: nowrap; }

/* The radiologist's words, and the only description of a film anyone should
 * be reading -- the assistant cannot see the image and must not narrate it. */
.study-report {
  margin: 4px 0 0;
  padding: 0 11px 10px;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--ink-2);
}

.study-full { display: flex; flex-direction: column; gap: 10px; }
.study-full img {
  width: 100%;
  max-height: min(70vh, 720px);
  object-fit: contain;
  background: var(--film-bed);
  border-radius: var(--r-sm);
}
.study-full .study-report { padding: 0; }

/* Did-you-mean rows ---------------------------------------------------------
 * Separated from results deliberately. The search found nothing; these are
 * guesses, and a guess that looks identical to a hit is one someone will read
 * as a hit. The heading carries that, and the rows sit on a tinted ground so
 * the boundary survives a glance. */
.table tbody tr.suggest-head {
  cursor: default;
  background: var(--panel-2);
  border-bottom: 1px solid var(--line);
}
.table tbody tr.suggest-head:hover { background: var(--panel-2); }
.table tr.suggest-head td { padding: 9px 14px; }
.table tr.suggest-head b { font-size: 12px; letter-spacing: 0.01em; }
.table tr.suggest-head span { font-size: 12px; color: var(--ink-2); }

.table tbody tr.suggested { background: var(--suggest-bg); }
.table tbody tr.suggested:hover { background: var(--panel-2); }

/* Why this row surfaced. "sounds similar" is much weaker evidence than a close
 * spelling -- phonetic keys collide on genuinely different names -- so the
 * distinction is on screen rather than folded away. */
.table .why {
  flex: none;
  font-size: 11px;
  line-height: 1;
  padding: 4px 7px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--ink-3);
  white-space: nowrap;
}

/* Assistant answers, tool trail, errors ------------------------------------
 * The answer is the thing being read; everything else in the log is context
 * for it and is styled to stay behind it. */

/* Rendered markdown inside an answer bubble. Tight spacing: a two-item list
 * with paragraph margins reads as three separate thoughts. */
.bubble > p { margin: 0; }
.bubble > p + p,
.bubble > .ans-list + p,
.bubble > p + .ans-list { margin-top: 8px; }
.bubble .ans-head { font-weight: 600; color: var(--ink); }
.bubble .ans-list { margin: 0; padding-left: 20px; }
.bubble .ans-list li { margin: 3px 0; }
.bubble .ans-list li::marker { color: var(--ink-3); }
.bubble code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.92em;
  padding: 1px 5px;
  border-radius: 5px;
  background: var(--panel-3, var(--ground));
}
.bubble strong { font-weight: 600; color: var(--ink); }

/* One collapsed row for everything the assistant looked up, instead of a
 * running log that pushes the answer off screen. */
.trail { align-self: stretch; }
.trail-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  width: 100%;
  padding: 3px 4px;
  border: 0;
  background: none;
  text-align: left;
  cursor: pointer;
  color: var(--ink-3);
  font-size: 12.5px;
}
.trail-head:hover { color: var(--ink-2); }
.trail-head::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  /* Only while the turn is running. A finished row is a record, not activity. */
  animation: trail-pulse 1.1s ease-in-out infinite;
}
.trail.is-done .trail-head::before { animation: none; background: var(--line); }
.trail.is-bad .trail-head::before { animation: none; background: var(--bad, #b02a2a); }
.trail-say { flex: 1; }
.trail-count { font-variant-numeric: tabular-nums; opacity: 0.75; }
.trail-list { padding: 2px 4px 4px 18px; display: flex; flex-direction: column; gap: 3px; }
/* `display: flex` outranks the user-agent's `[hidden] { display: none }`, so
   without this the collapsed list is never actually collapsed. */
.trail-list[hidden] { display: none; }
.trail-row { display: flex; gap: 8px; font-size: 12px; color: var(--ink-3); }
.trail-row b { font-weight: 500; color: var(--ink-2); }
.trail-fields { margin-left: auto; font-variant-numeric: tabular-nums; }

@keyframes trail-pulse { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .trail-head::before { animation: none; }
}

/* A failure the clinician can act on, rather than a dim line that reads as
 * part of the conversation. */
.ai-error {
  align-self: stretch;
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 9px 13px;
  border-radius: 10px;
  border: 1px solid var(--bad-line, #e8c9c9);
  background: var(--bad-bg, #fdf4f4);
  color: var(--bad-ink, #8f2020);
  font-size: 13px;
  line-height: 1.45;
}
.ai-error span { flex: 1; }
.link-btn {
  flex: none;
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  font-weight: 600;
  color: var(--accent-ink);
  cursor: pointer;
  text-decoration: underline;
}
.link-btn:hover { color: var(--accent); }

.stop-btn { flex: none; }

/* The diary, as rows to open rather than a paragraph to read. */
.diary { display: flex; flex-direction: column; gap: 2px; margin-top: 4px; }
.diary-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  width: 100%;
  padding: 7px 9px;
  border: 0;
  border-radius: 8px;
  background: none;
  text-align: left;
  cursor: pointer;
  font: inherit;
  color: var(--ink-2);
}
.diary-row:hover { background: var(--panel-2); }
.diary-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.diary-time {
  flex: none;
  font-variant-numeric: tabular-nums;
  font-size: 12.5px;
  color: var(--ink-3);
}
.diary-row b { font-weight: 500; color: var(--ink); }
.diary-why {
  flex: 1;
  text-align: right;
  font-size: 12.5px;
  color: var(--ink-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* A drafted note waiting to be accepted. Deliberately not styled as saved:
 * it is a proposal until the clinician clicks, and looking finished before it
 * is written is the one impression this card must not give. */
.draft { display: flex; flex-direction: column; gap: 10px; margin-top: 6px; }
.draft-sec b {
  display: block;
  font-size: 11.5px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 3px;
}
.draft-sec p { margin: 0; font-size: 13.5px; line-height: 1.5; color: var(--ink-2); }
.draft-foot { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.draft-status { font-size: 12.5px; color: var(--ink-3); }
.act.is-done .draft-status { color: var(--ok); }

/* Confirming a file into the record ----------------------------------------
 * The dialog is the authorising step, not a courtesy prompt, so it shows what
 * is actually about to happen: which patient, which file, and a picture of it.
 * A filename is easy to misread; the image is not. */
.confirm { display: flex; flex-direction: column; gap: 14px; }

.confirm-shot {
  height: 190px;
  border-radius: var(--r-sm);
  background: var(--film-bed);
  display: grid;
  place-items: center;
  overflow: hidden;
}
.confirm-shot img { width: 100%; height: 100%; object-fit: contain; }
.confirm-kind {
  font-size: 13px;
  letter-spacing: 0.08em;
  color: var(--ink-3);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 5px 12px;
  background: var(--panel);
}

.confirm-facts {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 5px 14px;
  margin: 0;
  font-size: 13.5px;
}
.confirm-facts dt { color: var(--ink-3); }
.confirm-facts dd { margin: 0; color: var(--ink); overflow-wrap: anywhere; }

/* Says where this ends up. Not styled as an error -- it is not a warning that
 * something is wrong, it is a statement of what the button does. */
.confirm-warn {
  margin: 0;
  padding: 9px 12px;
  border-radius: 8px;
  background: var(--accent-bg);
  border: 1px solid var(--accent-line);
  color: var(--accent-ink);
  font-size: 13px;
  line-height: 1.45;
}

/* Attaching an image to a question ------------------------------------------
 * The attachment sits above the composer rather than inside it: it is part of
 * the question being written, and a thumbnail crammed into a one-line input
 * reads as a control rather than as content. */
.ai-attached {
  padding: 8px 20px 0;
}
.ai-attached[hidden] { display: none; }

.attach-chip {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 9px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--panel-2);
}
.attach-chip img {
  flex: none;
  width: 38px;
  height: 38px;
  object-fit: cover;
  border-radius: 7px;
  background: var(--film-bed);
}
.attach-words { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.attach-words b {
  font-size: 13px;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.attach-words span { font-size: 11.5px; color: var(--ink-3); }
.attach-x {
  flex: none;
  display: grid;
  place-items: center;
  /* 32px: above the 24px WCAG 2.5.8 minimum with room for a fingertip, and it
     is the only control in the chip so it can afford the space. */
  width: 32px;
  height: 32px;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--ink-3);
  cursor: pointer;
}
.attach-x svg { width: 15px; height: 15px; }
.attach-x:hover { background: var(--panel-3, var(--ground)); color: var(--ink); }
.attach-x:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* The image as it was sent, above the question it accompanied. Without it the
   question reads as a non-sequitur once the composer has been cleared. */
.bubble-shot {
  display: block;
  width: 100%;
  max-height: 200px;
  object-fit: contain;
  border-radius: 8px;
  margin-bottom: 8px;
  background: var(--film-bed);
}

/* Dragging a file over the conversation. A dashed rule rather than a colour
   wash: the log is full of content and tinting all of it is noisy. */
#home-ai.is-dropping { outline: 2px dashed var(--accent); outline-offset: -6px; }
#home-ai.is-dropping #ai-log { opacity: 0.55; }

/* 36px, matching the input's height. 28 passed WCAG 2.5.8 (24px) but the
   brief's craft bar is the incumbents "minus the hostility", and cramped hit
   targets are named as the thing they get wrong. */
.ai-form #ai-clip { flex: none; width: 36px; height: 36px; }
.ai-form #ai-clip svg { width: 17px; height: 17px; }

/* "Did you mean" — near misses as something to press ------------------------
 * Full-width rows rather than inline chips: each one carries a name, an MRN
 * and an age, and those are what tell two Husseins apart. Squeezing them into
 * a chip would drop exactly the fields that make the choice safe. */
.guesses { display: flex; flex-direction: column; gap: 4px; margin-top: 6px; }

.guess {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--line-soft);
  border-radius: 9px;
  background: var(--panel);
  text-align: left;
  font: inherit;
  color: var(--ink-2);
  cursor: pointer;
}
.guess:hover { background: var(--panel-2); border-color: var(--line); }
.guess:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.guess[disabled] { cursor: default; opacity: 0.5; }
.guess.is-picked {
  opacity: 1;
  border-color: var(--accent-line);
  background: var(--accent-bg);
}

.guess-words { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.guess-words b { font-weight: 500; color: var(--ink); font-size: 14px; }
.guess-who { font-size: 11.5px; color: var(--ink-3); font-variant-numeric: tabular-nums; }

.guess-why {
  flex: none;
  font-size: 11px;
  padding: 3px 7px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--panel-2);
  color: var(--ink-3);
  white-space: nowrap;
}

/* While a turn is in flight ------------------------------------------------
 * The composer closes because a second question against the same conversation
 * queues behind the first and arrives as a reply to something the clinician
 * has stopped waiting for. Stop stays live -- it is the way out, not another
 * way in. */
.ai-form input[disabled] {
  background: var(--panel-2);
  color: var(--ink-3);
  cursor: not-allowed;
}
.ai-form button[disabled] { opacity: 0.45; cursor: not-allowed; }
.ai-form .stop-btn { opacity: 1; cursor: pointer; }

/* The two places that re-ask a question by clicking. Dimmed rather than
   removed, so the list does not jump while somebody is reading it. */
body.is-asking .hist-item,
body.is-asking .guess:not([disabled]) {
  opacity: 0.5;
  pointer-events: none;
}

/* The conversation currently on screen, in the chats list. */
.hist-item.is-open {
  background: var(--accent-bg);
  border-color: var(--accent-line);
}
.hist-item.is-open b { color: var(--accent-ink); }

/* Work left open, under the day it belongs to ------------------------------
 * One row, only when there is something in it. Sits below the diary because it
 * answers the question that comes after "who is coming" -- not beside it,
 * which would read as a second list of appointments. */
.loose { padding: 4px 6px 2px; }
.loose[hidden] { display: none; }

.loose-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 11px 12px;
  border: 1px solid var(--line-soft);
  border-radius: 10px;
  background: var(--panel-2);
  text-align: left;
  font: inherit;
  color: var(--ink-2);
  cursor: pointer;
}
.loose-row:hover { background: var(--accent-bg); border-color: var(--accent-line); }
.loose-row:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.loose-row b { flex: 1; font-weight: 500; font-size: 13.5px; color: var(--ink); }
.loose-row svg { width: 16px; height: 16px; flex: none; color: var(--ink-3); }
.loose-row:hover svg { color: var(--accent-ink); }

/* Switching views ----------------------------------------------------------
 * The panes are toggled with [hidden], which is a hard cut. A cut is not wrong
 * for a tool -- it is instant, and instant is honest -- but it reads as a jump
 * when four panels of content replace four others in the same frame.
 *
 * One short fade, on the arriving pane only. The leaving one is simply gone,
 * because holding it around to cross-fade would mean two view states alive at
 * once for the sake of 140ms. Nothing moves: a translate here would be motion
 * for its own sake, which is the fancy trick that was not asked for. */
.workspace:not([hidden]) {
  animation: view-in 140ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
/* From 0.55, not from 0, and with no fill-mode.
 *
 * A keyframe animation on a [hidden]-toggled pane can be pinned at its first
 * frame: a backgrounded tab freezes animations at currentTime 0, and with
 * `from { opacity: 0 }` that left the entire Home view invisible until the tab
 * was focused again. Measured, not theorised -- it happened here.
 *
 * So the first frame is one a person can still read. Frozen, the worst case is
 * a slightly dim panel; running, it is the same soft ramp. A screen holding
 * charts does not get to be blank because a frame was dropped. */
@keyframes view-in {
  from { opacity: 0.55; }
  to   { opacity: 1; }
}

/* Content arriving inside a card that is already on screen. Slower than the
   view fade, because this one lands under the reader's eye rather than
   replacing everything at once. */
.today-list > *, #data-body > *, .hist-list > * {
  animation: settle-in 190ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
@keyframes settle-in {
  from { opacity: 0.4; }
  to   { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  /* Not 0.01ms: that keeps the animation machinery running to no purpose and
     can still drop a frame. Remove it, and the cut is what remains -- which is
     the correct alternative here, since nothing about the change is conveyed
     by the motion itself. */
  .workspace:not([hidden]),
  .today-list > *, #data-body > *, .hist-list > * { animation: none; }
}

/* The assistant, stacked under the detail panel --------------------------
 * Not a floating window. It is the second row of a column that had a gap at
 * the bottom, so it sits in the flow and the panel above gives up the height
 * it takes. Nothing to drag around and nothing to lose behind the chart. */
.dock {
  flex: 0 0 auto;          /* height is set inline by the resizer */
  min-height: 0;
  display: flex;
  margin-top: 10px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--panel);
  box-shadow: var(--shadow-1);
  overflow: hidden;
}
.dock[hidden] { display: none; }
.dock > .card { flex: 1; min-width: 0; border: 0; border-radius: 0; box-shadow: none; }

/* The boundary between chart and conversation. Thin, because it is furniture,
   with a hit area larger than the line it draws -- a 1px target is a target
   only in principle. */
.dock-grab {
  flex: none;
  height: 12px;
  margin-top: 6px;
  border-radius: 6px;
  cursor: row-resize;
  display: grid;
  place-items: center;
  touch-action: none;
}
.dock-grab[hidden] { display: none; }
.dock-grab::before {
  content: "";
  width: 52px;
  height: 3px;
  border-radius: 3px;
  background: var(--line);
  /* scaleX, not width. Animating width relayouts the row on every frame of a
     hover, and this bar sits directly above a scrolling panel -- the detector
     was right to flag it. Drawn at its full width and scaled down at rest, so
     growing is a transform and the layout never moves. */
  transform: scaleX(0.73);
  transition: background 120ms ease-out, transform 120ms ease-out;
}
.dock-grab:hover::before { background: var(--accent-line); transform: scaleX(1); }
.dock-grab:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.dock-grab.is-dragging::before { background: var(--accent); transform: scaleX(1); }

/* Folded: the header only, so the panel above takes the room back. */
.dock.is-collapsed { height: auto !important; }
.dock.is-collapsed #ai-log,
.dock.is-collapsed .ai-attached,
.dock.is-collapsed .ai-form,
.dock.is-collapsed .card-foot { display: none; }
.dock .dock-fold { margin-left: 4px; }
.dock .dock-fold svg { transform: rotate(90deg); transition: transform 140ms ease-out; }
.dock.is-collapsed .dock-fold svg { transform: rotate(-90deg); }

/* The fold control belongs to the dock, not to the card on Home.
 *
 * Both selectors match while docked, because #home-ai is inside .dock -- so
 * the id wins on specificity and hid the button in the one place it is needed.
 * The dock rule has to out-specify it, not merely come later. */
#home-ai .dock-fold { display: none; }
.dock #home-ai .dock-fold { display: grid; place-items: center; }

@media (prefers-reduced-motion: reduce) {
  .dock .dock-fold svg,
  .dock-grab::before { transition: none; }
  /* Still legible without the grow: the bar keeps its resting scale. */
}

/* The empty state, in a window a third the height of the panel it was drawn
 * for. The orb is 168px of decoration that pushed its own message out of view
 * -- so in the dock it shrinks and the words keep the room. */
.dock .oracle { width: 88px; height: 88px; box-shadow: none; }
.dock .ai-empty { gap: 5px; max-width: 30ch; }
.dock .ai-empty b { font-size: 14px; }
.dock .ai-empty span { font-size: 12.5px; line-height: 1.45; }

/* The footer earns its line on a full panel and costs a third of a small
 * window. The same words live on the drafted-note card, at the moment they
 * actually matter. */
.dock .card-foot { display: none; }

/* The header, at 360px minus a fold button ---------------------------------
 * "New chat" wrapped to two lines and the composer placeholder truncated. The
 * model name is the thing that can go: it is developer information, it is on
 * the Home panel where there is room for it, and nobody mid-consult needs to
 * be told which build answered. */
.dock .card-top .meta { display: none; }
.dock .card-top .ghost { white-space: nowrap; }
.dock .ai-form { padding: 10px 14px; gap: 8px; }
.dock .ai-form input { padding: 9px 12px; }

/* --- second factor ------------------------------------------------------ */
/* The typed key. Monospace and wrapping, because it is 32 characters that
   somebody reads off a screen into a phone, and a line that runs off the edge
   is the difference between this working and not. */
.mfa-secret {
  display: block;
  margin: 8px 0;
  padding: 9px 11px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--panel-a);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  letter-spacing: 0.06em;
  word-break: break-all;
  color: var(--ink);
  user-select: all;                     /* one click selects the whole key */
}
.mfa-codes {
  margin: 8px 0 0;
  padding-left: 18px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  line-height: 1.7;
  color: var(--ink);
}
#set-mfa input {
  width: 100%;
  margin: 8px 0;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--bg);
  color: var(--ink);
  font-size: 14px;
}

/* The code step on the sign-in screen. `[hidden]` first and then the layout
   rule: an author `display` at equal specificity beats the UA's
   `[hidden] { display: none }`, which has caught this file three times. */
#mfa-step[hidden] { display: none; }
#mfa-step {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
#mfa-step input {
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--bg);
  color: var(--ink);
  font-size: 16px;
  letter-spacing: 0.18em;
}
#mfa-submit {
  padding: 11px 18px;
  border: 0;
  border-radius: 10px;
  background: var(--accent);
  color: var(--on-accent);
  font-weight: 500;
  cursor: pointer;
}
#mfa-submit:hover { background: var(--accent-hi); }
