/* AutoArch web — "Operatory": a light, precision-instrument surface with a
   single deep petrol-teal accent, the model's studio stage as the one image.
   4px rhythm, one accent, 120ms transitions, restraint everywhere. */
* { box-sizing: border-box; margin: 0; }
:root {
  /* structural neutrals — cool off-white ground, white panels, graphite ink */
  --bg: #eef1f3; --panel: #ffffff; --panel2: #ffffff; --inset: #e8edf0;
  --line: #dde3e8; --line2: #cbd3da;
  --text: #2b333b; --bright: #10161c; --dim: #5b6670; --dim2: #66707a;
  /* accent: deep petrol-teal. --blue/--sky names kept for churn-free reuse */
  --blue: #0f6f66; --blue-h: #0c7d72; --sky: #0c766b;
  /* semantic status foregrounds — deepened to read on light grounds */
  --green: #0f6e42; --amber: #8a5e12; --red: #b23a2f;
  /* semantic status tints (bg / border), separate from the accent */
  --ok-bg: #e4f3ea;  --ok-bd: #bce0cb;
  --warn-bg: #faeece; --warn-bd: #ecd6a1;
  --bad-bg: #fbe4e1;  --bad-bd: #f0c4bd;
  --info-bg: #ddefec; --info-fg: #0c6b62; --info-bd: #a9ddd6;
  --neutral-bg: #e7ebee;
  --edit-bg: #eee7fa; --edit-fg: #6a4aa8; --edit-bd: #d7c7f2;
  --r: 10px; --r-lg: 14px;
  --shadow: 0 1px 2px rgba(20,30,40,.06), 0 12px 30px rgba(20,30,40,.09);
  --studio: linear-gradient(180deg, #f3f6f8 0%, #d7e0e6 55%, #b6c4cd 100%);
}
html { -webkit-text-size-adjust: 100%; }
body {
  background: var(--bg); color: var(--text);
  font: 14px/1.55 'Segoe UI', system-ui, -apple-system, sans-serif;
  min-height: 100vh; display: flex; flex-direction: column;
}
a { color: var(--sky); text-decoration: none; }
a:hover { text-decoration: underline; }
::selection { background: #cdeae5; color: var(--bright); }
:focus-visible { outline: 2px solid var(--sky); outline-offset: 2px;
  border-radius: 4px; }

/* ---------------------------------------------------------- header */
header.top {
  display: flex; align-items: center; justify-content: space-between;
  padding: 13px 26px; background: var(--panel);
  border-bottom: 1px solid var(--line);
}
.brand { font-size: 19px; font-weight: 700; color: var(--bright);
  letter-spacing: -.2px; }
.brand span { color: inherit; }
.brand:hover { text-decoration: none; }
header nav { display: flex; align-items: center; gap: 22px; }
header nav a { color: var(--dim); font-weight: 600; font-size: 13.5px;
  transition: color .12s; }
header nav a:hover { color: var(--text); text-decoration: none; }
form.inline { display: inline; }

main { flex: 1; width: 100%; max-width: 1120px; margin: 0 auto;
  padding: 28px 26px 72px; }

footer.site {
  border-top: 1px solid var(--line); color: var(--dim2);
  font-size: 12px; padding: 18px 26px; display: flex;
  justify-content: space-between; background: var(--panel);
}

/* ---------------------------------------------------------- buttons */
.btn {
  display: inline-block; background: var(--blue); color: #fff;
  border: 1px solid var(--blue); border-radius: var(--r);
  padding: 9px 18px; font-weight: 600; font-size: 14px; cursor: pointer;
  transition: background .12s, transform .06s; text-align: center;
}
.btn:hover { background: var(--blue-h); text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn.ghost { background: transparent; color: var(--text);
  border-color: var(--line2); }
.btn.ghost:hover { background: var(--inset); border-color: var(--dim2); }
.btn.big { padding: 12px 26px; font-size: 15px; border-radius: 12px; }
.btn.small { padding: 6px 12px; font-size: 13px; }
.btn.wide { width: 100%; margin-top: 10px; }
.btn:disabled { background: #dfe4e8; border-color: #dfe4e8;
  color: var(--dim2); cursor: default; transform: none; }
button.linklike { background: none; border: none; color: var(--dim);
  font: inherit; font-weight: 600; cursor: pointer; padding: 0;
  transition: color .12s; }
button.linklike:hover { color: var(--text); }

/* ---------------------------------------------------------- cards */
.card {
  background: var(--panel2); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 20px;
}
h2 { margin-bottom: 14px; font-size: 21px; letter-spacing: -.2px; }
h3 { margin-bottom: 10px; font-size: 15px; }
.muted { color: var(--dim2); font-size: 12.5px; }
.center { text-align: center; padding: 22px 0; }
.kicker { color: var(--dim2); font-size: 13px; font-weight: 700;
  letter-spacing: 1.8px; margin-bottom: 14px; }

/* ---------------------------------------------------------- landing
   one centered editorial column. The 3D viewer is the centerpiece —
   the single object on the page; everything else is well-set type.
   No grids of cards, no icon rows. */
.lp { max-width: 1120px; margin: 0 auto; }

/* hero: the real model IS the page — copy beside it, stage dominant */
.lp-hero { display: grid; grid-template-columns: minmax(330px, 5fr) 7fr;
  gap: clamp(28px, 4vw, 56px); align-items: center;
  padding: clamp(28px, 5vh, 64px) 0 8px; }
.lp-hero-copy .kicker { margin-bottom: 18px; }
.lp-hero h1 { font-family: Georgia, 'Iowan Old Style', 'Times New Roman',
  serif; font-weight: 400; font-size: clamp(2.5rem, 4.6vw, 3.55rem);
  line-height: 1.05; letter-spacing: -.3px; color: var(--bright);
  text-wrap: balance; }
.lp-lede { margin: 20px 0 28px; color: var(--text); font-size: 17px;
  line-height: 1.65; max-width: 44ch; }
.cta-row { display: flex; gap: 12px; flex-wrap: wrap; }
.lp-trust { margin-top: 16px; color: var(--dim); font-size: 13px; }

.viewer-card { border: 1px solid var(--line2); border-radius: var(--r-lg);
  overflow: hidden; box-shadow: var(--shadow); background: var(--panel2); }
.lp-hero-stage #hero-viewer { height: clamp(380px, 44vw, 560px); }
#hero-viewer { height: 440px; background: var(--studio); cursor: grab; }
#hero-viewer:active { cursor: grabbing; }
#hero-viewer canvas { display: block; }

/* demo video: one clean player under the hero, no third-party chrome.
   Starts muted when scrolled into view (browsers only allow silent
   autoplay); Sound unmutes. Reduced motion: poster + play button. */
.lp-demo { max-width: 860px; margin: clamp(56px, 9vh, 96px) auto 0;
  text-align: center; }
.lp-demo .kicker { margin-bottom: 16px; }
.lp-demo-card { position: relative; aspect-ratio: 427 / 240;
  background: var(--studio); }
.lp-demo-video { display: block; width: 100%; height: 100%;
  object-fit: cover; background: var(--studio); cursor: pointer; }
.lp-demo-sound, .lp-demo-play { position: absolute; border: 0; color: #fff;
  background: rgba(15, 30, 34, .62); backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px); cursor: pointer;
  transition: background .15s ease, transform .15s ease; }
.lp-demo-sound { right: 14px; bottom: 14px; display: inline-flex;
  align-items: center; gap: 7px; padding: 7px 13px 7px 11px;
  border-radius: 999px; font: 600 13px/1 inherit; letter-spacing: .2px; }
.lp-demo-sound:hover, .lp-demo-play:hover { background: rgba(15, 111, 102, .88); }
.lp-demo-sound .lp-snd-on { display: none; }
.lp-demo-sound[aria-pressed="true"] .lp-snd-on { display: block; }
.lp-demo-sound[aria-pressed="true"] .lp-snd-off { display: none; }
.lp-demo-play { left: 50%; top: 50%; width: 72px; height: 72px;
  margin: -36px 0 0 -36px; border-radius: 50%; display: grid;
  place-items: center; }
.lp-demo-play:hover { transform: scale(1.05); }
.lp-demo-play[hidden] { display: none; }
.lp-demo-sound:focus-visible, .lp-demo-play:focus-visible {
  outline: 2px solid var(--blue); outline-offset: 2px; }
.lp-demo-cap { margin-top: 14px; color: var(--dim); font-size: 13.5px; }

/* the one line to remember, at statement scale */
.lp-statement { text-align: center; margin: clamp(72px, 11vh, 120px) auto 0;
  max-width: 720px; }
.lp-statement h2 { font-family: Georgia, 'Iowan Old Style',
  'Times New Roman', serif; font-weight: 400;
  font-size: clamp(1.9rem, 3.4vw, 2.7rem); letter-spacing: -.3px;
  color: var(--bright); margin-bottom: 16px; text-wrap: balance; }
.lp-statement p { color: var(--text); font-size: 16.5px; line-height: 1.7;
  max-width: 56ch; margin: 0 auto; }

/* the pipeline, in order — a real sequence, worn openly */
.lp-steps { display: flex; justify-content: center; align-items: center;
  gap: 10px; flex-wrap: wrap; list-style: none; padding: 0;
  margin: clamp(40px, 6vh, 64px) auto 0; }
.lp-steps li { display: flex; align-items: center; gap: 9px;
  color: var(--text); font-size: 14.5px; font-weight: 600; }
.lp-steps li + li::before { content: ''; width: clamp(14px, 3vw, 34px);
  height: 1px; background: var(--line2); margin-right: 10px; }
.lp-step-n { display: inline-flex; align-items: center;
  justify-content: center; width: 24px; height: 24px; border-radius: 50%;
  border: 1px solid var(--line2); color: var(--sky); font-size: 12px;
  font-weight: 700; }
.lp-step-final { color: var(--bright); }
.lp-step-final .lp-step-n { background: var(--blue); border-color:
  var(--blue); color: #fff; }
.viewer-cap { display: flex; justify-content: space-between;
  padding: 10px 14px; font-size: 12px; color: var(--dim);
  border-top: 1px solid var(--line); }

.lp-body { max-width: 620px; margin: 64px auto; }
.lp-body p { color: var(--dim); font-size: 15.5px; line-height: 1.75;
  margin: 0 0 22px; }
.lp-body p:last-child { margin-bottom: 0; }
.lp-body strong { color: var(--bright); font-weight: 600; }

.lp-price { text-align: center; margin: 0 auto 26px; padding-top: 44px;
  border-top: 1px solid var(--line); max-width: 620px; }
.lp-price-line { display: flex; align-items: baseline; gap: 16px;
  justify-content: center; flex-wrap: wrap; }
.price { font-family: Georgia, 'Iowan Old Style', 'Times New Roman',
  serif; font-weight: 400; font-size: 44px; color: var(--bright);
  letter-spacing: -.5px; }
.price span { font-size: 16px; color: var(--dim);
  font-family: 'Segoe UI', system-ui, sans-serif; letter-spacing: 0; }
.lp-or { color: var(--dim2); font-size: 14px; }
.lp-save { color: var(--green); font-size: 12px; font-weight: 700;
  letter-spacing: 1.4px; text-transform: uppercase; }
.lp-price-sub { color: var(--dim2); font-size: 13px; margin: 12px 0 22px; }

/* ---------------------------------------------------------- forms */
.auth-wrap { max-width: 400px; margin: 46px auto 0; }
.auth-brand { text-align: center; font-size: 24px; font-weight: 700;
  color: var(--bright); margin-bottom: 18px; letter-spacing: -.3px; }
.auth-brand span { color: inherit; }
.auth-card { padding: 26px; box-shadow: var(--shadow); }
label { display: block; margin: 14px 0 5px; color: var(--dim);
  font-size: 12.5px; font-weight: 600; letter-spacing: .2px; }
input:not([type=radio]):not([type=file]) {
  width: 100%; background: var(--inset); border: 1px solid var(--line2);
  border-radius: var(--r); padding: 10px 12px; color: var(--text);
  font-size: 14.5px; transition: border-color .12s; }
input:focus { outline: none; border-color: var(--sky); }
.error { background: var(--bad-bg); color: var(--red);
  border: 1px solid var(--bad-bd); border-radius: var(--r);
  padding: 9px 12px; margin-bottom: 6px; font-size: 13px; }
.aux { margin-top: 16px; text-align: center; }

.banner { border-radius: var(--r); padding: 10px 14px; margin-bottom: 18px;
  border: 1px solid var(--line2); font-size: 13.5px; }
.banner.ok { background: var(--ok-bg); color: var(--green); border-color: var(--ok-bd); }
.banner.warn { background: var(--warn-bg); color: var(--amber); border-color: var(--warn-bd); }
.banner.dev { background: var(--neutral-bg); color: var(--dim); }
/* the sign-in popup after an update signed everyone out (tools/sign_out_all.py) */
dialog.update-note { margin: auto; max-width: 420px; width: calc(100% - 32px);
  border: 1px solid var(--line2); border-radius: var(--r);
  background: var(--panel); color: var(--text); padding: 20px 22px;
  box-shadow: 0 14px 44px rgba(16, 22, 28, .28); }
dialog.update-note::backdrop { background: rgba(16, 22, 28, .45); }
dialog.update-note h3 { margin: 0 0 8px; color: var(--bright); }
dialog.update-note p { margin: 0 0 16px; line-height: 1.45; }

/* ---------------------------------------------------------- dashboard */
/* small drop tile on the left, the viewer hero on the right */
.top-row { display: grid; grid-template-columns: 280px 1fr; gap: 16px;
  align-items: start; margin-bottom: 16px; }
.dropzone {
  border: 2px dashed var(--line2); border-radius: 12px; background: var(--inset);
  padding: 22px 14px; text-align: center; margin-bottom: 6px;
  transition: border-color .12s, background .12s;
}
.dropzone.armed, .dropzone:hover { border-color: var(--sky);
  background: var(--info-bg); }
.dropzone.busy { border-color: var(--blue); animation: pulse 1.6s
  ease-in-out infinite; }
@keyframes pulse { 50% { border-color: var(--blue-h); background: var(--info-bg); } }
.drop-title { font-weight: 600; color: var(--bright); margin-bottom: 2px; }
.dropzone .btn { margin-top: 12px; }
/* dropped-file details, under the drop zone */
.file-info { margin-top: 10px; border: 1px solid var(--line);
  border-radius: var(--r); background: var(--inset); padding: 4px 12px; }
.file-info[hidden] { display: none; }
.fi-row { display: flex; justify-content: space-between; gap: 10px;
  padding: 6px 0; border-bottom: 1px solid var(--line); font-size: 12.5px; }
.fi-row:last-child { border-bottom: none; }
.fi-row span:first-child { color: var(--dim2); font-weight: 600; flex: none; }
.fi-row span:last-child { color: var(--text); text-align: right;
  word-break: break-all; }
#fi-status.ok { color: var(--green); }
#fi-status.bad { color: var(--red); }
#fi-status.run { color: var(--info-fg); }
#upload-msg { margin-top: 8px; min-height: 18px; }
#upload-msg.notice { color: var(--sky); font-size: 13px;
  font-weight: 600; }
#upload-msg.run { color: var(--info-fg); font-size: 13px; font-weight: 600;
  display: flex; align-items: center; gap: 8px; }
.radio { display: inline-flex; gap: 7px; align-items: center; margin: 0;
  color: var(--text); font-weight: 400; font-size: 14px; cursor: pointer; }
#label-text { width: 200px; padding: 6px 10px; font-size: 12.5px; }
/* the left column stacks the drop tile and the blocking card */
.left-col { display: flex; flex-direction: column; gap: 16px; }
.beta-pill { display: inline-block; margin-left: 7px; border-radius: 8px;
  padding: 1.5px 8px; font-size: 10.5px; font-weight: 700;
  letter-spacing: .6px; text-transform: uppercase; vertical-align: 2px;
  background: var(--ok-bg); color: var(--green); border: 1px solid var(--ok-bd); }
/* full-width preset seg: the 280px card clipped the old inline seg and
   made Heavy unreachable */
.seg-full { display: flex; margin: 4px 0 2px; }
.seg-full button { flex: 1; padding: 6px 0; text-align: center; }
.bs-row { display: flex; align-items: center; gap: 8px; margin: 9px 0; }
.bs-row span:first-child { flex: none; width: 76px; }
.bs-row input[type=range] { flex: 1; min-width: 0; }
.bs-row span:last-child { flex: none; width: 44px; text-align: right; }
#btn-unblock { margin-top: 8px; }
.block-row { display: flex; align-items: center; gap: 10px;
  margin: 12px 0 8px; }
.block-row input[type=color] { width: 34px; height: 26px; padding: 2px;
  border: 1px solid var(--line2); border-radius: 7px;
  background: var(--inset); cursor: pointer; }
.block-row .radio { font-size: 13px; }
/* in-page confirmation strip — replaces the browser's popup dialogs */
.confirm-bar { display: flex; align-items: center; gap: 12px;
  margin-top: 8px; padding: 9px 14px; border-radius: var(--r);
  background: var(--warn-bg); border: 1px solid var(--warn-bd); color: var(--amber);
  font-size: 13.5px; font-weight: 600; }
.confirm-bar[hidden] { display: none; }
.confirm-bar #confirm-text { flex: 1; }
.btn.danger { background: var(--red); border-color: var(--red); color: #fff; }
.btn.danger:hover { background: #9c3126; border-color: #9c3126; }

/* the list keeps its default height and scrolls beyond it */
.cases-scroll { max-height: 240px; overflow-y: auto; }
.cases-scroll thead th { position: sticky; top: 0;
  background: var(--panel2); z-index: 2; }
.pill-edited { display: inline-block; margin-left: 7px; border-radius: 8px;
  padding: 1.5px 8px; font-size: 10.5px; font-weight: 700;
  background: var(--edit-bg); color: var(--edit-fg); border: 1px solid var(--edit-bd);
  vertical-align: 1px; }
.promo-row { display: flex; gap: 8px; margin: 12px 0; }
.promo-row input { flex: 1; }
.promo-create { display: flex; gap: 8px; align-items: center;
  flex-wrap: wrap; }
.promo-create input[name=code] { width: 190px; }
.promo-create input[type=number] { width: 70px; }
.promo-create input[name=note] { width: 200px; }

table.cases { width: 100%; border-collapse: collapse; }
table.cases th { text-align: left; color: var(--dim2); font-size: 10.5px;
  letter-spacing: 1.2px; text-transform: uppercase; padding: 7px 9px;
  border-bottom: 1px solid var(--line); font-weight: 700; }
table.cases td { padding: 8px 9px; border-bottom: 1px solid var(--line);
  font-size: 13px; vertical-align: middle; }
table.cases tr:hover td { background: #f1f4f6; }
.actions { display: flex; gap: 12px; justify-content: flex-end; }
.actions a { font-size: 13px; font-weight: 600; }

.chip { display: inline-block; border-radius: 9px; padding: 2.5px 10px;
  font-size: 11px; font-weight: 700; background: var(--neutral-bg);
  color: var(--dim); border: 1px solid var(--line2); }
.chip.run { background: var(--info-bg); color: var(--info-fg); border-color: var(--info-bd); }
.chip.ok { background: var(--ok-bg); color: var(--green); border-color: var(--ok-bd); }
.chip.warn { background: var(--warn-bg); color: var(--amber); border-color: var(--warn-bd); }
.chip.bad { background: var(--bad-bg); color: var(--red); border-color: var(--bad-bd); }

/* ------------------------------------------------------------ admin */
.stat-row { display: flex; gap: 14px; margin-top: 14px; flex-wrap: wrap; }
.stat { background: var(--panel2); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 16px 22px; min-width: 150px; }
.stat-n { font-size: 30px; font-weight: 700; color: var(--bright);
  letter-spacing: -.5px; }
.stat-l { color: var(--dim2); font-size: 12.5px; margin-top: 2px; }
.admin-table th, .admin-table td { white-space: nowrap; }
/* Server health card (web/health.py): one row per signal, its chip green /
   amber / red; the values wrap on a narrow screen */
.health-card { margin-top: 12px; padding: 14px 18px; overflow-x: auto; }
.health-head { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap;
  margin-bottom: 8px; }
table.health { border-collapse: collapse; width: 100%; }
table.health td { padding: 4px 10px 4px 0; vertical-align: top; font-size: 13px; }
table.health td:first-child { width: 1%; white-space: nowrap; }
table.health td:nth-child(2) { width: 1%; white-space: nowrap; font-weight: 600;
  padding-right: 18px; }
/* accounts logging in from more than one state — worth a look */
.admin-table tr.row-flag td { background: var(--warn-bg); }
.admin-table details summary { cursor: pointer; color: var(--sky); }
.admin-table .ip-history { margin-top: 6px; border-collapse: collapse; }
.admin-table .ip-history td { padding: 2px 10px 2px 0; font-size: 12px;
  color: var(--dim2); white-space: nowrap; }
/* the owner's roster uses the whole window and re-flows with it: long
   cells (names + chips, dates, places) wrap, the Beta checkboxes sit in
   one row, so every column - the actions last - stays on screen */
main.admin-full { max-width: none;
  padding-left: clamp(12px, 2.5vw, 40px);
  padding-right: clamp(12px, 2.5vw, 40px); }
.admin-table.roster th, .admin-table.roster td { padding-left: 7px;
  padding-right: 7px; }
.admin-table.roster td.name-cell { white-space: normal; min-width: 170px;
  max-width: 340px; }
.admin-table.roster td.name-cell .chip { margin: 2px 4px 2px 0 !important; }
.admin-table.roster td.wrap { white-space: normal; min-width: 96px; }
.admin-table.roster .beta-form { display: grid;
  grid-template-columns: repeat(2, max-content); align-items: center;
  gap: 3px 12px; }
.admin-table.roster .ip-line { font-size: 12px; color: var(--dim2);
  white-space: nowrap; }
.admin-table.roster .beta-form label { display: flex; justify-self: start;
  justify-content: flex-start; align-items: center; gap: 4px;
  white-space: nowrap; font-size: 12.5px; }
.admin-table.roster .beta-form button { font-weight: 600; color: var(--sky); }
.admin-table.roster .chip { white-space: nowrap; }
.admin-table.roster td.row-actions { white-space: normal; min-width: 140px; }
.admin-table.roster td.row-actions form { display: inline-block;
  white-space: nowrap; }
.admin-table.roster .trial-left { white-space: normal; }
/* narrower windows still scroll the table sideways: the practice name
   stays pinned on the left so every row is still readable */
.admin-table.roster th:first-child, .admin-table.roster td:first-child {
  position: sticky; left: 0; z-index: 1; background: var(--panel2);
  box-shadow: 1px 0 0 var(--line); }
.admin-table.roster tr.row-flag td:first-child { background: var(--warn-bg); }
.admin-table.roster tr:hover td:first-child { background: #f1f4f6; }
/* the Beta column: blocking and hollow, then Save beta - one row on wide
   windows, the two boxes over the button otherwise */
@media (min-width: 1600px) {
  .admin-table.roster .beta-form { grid-template-columns: repeat(3, max-content); }
}
/* form-page confirmation line (verify-code resend, etc.) */
.notice { color: var(--sky); font-size: 13px; margin: 4px 0 8px; }
.trial-left { margin-left: 6px; font-size: 12px; }
/* "signed out on another device" banner on the login card */
.signout-note { text-align: left; margin-bottom: 14px; font-size: 13px; }

/* ------------------------------------------------- embedded viewer
   (the hero — the product IS this viewport) */
.viewer-panel { padding: 14px 14px 10px; }
.viewer-head { display: flex; align-items: center; gap: 14px;
  flex-wrap: wrap; padding-bottom: 10px; }
.v-title { font-weight: 700; font-size: 14.5px; }
.trim-model-pill { border: 1px solid var(--ok-bd); border-radius: 999px;
  background: var(--ok-bg); color: var(--green); padding: 2px 8px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .2px; }
.trim-model-pill.fallback { border-color: var(--warn-bd); background: var(--warn-bg);
  color: var(--amber); }
.trim-model-pill.logistic { border-color: var(--line2); background: var(--neutral-bg);
  color: var(--dim); }
.v-spacer { flex: 1; }
.seg { display: inline-flex; border: 1px solid var(--line2);
  border-radius: 9px; overflow: hidden; }
.seg button { background: transparent; border: none; color: var(--dim);
  font: inherit; font-size: 12.5px; font-weight: 600; padding: 6px 13px;
  cursor: pointer; border-right: 1px solid var(--line); }
.seg button:last-child { border-right: none; }
.seg button:hover { color: var(--text); background: var(--inset); }
.seg button.active { background: var(--info-bg); color: var(--info-fg); }
.seg button:disabled { color: #a7b0b9; cursor: default; background: none; }
.btn.small.warn { background: var(--warn-bg); border-color: var(--warn-bd); color: var(--amber); }
.btn.small.active { background: var(--info-bg); border-color: var(--blue);
  color: var(--info-fg); }
.viewer-tools { display: flex; align-items: center; gap: 10px;
  flex-wrap: wrap; padding: 8px 2px; border-top: 1px solid var(--line); }
.viewer-tools[hidden] { display: none; }
.viewer-tools .radio { font-size: 13px; }
/* live "label may not fit" notice next to the label box */
.label-warn { font-size: 12.5px; color: var(--amber);
  display: inline-flex; align-items: center; gap: 5px; }
.label-warn[hidden] { display: none; }
.label-warn::before { content: "⚠"; font-size: 13px; }
/* per-model character counter beside the label box (limit varies by model) */
#label-count { font-size: 12px; white-space: nowrap; }
#label-count.over { color: var(--amber); font-weight: 600; }
.tool-gap { width: 10px; }
input[type=range] { accent-color: var(--blue); }
#brush-size { width: 120px; }
#base-size { width: 160px; }
#chamfer-size { width: 160px; }   /* same size as the base slider */
/* keep the EasyOff button + its Chamfer slider together on one line */
.eo-group { display: inline-flex; align-items: center; gap: 8px;
  flex: none; }
/* Download / Revert / Delete stay together, pinned to the right edge
   (margin-left:auto keeps them right-aligned even if the row wraps) */
.action-group { display: inline-flex; align-items: center; gap: 10px;
  flex: none; margin-left: auto; }
#stage-wrap { position: relative; margin-top: 10px; }
#stage { height: min(60vh, 620px); min-height: 380px;
  background: var(--studio); border-radius: 10px;
  overflow: hidden; cursor: grab; }
#stage:active { cursor: grabbing; }
#stage canvas { display: block; }
#stage-busy { position: absolute; inset: 0; border-radius: 10px;
  background: rgba(240, 243, 245, .62); backdrop-filter: blur(2px);
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 14px; color: var(--bright);
  font-weight: 600; font-size: 14.5px; z-index: 5; }
#stage-busy[hidden] { display: none; }
.spinner { width: 34px; height: 34px; border-radius: 50%;
  border: 3px solid rgba(20, 30, 40, .16);
  border-top-color: var(--sky); animation: spin .8s linear infinite; }
.spinner.small { width: 14px; height: 14px; border-width: 2px; flex: none; }
@keyframes spin { to { transform: rotate(360deg); } }
.viewer-foot { display: flex; justify-content: space-between; gap: 12px;
  padding: 9px 4px 2px; }

/* ---------------------------------------------------------- viewer */
.modal { position: fixed; inset: 0; background: rgba(28, 38, 48, .42);
  backdrop-filter: blur(3px); display: flex; align-items: center;
  justify-content: center; z-index: 40; }
.modal[hidden] { display: none; }
.modal-body { width: min(1000px, 94vw); height: min(700px, 88vh);
  background: var(--panel); border: 1px solid var(--line2);
  border-radius: var(--r-lg); display: flex; flex-direction: column;
  box-shadow: var(--shadow); overflow: hidden; }
.modal-head { display: flex; justify-content: space-between;
  align-items: center; padding: 11px 16px;
  border-bottom: 1px solid var(--line); font-weight: 600; }
#viewer-canvas { flex: 1; background: var(--studio); }
#viewer-canvas canvas { display: block; }

/* ------------------------------------------- archs page: viewer-first
   (owner call 2026-08-27, from customer feedback: kill the dead space).
   A narrow rail of compact cards hugs the LEFT WALL — upload + every
   secondary control; the essentials (label / add date / apply /
   download) ride in one strip above the stage; the stage gets
   everything else, down to the bottom of the window (no footer here). */
main.app-full { max-width: none; padding: 10px 14px 12px 0;
  display: flex; flex-direction: column; }
main.app-full .banner { margin: 0 0 10px; border-radius: 0 var(--r) var(--r) 0;
  border-left: none; }
main.app-full .top-row { flex: 1 1 0; min-height: 0; margin-bottom: 0;
  grid-template-columns: 248px 1fr; gap: 12px; align-items: stretch; }
/* rail cards sit flush against the window's left edge; on short windows
   the RAIL scrolls, never the page — the stage always fills the viewport */
main.app-full .left-col { gap: 10px; min-height: 0; overflow-y: auto;
  overscroll-behavior: contain; }
main.app-full .left-col .card { flex: none; }
main.app-full .left-col .card { border-left: none;
  border-radius: 0 var(--r-lg) var(--r-lg) 0; }
.side-card { padding: 11px 13px 12px; }
.side-head { display: flex; align-items: center; gap: 8px;
  justify-content: space-between; margin-bottom: 6px; }
.side-head h3, .side-card h3 { margin: 0 0 4px; font-size: 13.5px; }
.side-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 8px; }
/* the hidden attribute must beat the display rules above/below — without
   this, mode-gated rows and buttons (trim radios in erase mode, Remove
   blocking next to Apply blocking) stayed visible */
.side-row[hidden], .side-slider[hidden], .btn[hidden] { display: none; }
.side-slider { display: flex; align-items: center; gap: 8px;
  margin-top: 8px; }
.side-slider span { flex: none; font-size: 12px; color: var(--dim2); }
.side-slider input[type=range] { flex: 1; min-width: 0; }
/* compact drop tile + file details */
main.app-full .dropzone { padding: 12px 10px; margin-bottom: 4px; }
main.app-full .dropzone .btn { margin-top: 8px; }
main.app-full .file-info { margin-top: 8px; padding: 2px 10px; }
main.app-full .fi-row { padding: 4px 0; font-size: 12px; }
/* file details fold shut by default — the grey box stays, the rows show
   on demand; the "Done in Ns — arch" line below is always visible */
.file-info summary { list-style: none; cursor: pointer; display: flex;
  align-items: center; justify-content: space-between; padding: 6px 0;
  font-size: 12px; font-weight: 600; color: var(--dim); }
.file-info summary::-webkit-details-marker { display: none; }
.file-info summary::after { content: '▸'; color: var(--dim2);
  transition: transform .12s; }
.file-info[open] summary::after { transform: rotate(90deg); }
.file-info[open] summary { border-bottom: 1px solid var(--line); }
main.app-full #upload-msg { margin-top: 6px; min-height: 0; }
/* the stage owns the rest of the page */
main.app-full .viewer-panel { display: flex; flex-direction: column;
  min-height: 0; min-width: 0; padding: 10px 12px 8px; }
/* without min-width:0 the canvas's intrinsic width pins the grid column
   and the whole page overflows sideways when the window narrows */
main.app-full #stage-wrap, main.app-full #stage { min-width: 0; }
main.app-full .viewer-head { padding-bottom: 8px; flex-wrap: nowrap;
  min-width: 0; }
/* the title yields: it shrinks (with an ellipsis) before anything else
   in the strip moves — Raw/Finished sits right beside it (owner call) */
#v-title { flex: 0 1 auto; min-width: 56px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }
#stage-seg { flex: none; }
main.app-full .viewer-head #label-text { flex: 0 1 200px; min-width: 110px;
  width: 200px; }
main.app-full .viewer-head .muted, main.app-full .viewer-head .btn {
  white-space: nowrap; flex: none; }
/* second strip: ONE line always — EasyOff/chamfer + base stretch and
   compress to soak up the width, so Revert · Delete · Download stay in
   line at the right edge (Download directly under Add date / Apply) */
.viewer-actions { display: flex; align-items: center; gap: 18px;
  flex-wrap: nowrap; min-width: 0; padding: 8px 2px;
  border-top: 1px solid var(--line); }
.va-group { display: flex; align-items: center; gap: 8px; flex: 1 1 auto;
  min-width: 0; }
.va-group .muted, .va-group .btn, .va-group .seg { flex: none; }
/* with Hollow's group (the 'hollow' beta flag) the strip is too long for one
   line on a narrow viewer: it wraps instead of overlapping */
.viewer-actions:has(#btn-hollow) { flex-wrap: wrap; row-gap: 6px; }
.va-group input[type=range] { flex: 1 1 150px; min-width: 90px;
  max-width: 340px; }
.va-actions { display: inline-flex; align-items: center; gap: 10px;
  margin-left: auto; flex: none; }
main.app-full .confirm-bar { margin: 0 0 8px; }
main.app-full #stage-wrap { flex: 1; min-height: 0; display: flex;
  margin-top: 0; }
main.app-full #stage { flex: 1; height: auto; min-height: 320px; }
main.app-full .viewer-foot { padding: 7px 4px 0; }

@media (max-width: 900px) {
  .lp-hero { grid-template-columns: 1fr; padding-top: 22px; }
  .lp-hero-copy { text-align: center; }
  .lp-hero-copy .cta-row { justify-content: center; }
  .lp-lede { margin-left: auto; margin-right: auto; }
  .lp-hero-stage #hero-viewer, #hero-viewer { height: 320px; }
  .lp-steps li + li::before { display: none; }
  .top-row { grid-template-columns: 1fr; }
  main { padding: 20px 16px 56px; }
  main.app-full { padding: 10px 12px 20px 0; }
  main.app-full .top-row { grid-template-columns: 1fr; }
  main.app-full #stage { min-height: 300px; }
  main.app-full .viewer-head, .viewer-actions { flex-wrap: wrap; }
}

/* ------------------------------------------ admin on phones and tablets
   (owner 2026-09-28: on an iPhone the admin page "gets bunched"). Every
   rule sits in a max-width query, so desktop (>= 1024px) is unchanged. */

/* tablets and phones held sideways: the roster, problems and promo tables
   keep scrolling sideways with the practice name pinned. The cards' side
   padding moves into the first and last cells, so the columns scrolling
   under the pinned name no longer show in a 20px strip to its left. */
@media (min-width: 641px) and (max-width: 1023.98px) {
  main.admin-full .card:has(> table.admin-table),
  main.admin-full .card:has(> form > table.admin-table) {
    padding-left: 0; padding-right: 0; }
  main.admin-full .card > table.admin-table > * > tr > :first-child,
  main.admin-full .card > form > table.admin-table > * > tr > :first-child {
    padding-left: 20px; }
  main.admin-full .card > table.admin-table > * > tr > :last-child,
  main.admin-full .card > form > table.admin-table > * > tr > :last-child {
    padding-right: 20px; }
  main.admin-full .admin-table.roster td.name-cell { min-width: 183px; }
  main.admin-full .card > form > div,
  main.admin-full .card > .center { padding-left: 20px; padding-right: 20px; }
}

/* phones: nothing scrolls sideways. One card per practice with label |
   value rows, problems and promo codes as stacked rows, tap-sized buttons
   and checkboxes. */
@media (max-width: 640px) {
  /* the owner's five header links: the nav drops under the brand instead
     of pushing the page sideways (375px) or folding "Sign out" (390-430) */
  header.top { flex-wrap: wrap; gap: 6px 16px; padding: 12px 16px; }
  header nav { flex-wrap: wrap; gap: 4px 16px; }
  header nav .linklike { white-space: nowrap; }
  /* the footer's three lines stack instead of three narrow columns */
  footer.site { flex-direction: column; gap: 6px; padding: 16px; }

  /* usage and totals: two even columns filling the width */
  .stat-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px; }
  .stat { min-width: 0; padding: 12px 14px; }
  .stat-n { font-size: 24px; }
  main.admin-full .chip { font-size: 12px; }
  main.admin-full .btn.small { min-height: 36px; }
  /* iOS Safari zooms the page into any input under 16px */
  main.admin-full input:not([type=checkbox]):not([type=hidden]) {
    font-size: 16px; }

  /* roster: a card per practice. The labels follow the column order of
     the roster's <thead> in admin.html - keep them in step with it. */
  main.admin-full .card:has(> table.roster) { padding: 0; background: none;
    border: 0; }
  .admin-table.roster, .admin-table.roster > tbody { display: block; }
  .admin-table.roster > thead { display: none; }
  .admin-table.roster > tbody > tr { display: block; margin-bottom: 10px;
    padding: 12px 14px 10px; background: var(--panel2);
    border: 1px solid var(--line); border-radius: var(--r-lg); }
  .admin-table.roster > tbody > tr.row-flag { background: var(--warn-bg);
    border-color: var(--warn-bd); }
  .admin-table.roster > tbody > tr > td { display: block;
    min-width: 0; white-space: normal; overflow-wrap: anywhere;
    padding: 7px 0 7px 94px; border: 0; border-top: 1px solid var(--line); }
  /* the name is no longer pinned; the card, not the cells, is tinted */
  .admin-table.roster > tbody > tr > td,
  .admin-table.roster > tbody > tr > td:first-child,
  .admin-table.roster > tbody > tr:hover > td,
  .admin-table.roster > tbody > tr:hover > td:first-child,
  .admin-table.roster > tbody > tr.row-flag > td:first-child {
    position: relative; left: auto; z-index: auto; background: none;
    box-shadow: none; }
  .admin-table.roster > tbody > tr > td::before { position: absolute;
    left: 0; top: 8px; width: 86px; color: var(--dim2); font-size: 12px;
    font-weight: 600; line-height: 1.4; }
  .admin-table.roster > tbody > tr > td:nth-child(2)::before { content: 'Email'; }
  .admin-table.roster > tbody > tr > td:nth-child(3)::before { content: 'Signed up'; }
  .admin-table.roster > tbody > tr > td:nth-child(4)::before { content: 'Plan'; }
  .admin-table.roster > tbody > tr > td:nth-child(5)::before { content: 'Models'; }
  .admin-table.roster > tbody > tr > td:nth-child(6)::before { content: 'Location'; }
  .admin-table.roster > tbody > tr > td:nth-child(7)::before { content: 'IP history'; }
  .admin-table.roster > tbody > tr > td:nth-child(8)::before { content: 'Last active'; }
  .admin-table.roster > tbody > tr > td:nth-child(9)::before { content: 'Beta'; }
  /* the practice name heads the card; the actions close it, full width */
  .admin-table.roster > tbody > tr > td.name-cell { max-width: none;
    padding: 0 0 8px; border-top: 0; font-size: 15px; font-weight: 600;
    color: var(--bright); }
  .admin-table.roster > tbody > tr > td.row-actions { display: flex;
    flex-wrap: wrap; gap: 8px; padding: 10px 0 2px; }
  .admin-table.roster td.row-actions form { margin: 0 !important; }
  .admin-table.roster .ip-line { white-space: normal; }
  /* tap-sized buttons (the bare text links are 20px tall) */
  main.admin-full .admin-table button.linklike,
  main.admin-full .card > form > div button.linklike {
    min-height: 36px; padding: 6px 14px; border: 1px solid var(--line2);
    border-radius: var(--r); background: var(--panel2); }
  .admin-table.roster > tbody > tr > td .beta-form { display: flex;
    flex-wrap: wrap; align-items: center; gap: 2px 18px; }
  .admin-table.roster .beta-form label { min-height: 36px; margin: 0;
    gap: 8px; font-size: 14px; }
  main.admin-full .admin-table input[type=checkbox] { width: 20px;
    height: 20px; min-width: 20px; min-height: 20px; margin: 0; }
  /* the 30-day breakdown and the sign-in history wrap inside the card */
  .admin-table.roster details summary { padding: 6px 0; }
  .admin-table.roster .ip-history,
  .admin-table.roster .ip-history > tbody { display: block; }
  .admin-table.roster .ip-history tr { display: flex; flex-wrap: wrap;
    gap: 0 12px; padding: 3px 0; border-bottom: 1px solid var(--line); }
  .admin-table.roster .ip-history tr td,
  .admin-table.roster .ip-history tr td:first-child {
    position: static; padding: 0; white-space: normal;
    overflow-wrap: anywhere; font-size: 12.5px; background: none;
    box-shadow: none; }

  /* recent problems: checkbox | when, practice, what, detail (wrapped) */
  main.admin-full .card:has(> form > table.admin-table) { padding: 14px; }
  main.admin-full .card > form > table.admin-table,
  main.admin-full .card > form > table.admin-table > tbody { display: block; }
  main.admin-full .card > form > table.admin-table > thead { display: none; }
  main.admin-full .card > form > table.admin-table > tbody > tr {
    display: grid; grid-template-columns: 30px minmax(0, 1fr);
    gap: 3px 8px; padding: 10px 0; border-bottom: 1px solid var(--line); }
  main.admin-full .card > form > table.admin-table > tbody > tr > td {
    display: block; padding: 0; border: 0; white-space: normal;
    overflow-wrap: anywhere; background: none; }
  main.admin-full .card > form > table.admin-table > tbody > tr > td:first-child {
    grid-row: span 4; padding-top: 2px; }
  main.admin-full .card > form > table.admin-table > tbody > tr > td:nth-child(5) {
    color: var(--text); }
  main.admin-full .card > form > div { flex-wrap: wrap; gap: 10px !important; }

  /* promo codes: the form one field per row, each number with its hint */
  .promo-create { display: grid;
    grid-template-columns: 76px minmax(0, 1fr); gap: 8px 10px; }
  .promo-create input[name=code], .promo-create input[name=note],
  .promo-create .btn { grid-column: 1 / -1; width: 100%; }
  .promo-create input[type=number] { width: 100%; }
  .promo-create .btn { min-height: 40px; }
  /* ...and the list as rows: code + action, offer · used · status, note */
  main.admin-full .card > table.admin-table:not(.roster),
  main.admin-full .card > table.admin-table:not(.roster) > tbody {
    display: block; }
  main.admin-full .card > table.admin-table:not(.roster) > thead {
    display: none; }
  main.admin-full .card > table.admin-table:not(.roster) > tbody > tr {
    display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px;
    padding: 10px 0; border-bottom: 1px solid var(--line); }
  main.admin-full .card > table.admin-table:not(.roster) > tbody > tr > td {
    display: block; padding: 0; border: 0; white-space: normal;
    overflow-wrap: anywhere; background: none; }
  main.admin-full .card > table.admin-table:not(.roster) > tbody > tr > td:first-child {
    order: -3; flex: 1 1 auto; }
  main.admin-full .card > table.admin-table:not(.roster) > tbody > tr > td:last-child {
    order: -2; }
  main.admin-full .card > table.admin-table:not(.roster) > tbody > tr::after {
    content: ''; order: -1; flex-basis: 100%; }
  main.admin-full .card > table.admin-table:not(.roster) > tbody > tr > td:nth-child(3)::before {
    content: 'used '; }
  main.admin-full .card > table.admin-table:not(.roster) > tbody > tr > td:nth-child(4) {
    order: 1; flex-basis: 100%; }

  /* Server health card: each signal stacks - its chip and name on one
     line, the value wrapped under them (the desktop table keeps 3 columns) */
  .health-card { padding: 12px 14px; overflow-x: visible; }
  table.health, table.health tbody { display: block; }
  table.health tr { display: flex; flex-wrap: wrap; align-items: baseline;
    gap: 2px 8px; padding: 7px 0; border-bottom: 1px solid var(--line); }
  table.health tr:last-child { border-bottom: 0; }
  table.health td:first-child, table.health td:nth-child(2),
  table.health td:nth-child(3) { display: block; width: auto; padding: 0;
    white-space: normal; overflow-wrap: anywhere; }
  table.health td:nth-child(3) { flex-basis: 100%; }
}
