/* Arimo (Apache-2.0, Google Fonts) is character-by-character metric-compatible
   with Apple's Arial — same advance widths, so text laid out by the form renderer
   wraps at exactly the same break points as iOS Arial regardless of OS/browser.
   Self-hosted variable font; one .ttf per slope covers every weight via the wght
   axis. We use it as the substitute for the surveyXml `g="Arial"` font references
   (all 395 in the dental fixture are "Arial"). Only loaded for the form renderer
   — system UI text continues to use the Mac/native sans stack below. */
@font-face {
  font-family: 'Arimo';
  src: url('/static/fonts/Arimo.ttf') format('truetype-variations');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Arimo';
  src: url('/static/fonts/Arimo-Italic.ttf') format('truetype-variations');
  font-weight: 100 900;
  font-style: italic;
  font-display: swap;
}

* { box-sizing: border-box; }
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  margin: 0;
  background: #f5f6f8;
  color: #1c1f23;
}
.topbar {
  /* Three-region grid: left cluster, centered iPad strip, right cluster.
     The 1fr middle column grows to take leftover space, so the strip is
     always centered in the topbar regardless of how many tiles render. */
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 1rem;
  padding: 0.5rem 1.5rem;
  background: #1c2c40;
  color: #f5f6f8;
}
.topbar-left, .topbar-right {
  display: flex;
  align-items: center;
  gap: 1rem;
}
.topbar-center {
  display: flex;
  justify-content: center;
  align-items: center;
  min-width: 0;          /* allow the centered strip to shrink + scroll */
}
.topbar .brand { font-weight: 600; }
.topbar .workgroup { font-size: 0.85rem; opacity: 0.7; }
.topbar form.inline { display: inline; margin: 0; }
.topbar-link {
  color: #f5f6f8; text-decoration: none; font-size: 0.9rem;
  padding: 0.3rem 0.7rem; border-radius: 6px;
  background: rgba(255,255,255,0.08); transition: background 120ms ease;
}
.topbar-link:hover { background: rgba(255,255,255,0.18); }
button.link {
  background: none;
  border: none;
  color: #f5f6f8;
  cursor: pointer;
  padding: 0;
  font: inherit;
  text-decoration: underline;
}
main { padding: 1.5rem; max-width: 1100px; margin: 0 auto; }
.card {
  background: white;
  border-radius: 8px;
  padding: 1.5rem;
  box-shadow: 0 1px 3px rgba(0,0,0,0.05);
  margin-bottom: 1.5rem;
}
.card.auth { max-width: 420px; margin: 4rem auto; }
.card.placeholder { opacity: 0.7; }
.card-link { text-decoration: none; color: inherit; display: block; }
.card-link .card { transition: transform 120ms ease, box-shadow 120ms ease; }
.card-link:hover .card { transform: translateY(-2px); box-shadow: 0 4px 14px rgba(0,0,0,0.08); }
.muted { color: #6a7280; font-size: 0.9rem; }
form label { display: block; margin: 0.75rem 0; font-size: 0.9rem; color: #303641; }
form input[type=text], form input[type=password] {
  display: block;
  width: 100%;
  padding: 0.55rem 0.7rem;
  font: inherit;
  border: 1px solid #c9ced6;
  border-radius: 6px;
  margin-top: 0.25rem;
}
button[type=submit] {
  background: #1c6ed1;
  color: white;
  border: none;
  border-radius: 6px;
  padding: 0.6rem 1.2rem;
  font-weight: 500;
  cursor: pointer;
}
button[type=submit]:disabled { background: #99a3b3; cursor: not-allowed; }
.flash { list-style: none; padding: 0; margin: 1rem auto; max-width: 1100px; padding: 0 1.5rem; }
.flash li { padding: 0.7rem 1rem; border-radius: 6px; margin-bottom: 0.5rem; font-size: 0.9rem; }
.flash-error { background: #fdecea; color: #8d1e15; border: 1px solid #f4c6c2; }
.flash-info { background: #e7f0fa; color: #1a4a7d; border: 1px solid #b9d3ec; }
.grid { display: grid; gap: 1rem; }
.grid.two { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.grid.three { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.access { padding-left: 1.2rem; }
hr { border: none; border-top: 1px solid #e3e7ee; margin: 1.5rem 0; }

/* ----- generic helpers shared across stage-2 features ----- */
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
.small { font-size: 0.85rem; }

.data-table { width: 100%; border-collapse: collapse; }
.data-table th, .data-table td { text-align: left; padding: 0.55rem 0.7rem; border-bottom: 1px solid #e3e7ee; font-size: 0.92rem; }
.data-table th { background: #f1f3f6; font-weight: 600; color: #303641; }
.data-table tr:hover td { background: #f8f9fb; }

.btn-inline { color: #1c6ed1; text-decoration: none; font-weight: 500; }
.btn-inline:hover { text-decoration: underline; }

.xml-dump { background: #f1f3f6; padding: 1rem; border-radius: 6px; overflow-x: auto;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.82rem;
  white-space: pre-wrap; word-break: break-word; }

/* ----- Data area (subject list / detail) ----- */
.data-header-card { padding: 1rem 1.5rem; }
.data-header { display: flex; justify-content: space-between; align-items: flex-end;
  gap: 1rem; flex-wrap: wrap; }
.data-title { margin: 0 0 0.25rem; font-size: 1.5rem; }
.site-picker label { display: flex; gap: 0.5rem; align-items: center; margin: 0; font-size: 0.9rem; }
.site-picker select { padding: 0.4rem 0.6rem; border: 1px solid #c9ced6; border-radius: 6px;
  font: inherit; background: white; min-width: 220px; }
.site-current { display: flex; flex-direction: column; align-items: flex-end; gap: 0.1rem; }

.stats-row { display: grid; gap: 0.75rem; margin-bottom: 1.5rem;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }
.stat { background: white; border-radius: 8px; padding: 1rem 1.2rem;
  box-shadow: 0 1px 3px rgba(0,0,0,0.05); }
.stat-num { font-size: 1.8rem; font-weight: 600; color: #1c2c40; line-height: 1.1; }
.stat-label { font-size: 0.82rem; color: #6a7280; margin-top: 0.2rem; }

.subjects-toolbar { display: flex; align-items: center; gap: 1rem; margin-bottom: 1rem;
  flex-wrap: wrap; }
.search-input { flex: 1 1 300px; max-width: 460px;
  padding: 0.55rem 0.7rem; border: 1px solid #c9ced6; border-radius: 6px; font: inherit; }
.search-input:focus { outline: 2px solid #1c6ed1; outline-offset: -1px; border-color: transparent; }

.table-scroll { overflow-x: auto; }
.data-table.sortable th { cursor: pointer; user-select: none; white-space: nowrap; }
.data-table.sortable th:hover { background: #e8ebf0; }
.sort-indicator { display: inline-block; margin-left: 0.3rem; color: #6a7280; font-size: 0.75rem; }

.kv { display: grid; grid-template-columns: max-content 1fr; gap: 0.4rem 1rem; margin: 1rem 0; }
.kv dt { color: #6a7280; font-size: 0.85rem; }
.kv dd { margin: 0; }

.section-title { font-size: 1.15rem; margin: 0 0 1rem; color: #1c2c40; }

/* Pastel panel tints — applied as a modifier class on cards / stat tiles to
   add visual variety so the dashboard doesn't read as a wall of white boxes.
   Each tint is a soft pastel from the same palette family as the dashboard
   section cards (see _PASTEL_RAINBOW in routes/dashboard.py) so the look is
   consistent across the portal. Borders subtly tint too — pure white borders
   on a colored background look "stuck on", a slightly-saturated edge looks
   intentional. */
.panel-tint-pink     { background: #fde4e4; border-color: #f6c8c8; }
.panel-tint-peach    { background: #fdecd6; border-color: #f6d3a8; }
.panel-tint-cream    { background: #fdf5d3; border-color: #f1e2a3; }
.panel-tint-green    { background: #dff5d9; border-color: #b6dfa8; }
.panel-tint-blue     { background: #d6e8ff; border-color: #a8c8f0; }
.panel-tint-lavender { background: #e2d9fd; border-color: #c0b3ec; }
.panel-tint-rose     { background: #f5d9f3; border-color: #e3b3df; }

/* Subject identity grid (detail page header) — wider gap and slightly larger
   value text than the generic .kv since these values are the primary content
   of the header card. */
.subject-identity-kv { grid-template-columns: max-content 1fr; gap: 0.4rem 1.5rem;
  margin-top: 0.5rem; }
.subject-identity-kv dt { color: #6a7280; font-size: 0.85rem; }
.subject-identity-kv dd { font-size: 1rem; }

/* Stats row variant for the 2-up "Total visits / Visits complete" block on
   the subject detail page. */
.stats-row-2up { grid-template-columns: repeat(auto-fit, minmax(170px, 240px)); }

/* Visit list — accordion of clickable summary rows, each expanding to show
   its child forms. Built as divs (not a single table) because tables can't
   cleanly nest a sub-table inside a row spanning all columns. */
.visit-list { display: flex; flex-direction: column; gap: 0.4rem; }
.visit-item { border: 1px solid #e3e7ee; border-radius: 8px; background: white;
  overflow: hidden; }
.visit-summary { display: flex; align-items: center; gap: 0.8rem;
  padding: 0.7rem 1rem; cursor: pointer;
  transition: background 100ms ease; }
.visit-summary:hover { background: #f8f9fb; }
.visit-chevron { color: #6a7280; font-size: 0.8rem; width: 1rem;
  flex-shrink: 0; user-select: none; }
.visit-summary-main { display: flex; align-items: baseline; gap: 0.7rem;
  min-width: 200px; flex: 1; }
.visit-name { font-weight: 600; color: #1c2c40; }
.visit-status { font-size: 0.85rem; font-weight: 600; }
.visit-summary-meta { display: flex; align-items: center; gap: 1.2rem;
  flex-wrap: wrap; }
.visit-formcount { font-size: 0.85rem; color: #303641; white-space: nowrap; }
.visit-pct-wrap { display: inline-flex; align-items: center; gap: 0.5rem;
  white-space: nowrap; }
.visit-pct-bar { display: inline-block; width: 90px; height: 6px;
  background: #e3e7ee; border-radius: 3px; overflow: hidden; }
.visit-pct-fill { display: block; height: 100%; transition: width 200ms ease; }
.visit-pct-num { font-size: 0.8rem; color: #6a7280; min-width: 2.6rem; text-align: right; }
.visit-dates { white-space: nowrap; }

/* Forms sub-panel: indented from the visit row's left edge so the visual
   hierarchy reads as "these forms belong to this visit". Light pastel tint
   (lavender) differentiates the nested level from the outer visit row. */
.visit-forms { padding: 0.5rem 1rem 1rem 2.5rem;
  border-top: 1px solid rgba(0,0,0,0.05); }
.forms-empty { margin: 0.7rem 0; }

/* Two-line visit dates (Window + Actual) inside the summary meta. */
.visit-dates { display: flex; flex-direction: column; gap: 0.15rem; min-width: 220px; }
.visit-date-line { white-space: nowrap; }
.visit-date-label { display: inline-block; min-width: 3.6rem;
  color: #6a7280; font-weight: 600; }

/* Compact data-table variant for nested form lists inside expanded visits. */
.data-table-compact { margin-top: 0.7rem; }
.data-table-compact th { background: #fbfcfd; }
.data-table-compact th, .data-table-compact td {
  padding: 0.4rem 0.6rem; font-size: 0.88rem; }

.pager { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap;
  margin-top: 1rem; padding-top: 1rem; border-top: 1px solid #e3e7ee; }
.pager-btn, .pager-page {
  display: inline-block; padding: 0.4rem 0.7rem; border-radius: 6px;
  text-decoration: none; color: #1c6ed1; background: white;
  border: 1px solid #d1d6de; font-size: 0.9rem; min-width: 2.4rem;
  text-align: center; transition: background 100ms ease;
}
.pager-btn:hover, .pager-page:hover { background: #f1f3f6; }
.pager-btn.disabled { color: #b0b6c0; cursor: not-allowed; background: #f5f6f8; }
.pager-btn.disabled:hover { background: #f5f6f8; }
.pager-page.current { background: #1c6ed1; color: white; border-color: #1c6ed1; cursor: default; }
.pager-page.current:hover { background: #1c6ed1; }
.pager-ellipsis { color: #6a7280; padding: 0 0.3rem; font-size: 0.9rem; }

/* ----- Study Editor (designer/edit.html) ----- */
.editor-shell { max-width: 1280px; margin: 0 auto; padding-bottom: 6rem; }
.editor-header { display: flex; justify-content: space-between; align-items: flex-end;
  padding: 0.5rem 0 1.25rem; gap: 1rem; flex-wrap: wrap; }
.editor-title { margin: 0; font-size: 1.6rem; }
.editor-status { display: flex; gap: 0.5rem; align-items: center; }

.badge { display: inline-block; padding: 0.25rem 0.6rem; border-radius: 999px; font-size: 0.78rem; font-weight: 600; }
.badge-warn { background: #fff4d6; color: #7a5b00; border: 1px solid #f3dd9c; }
.badge-ok { background: #def5e6; color: #1d6b3a; border: 1px solid #b1deba; }

.editor-layout { display: grid; grid-template-columns: 320px 1fr; gap: 1.5rem; align-items: start; }
@media (max-width: 880px) { .editor-layout { grid-template-columns: 1fr; } }

.tree-pane { background: white; border-radius: 8px; padding: 0.75rem; box-shadow: 0 1px 3px rgba(0,0,0,0.05);
  position: sticky; top: 1rem; max-height: calc(100vh - 8rem); overflow-y: auto; }
.tree, .tree-children { list-style: none; padding: 0; margin: 0; }
.tree-children { padding-left: 1.1rem; border-left: 1px dashed #d8dde6; margin-left: 0.4rem; }
.tree-section { display: flex; align-items: center; justify-content: space-between; gap: 0.3rem; padding-right: 0.3rem; }
.tree-toggle { background: none; border: none; color: #303641; font: inherit; padding: 0.3rem 0.4rem;
  border-radius: 4px; cursor: pointer; text-align: left; flex: 1; }
.tree-toggle:hover { background: #f1f3f6; }
.tree-node { display: block; width: 100%; text-align: left; background: none; border: none; font: inherit;
  color: #1c1f23; padding: 0.4rem 0.6rem; border-radius: 4px; cursor: pointer; }
.tree-node:hover { background: #f1f3f6; }
.tree-node.active { background: #e7f0fa; color: #1a4a7d; font-weight: 600; }
.tree-node.tree-root { font-weight: 600; }
.tree-node.tree-leaf { color: #4a5160; }

/* Pastel rainbow per node kind — colored 4px left border accent + soft tint when
 * inactive, deeper tint when active. The active style overrides the kind-specific
 * background so the user always knows what's selected; the left-border keeps the
 * kind identifiable even at a glance through hover/active states. */
.tree-node.n-visit   { border-left: 4px solid #60a5fa; background: #eff6ff; }   /* blue */
.tree-node.n-form    { border-left: 4px solid #34d399; background: #ecfdf5; }   /* green */
.tree-node.n-role    { border-left: 4px solid #a78bfa; background: #f5f3ff; }   /* purple */
.tree-node.n-menu    { border-left: 4px solid #f472b6; background: #fdf2f8; }   /* pink */
.tree-node.n-subject { border-left: 4px solid #fbbf24; background: #fffbeb; }   /* amber */
.tree-node.n-visit:hover   { background: #dbeafe; }
.tree-node.n-form:hover    { background: #d1fae5; }
.tree-node.n-role:hover    { background: #ede9fe; }
.tree-node.n-menu:hover    { background: #fce7f3; }
.tree-node.n-subject:hover { background: #fef3c7; }
.tree-node.n-visit.active   { background: #bfdbfe; color: #1e40af; }
.tree-node.n-form.active    { background: #a7f3d0; color: #065f46; }
.tree-node.n-role.active    { background: #ddd6fe; color: #5b21b6; }
.tree-node.n-menu.active    { background: #fbcfe8; color: #9d174d; }
.tree-node.n-subject.active { background: #fde68a; color: #92400e; }
.tree-add { background: none; border: 1px dashed #c9ced6; border-radius: 4px; color: #6a7280;
  cursor: pointer; padding: 0.15rem 0.5rem; font-size: 0.85rem; }
.tree-add:hover { background: #f1f3f6; color: #1c6ed1; border-color: #1c6ed1; }
.tree-add.inline { width: 100%; text-align: left; padding: 0.3rem 0.6rem; margin: 0.15rem 0; }

.editor-pane { min-width: 0; }
.editor-panel { background: white; border-radius: 8px; padding: 1.5rem; box-shadow: 0 1px 3px rgba(0,0,0,0.05); }
.panel-header { display: flex; justify-content: space-between; align-items: center; gap: 1rem; margin-bottom: 1rem; flex-wrap: wrap; }
.panel-header h2 { margin: 0; font-size: 1.15rem; }
.panel-actions { display: flex; gap: 0.4rem; }
.panel-actions button { background: #f1f3f6; color: #303641; border: 1px solid #d8dde6; border-radius: 6px;
  padding: 0.35rem 0.8rem; font: inherit; font-size: 0.85rem; cursor: pointer; }
.panel-actions button:hover:not(:disabled) { background: #e7f0fa; border-color: #1c6ed1; color: #1c6ed1; }
.panel-actions button:disabled { opacity: 0.45; cursor: not-allowed; }
.panel-actions button.danger { background: #fdecea; color: #8d1e15; border-color: #f4c6c2; }
.panel-actions button.danger:hover { background: #f4c6c2; }

.tabs { display: flex; gap: 0.25rem; border-bottom: 1px solid #e3e7ee; margin-bottom: 1rem; }
.tab { background: none; border: none; padding: 0.55rem 0.95rem; font: inherit; cursor: pointer;
  color: #6a7280; border-bottom: 2px solid transparent; }
.tab:hover { color: #1c6ed1; }
.tab.active { color: #1c6ed1; border-bottom-color: #1c6ed1; font-weight: 600; }

.field-grid { display: grid; gap: 0.6rem; }
.field-row { display: grid; grid-template-columns: 220px 1fr; gap: 0.8rem; align-items: center; }
@media (max-width: 600px) { .field-row { grid-template-columns: 1fr; } }
.field-label { color: #303641; font-size: 0.9rem; font-weight: 500; }
.field-input input[type=text], .field-input input[type=number], .field-input select {
  width: 100%; padding: 0.45rem 0.6rem; border: 1px solid #c9ced6; border-radius: 6px; font: inherit; }
.field-input input[disabled] { background: #f1f3f6; color: #6a7280; }
.field-input input[type=color] { width: 3rem; height: 2rem; padding: 0; border: 1px solid #c9ced6; border-radius: 6px; }
.field-input input[type=checkbox] { width: 1.1rem; height: 1.1rem; }

.action-bar { position: fixed; bottom: 0; left: 0; right: 0; background: white;
  border-top: 1px solid #e3e7ee; padding: 0.85rem 1.5rem; display: flex; gap: 0.7rem; align-items: center;
  box-shadow: 0 -2px 8px rgba(0,0,0,0.04); z-index: 10; }
.action-bar .errors { list-style: none; margin: 0 auto 0 0; padding: 0; color: #8d1e15; font-size: 0.85rem; }
.action-bar button { background: #f1f3f6; color: #303641; border: 1px solid #d8dde6; border-radius: 6px;
  padding: 0.55rem 1.1rem; font: inherit; cursor: pointer; }
.action-bar button.primary { background: #1c6ed1; color: white; border-color: #1c6ed1; font-weight: 600; }
.action-bar button.primary:disabled { background: #99a3b3; border-color: #99a3b3; cursor: not-allowed; }
.action-bar button:disabled { opacity: 0.5; cursor: not-allowed; }

/* ----- Form Renderer (designer/form_preview.html) ----- */
.fpreview-toolbar { display: flex; align-items: center; gap: 0.75rem;
  margin-top: 0.4rem; flex-wrap: wrap; font-size: 0.92rem; }
.fpreview-toolbar select { padding: 0.25rem 0.5rem; border: 1px solid #c9ced6; border-radius: 4px;
  font: inherit; background: white; }
.btn-page { background: #f1f3f6; border: 1px solid #d8dde6; border-radius: 4px;
  width: 2rem; height: 2rem; cursor: pointer; font: inherit; }
.btn-page:hover:not(:disabled) { background: #e7f0fa; border-color: #1c6ed1; color: #1c6ed1; }
.btn-page:disabled { opacity: 0.4; cursor: not-allowed; }

.fstage-wrap { background: #f1f3f6; padding: 1rem; border-radius: 8px;
  overflow-x: auto; }
.fstage { background: white; box-shadow: 0 1px 4px rgba(0,0,0,0.1);
  position: relative; transform-origin: top left;
  /* Default to Arial — surveyXml is designed at Arial metrics on iPad. system-ui /
   * SF Pro / Segoe UI all kern wider, which causes long labels to overflow into
   * adjacent controls (e.g. "Does the patient have gingival inflammation?" pushing
   * past the Yes checkbox on Dental_Survey_Children_NEW p2). Liberation Sans is the
   * Linux fallback w/ matching metrics. Per-label `g="..."` overrides this default. */
  font-family: Arial, "Liberation Sans", "Helvetica Neue", Helvetica, sans-serif; }

.fctrl { position: absolute; box-sizing: border-box; }
/* Labels get a subtle negative letter-spacing to compensate for web Arial rendering
 * wider than iOS Arial — ~1.5% compression that's imperceptible in typical text but
 * meaningfully reclaims horizontal space when a label fills its allocated width
 * (e.g., "Does the patient have gingival inflammation?" not bleeding into Yes/No). */
/* iPad UILabel vertically centers text within its bounds by default; a plain block
   div doesn't. Use column flex + `safe center` so shorter text sits in the middle
   of the label rect (Open Camera / Missing Teeth captions look right) but multi-
   line text taller than its container falls back to top-alignment instead of being
   clipped from both ends — matching iOS's "show top, truncate bottom" behavior for
   long instruction labels like "Please return to Student Manager form to ...".
   text-align on the div still handles horizontal alignment of wrapped lines.
   The font-family stack is set per-element by the renderer (Arimo first to mirror
   iOS Arial advance widths exactly); no letter-spacing tweak is needed since the
   metric compatibility means line breaks already match iOS one-for-one. */
.ftext { display: flex; flex-direction: column; justify-content: safe center;
  white-space: pre-wrap; line-height: 1.15; overflow: hidden; }
.fed { background: white; border: 1px solid #303641; padding: 2px 4px;
  font-family: inherit; box-sizing: border-box; }
.fro { background: #e3e7ee; border: none; padding: 2px 4px; color: #1c1f23;
  box-sizing: border-box; }
textarea.fed, textarea.fro { resize: none; overflow: hidden; }

.frad { display: flex; align-items: center; justify-content: center;
  border: 2px solid #303641; border-radius: 50%; box-sizing: border-box; }
.frad-dot { width: 60%; height: 60%; border-radius: 50%; }
.frad-dot.on { background: #1d6b3a; }
.fcheck { display: flex; align-items: center; justify-content: center;
  border: 2px solid #303641; box-sizing: border-box; }
/* Tap-to-fire surface — iOS NEStaticControl lights up any static control
 * (label / shape / image) with attached Field-triggers as tappable. Cursor
 * + a subtle :active highlight mirrors iOS's black 2px touch highlight
 * without needing a JS state flag. Pure CSS so it works in view mode. */
.ftap {
  cursor: pointer;
  user-select: none;
  transition: filter 80ms ease;
}
.ftap:hover  { filter: brightness(1.08); }
.ftap:active { filter: brightness(0.92); outline: 2px solid rgba(0, 0, 0, 0.45); outline-offset: -1px; }

/* SVG-rendered radios using the <RadioDisplay> palette path data. The path is
 * drawn in 0..1 unit space and stretched to fill the control via viewBox. */
.fradsvg { overflow: visible; }
/* Embedded image control — surveyXml's <h> control with a matching <ae> blob. */
.fimg { object-fit: contain; }

.fshape { box-sizing: border-box; }
.fph { display: flex; align-items: center; justify-content: center; gap: 0.3rem;
  background: repeating-linear-gradient(45deg, #f1f3f6, #f1f3f6 6px, #e8ebf0 6px, #e8ebf0 12px);
  color: #6a7280; font-size: 0.78rem; border: 1px dashed #c9ced6; border-radius: 4px; }
.fph-sig { color: #1a4a7d; }
.fph-photo { color: #4a5160; }
.fph-image { color: #4a5160; }
.fph-unk { color: #8d1e15; background: repeating-linear-gradient(45deg, #fdecea, #fdecea 6px, #f4c6c2 6px, #f4c6c2 12px); }

/* Field-name annotation badges (overlay layer when toggle is Regular or Full) */
.seg-control { display: inline-flex; border: 1px solid #c9ced6; border-radius: 6px; overflow: hidden; }
.seg-control button { background: white; color: #303641; border: none; padding: 0.3rem 0.7rem;
  font: inherit; font-size: 0.85rem; cursor: pointer; border-right: 1px solid #c9ced6; }
.seg-control button:last-child { border-right: none; }
.seg-control button:hover { background: #f1f3f6; }
.seg-control button.active { background: #1c6ed1; color: white; }

.fanno {
  position: absolute;
  pointer-events: none;          /* never intercept clicks/hover */
  background: rgba(255, 215, 0, 0.92);
  color: #1c1f23;
  font: 9px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  padding: 1px 4px;
  border-radius: 0 0 3px 0;
  border: 1px solid rgba(120, 95, 0, 0.5);
  border-top: none; border-left: none;
  white-space: nowrap;
  max-width: 240px;
  overflow: hidden;
  text-overflow: ellipsis;
  z-index: 99999;
}
/* Alias badge — same shape as the yellow fieldname badge but tinted orange,
   shown only in 'full' annotation mode for controls whose value is derived
   from tblSubjectDetail via the iOS `s` (kAttDetailalias) attribute. */
.fanno-alias {
  background: rgba(255, 158, 64, 0.92);
  border-color: rgba(150, 75, 0, 0.55);
}

/* Trigger / JS diagnostics panel in the form preview toolbar. Collapsed
   by default — click to expand the per-block stats and any JS errors. */
.trigger-debug { font-size: 0.78rem; margin-left: 0.5rem; }
.trigger-debug summary { cursor: pointer; padding: 0.3rem 0.6rem;
  background: #f1f3f6; border: 1px solid #d1d6de; border-radius: 6px;
  color: #303641; user-select: none; }
.trigger-debug summary:hover { background: #e8ebf0; }
.trigger-debug[open] summary { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.trigger-debug-body { background: white; border: 1px solid #d1d6de; border-top: none;
  border-radius: 0 0 6px 6px; padding: 0.7rem 1rem; max-width: 600px;
  max-height: 400px; overflow-y: auto; }
.trigger-debug-body dl { margin: 0; display: grid;
  grid-template-columns: max-content 1fr; gap: 0.3rem 0.8rem; }
.trigger-debug-body dt { color: #6a7280; font-weight: 600; }
.trigger-debug-body dd { margin: 0; }
.trigger-debug-body code { font-size: 0.78rem; background: #f1f3f6;
  padding: 0.1rem 0.3rem; border-radius: 3px; }
.trigger-debug-body pre { margin: 0.3rem 0 0; padding: 0.5rem;
  background: #1c2c40; color: #e3e7ee; border-radius: 4px;
  font-size: 0.75rem; overflow-x: auto; }
.trigger-debug-err { color: #b32626; }
.trigger-debug-errlist { margin: 0.3rem 0 0; padding-left: 1.2rem; }
.trigger-debug-errlist li { margin-bottom: 0.4rem; }
.trigger-debug-errmsg { color: #b32626; }

/* ---------------------------------------------------------------------------
   Live-edit mode styling.
   The edit surface reuses the read-only renderer's layout; these rules just
   tint the chrome (EDIT badge, mode-switch link, save indicator, submit bar)
   and add affordances on editable controls (focus outlines, clickable radio
   cursor). Inputs remain disabled on read-only controls (iOS `ab` attr)
   even inside edit mode, matching iPad behavior.
   ------------------------------------------------------------------------- */
.badge-edit {
  display: inline-block;
  margin-left: 0.4rem;
  padding: 0.1rem 0.5rem;
  font: 600 0.7rem ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  background: #d63c28;
  color: white;
  border-radius: 3px;
  vertical-align: middle;
  letter-spacing: 0.05em;
}
.mode-switch-link {
  font-size: 0.85rem;
  color: #1c6ed1;
  text-decoration: none;
  padding: 0.15rem 0.4rem;
  border-radius: 4px;
}
.mode-switch-link:hover { background: #eaf2fc; text-decoration: underline; }

/* Save-state indicator pills (right-aligned in toolbar). */
.save-indicator {
  font: 0.8rem ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  padding: 0.15rem 0.55rem;
  border-radius: 10px;
}
.save-indicator-inflight { background: #fff6d8; color: #7c6400; border: 1px solid #e9c96a; }
.save-indicator-error    { background: #fdecea; color: #8d1e15; border: 1px solid #f4c6c2;
  max-width: 360px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Editable textbox/textarea — keep visual parity with .fed but lift the
 * `disabled` grey-out in edit mode (the `disabled` attribute is what drives
 * browser-default grey; once removed the base .fed style renders fine). */
.fed:focus { outline: 2px solid #1c6ed1; outline-offset: -1px; }

/* Radio SVG in edit mode — pointer cursor so users know they can tap the
 * tooth/marker shapes. Read-only controls keep the default cursor. */
.fradsvg-edit { cursor: pointer; }
.fradsvg-edit:hover path[fill="transparent"] { fill: rgba(28, 110, 209, 0.10); }

/* Submit bar lives below the fstage in edit mode. Sticky to stay visible
 * while the user scrolls through long forms; subtle shadow delimits it from
 * the stage above. */
.form-submit-bar {
  position: sticky; bottom: 0;
  padding: 0.8rem 1.2rem;
  background: white;
  box-shadow: 0 -2px 6px rgba(0,0,0,0.08);
  display: flex; align-items: center; gap: 1rem;
  z-index: 10;
}
.btn-primary {
  background: #1c6ed1; color: white; border: none;
  padding: 0.5rem 1.2rem; border-radius: 6px;
  font-weight: 600; cursor: pointer;
}
.btn-primary:hover:not(:disabled) { background: #165ab0; }
.btn-primary:disabled { background: #9fb7d4; cursor: wait; }

.form-submit-errors {
  color: #8d1e15; background: #fdecea; border: 1px solid #f4c6c2;
  padding: 0.5rem 0.8rem; border-radius: 6px; font-size: 0.9rem;
}
.form-submit-errors ul { margin: 0.3rem 0 0; padding-left: 1.2rem; }
.form-spawn-notice {
  color: #1a4a7d; background: #eaf2fc; border: 1px solid #a8c8ea;
  padding: 0.5rem 0.8rem; border-radius: 6px; font-size: 0.9rem;
}

/* ---------------------------------------------------------------------------
   Asterisk-owner iPad strip — centered in the topbar (see .topbar-center).
   Per tile:
     ┌──────────────────────────┐
     │  [iPad silhouette]       │   ← owner name overlaid on the screen
     │   Front Desk             │
     └──────────────────────────┘
        ALL SYNCED / NEEDS SYNC   ← two-state text label, colored

   Aura around the iPad is GREEN when synced, ORANGE otherwise. Sub-state
   (up / down / both / awaiting) still lives in the hover tooltip but no
   longer drives distinct colors — the user asked for just the two buckets.
   --------------------------------------------------------------------------- */
.ipad-strip-topbar {
  display: flex;
  flex-wrap: nowrap;       /* topbar = one row only */
  gap: 0.55rem;
  overflow-x: auto;
  max-width: 100%;
  padding: 0 0.25rem;
  scrollbar-width: thin;
  scrollbar-color: #48536a transparent;
}
.ipad-strip-topbar::-webkit-scrollbar        { height: 4px; }
.ipad-strip-topbar::-webkit-scrollbar-thumb  { background: #48536a; border-radius: 2px; }
.ipad-strip-topbar::-webkit-scrollbar-track  { background: transparent; }

.ipad-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  min-width: 72px;
  line-height: 1.05;
}

.ipad-frame {
  position: relative;
  width: 72px;
  height: 48px;              /* 3:2, matches the resized iPadDevice PNG */
  display: flex;
  align-items: center;
  justify-content: center;
  transition: filter 180ms ease;
}

/* Two-state aura — green = all synced, orange = needs sync. */
.ipad-tile.ipad-synced     .ipad-frame {
  filter: drop-shadow(0 0 6px rgba( 94, 190,  86, 0.95));
}
.ipad-tile.ipad-needs-sync .ipad-frame {
  filter: drop-shadow(0 0 6px rgba(255, 152,  75, 0.95));
}

.ipad-silhouette {
  width: 100%;
  height: 100%;
  object-fit: contain;
  pointer-events: none;
}

/* Device name overlaid on the iPad's screen area. Absolutely positioned so
   it sits inside the silhouette's dark "glass" region, centered, truncated
   if the owner string is long. */
.ipad-name-overlay {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 0.6rem;
  font-weight: 600;
  color: #f5f6f8;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.85);
  max-width: 85%;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
}

/* Status label beneath the iPad — colored per sync bucket. */
.ipad-status-label {
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  white-space: nowrap;
}
.ipad-tile.ipad-synced     .ipad-status-label { color: #9fe870; }   /* lime */
.ipad-tile.ipad-needs-sync .ipad-status-label { color: #ffab5c; }   /* orange */

@media (max-width: 720px) {
  .ipad-strip-topbar { gap: 0.4rem; }
  .ipad-frame        { width: 60px; height: 40px; }
  .ipad-tile         { min-width: 62px; }
  .ipad-name-overlay, .ipad-status-label { font-size: 0.54rem; }
}

/* ---------------------------------------------------------------------------
   SpeechAI Telemetry — explainer card + stat-tile captions.
   Keeps the KPIs readable by staff who don't live in the metrics day-to-day.
   --------------------------------------------------------------------------- */
.telemetry-explain details {
  cursor: default;
}
.telemetry-explain summary {
  cursor: pointer;
  font-size: 0.95rem;
  padding: 0.1rem 0;
  color: #3a3f4b;
  list-style: revert;      /* show the disclosure triangle */
}
.telemetry-explain summary:hover { color: #b65a3a; }
.telemetry-explain .explain-body {
  margin-top: 0.9rem;
  padding-top: 0.8rem;
  border-top: 1px dashed #d1d6de;
  font-size: 0.92rem;
  line-height: 1.55;
  color: #303641;
  max-width: 920px;
}
.telemetry-explain .explain-body h3 {
  margin-top: 1.2rem;
  margin-bottom: 0.4rem;
  font-size: 1rem;
  color: #2b2e3a;
}
.telemetry-explain .explain-body ol,
.telemetry-explain .explain-body ul.explain-buckets {
  margin: 0.4rem 0 0.6rem 1.2rem;
  padding: 0;
}
.telemetry-explain .explain-body ul.explain-buckets li { margin-bottom: 0.25rem; }
.telemetry-explain dl.explain-terms {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.35rem 1rem;
  margin: 0.3rem 0 0.6rem;
}
.telemetry-explain dl.explain-terms dt {
  font-weight: 600;
  color: #2b2e3a;
}
.telemetry-explain dl.explain-terms dd { margin: 0; }
.telemetry-explain code {
  background: #f1f3f6;
  padding: 0.05rem 0.3rem;
  border-radius: 3px;
  font-size: 0.85em;
}

/* Stat-tile captions — subtle line under the number's label. */
.stat .stat-sub {
  margin-top: 0.1rem;
  font-size: 0.72rem;
  line-height: 1.25;
}

/* Stats-row pastel — widen gaps a touch so the colored tiles breathe.
   Tile color classes (.panel-tint-*) are defined earlier; this just tunes
   the grid layout when the pastel variant is in use. */
.stats-row-pastel { gap: 0.8rem; }
.stats-row-pastel .stat {
  /* Soften the default white-card border on tinted stat tiles. */
  box-shadow: 0 1px 2px rgba(0,0,0,0.04);
}

/* ---------------------------------------------------------------------------
   Recent evaluations table — dense per-bundle detail. Sized for content
   rather than squeezed to fit the card; horizontal scroll inside a wrapper
   keeps the rest of the report readable even when the transcript is long.
   --------------------------------------------------------------------------- */
.telemetry-recent .table-scroll {
  overflow-x: auto;
  margin-top: 0.3rem;
}
.telemetry-recent-table { font-size: 0.82rem; }
.telemetry-recent-table td { vertical-align: top; padding: 0.45rem 0.6rem; }
.telemetry-recent-table th { font-size: 0.78rem; white-space: nowrap; }

.transcript-cell { max-width: 380px; }
.transcript-live { font-weight: 500; color: #2b2e3a; }
.transcript-gold {
  margin-top: 0.2rem;
  color: #1f66c1;
  border-left: 2px solid #a7c4f0;
  padding-left: 0.45rem;
  font-size: 0.78rem;
}

/* Score color stripes — quick visual read without squinting at percentages. */
.score-good { color: #2e7a2e; font-weight: 600; }
.score-mid  { color: #8a6b17; }
.score-bad  { color: #b32626; font-weight: 600; }

/* ---------------------------------------------------------------------------
   Remove the scrollbar from the topbar iPad strip — per UX feedback the
   strip fits naturally in the topbar's center region until the clinic has
   a lot of iPads. Let the grid handle overflow; no custom scrollbar.
   --------------------------------------------------------------------------- */
.ipad-strip-topbar {
  overflow: visible;
  max-width: none;
}
.ipad-strip-topbar::-webkit-scrollbar        { display: none; }

/* ---------------------------------------------------------------------------
   Device report card — list / detail / super-sync log.
   Minimal additions on top of the existing `.card`, `.field-grid`, `.badge`,
   and `.data-table` primitives. Keep scoped to device-specific affordances:
   state pills, result pills, registration-code chip, chevron styling.
   --------------------------------------------------------------------------- */

/* Copyable registration code — visually obvious it's distinct from other code snippets. */
.reg-code {
  background: #0f1a2b;
  color: #d9e6ff;
  padding: 0.15rem 0.55rem;
  border-radius: 4px;
  font-weight: 600;
  letter-spacing: 0.04em;
  margin-right: 0.3rem;
}

/* Badge variants unique to devices. */
.badge.badge-udid-cleared {
  background: #fff3d6;
  color: #7c5e00;
  border: 1px solid #e9c96a;
}

/* Sync-state pills — one per tblIpadStatus.syncState value. Palette borrows
   from the existing status color tokens so the device card reads consistently
   with the subject list. */
.badge.state-idle,
.badge.state-ready       { background: #e8ebf0; color: #303641; }
.badge.state-uploading,
.badge.state-downloading { background: #dfeafc; color: #1a4a7d; }
.badge.state-done,
.badge.state-complete    { background: #d7ecd9; color: #1d6b3a; }
.badge.state-error,
.badge.state-errored     { background: #fdecea; color: #8d1e15; }

/* Sync-event result pills. */
.badge.result-ok         { background: #d7ecd9; color: #1d6b3a; }
.badge.result-running    { background: #dfeafc; color: #1a4a7d; }
.badge.result-cancelled,
.badge.result-timeout    { background: #fff3d6; color: #7c5e00; border: 1px solid #e9c96a; }
.badge.result-error,
.badge.result-incomplete { background: #fdecea; color: #8d1e15; }

/* Sync-history chevron (<details>). Keeps the device card compact by default;
   expanded state shows the full 6-month table without a page navigation. */
.sync-history-details > summary {
  cursor: pointer;
  user-select: none;
  padding: 0.3rem 0;
}
.sync-history-details > summary:hover { color: #1c6ed1; }
.sync-history-details[open] > summary { margin-bottom: 0.8rem; }

/* Super-sync log — collapsible card per orchestration run. */
.super-sync-run summary {
  cursor: pointer;
  user-select: none;
  padding: 0.2rem 0;
}
.super-sync-run summary:hover { color: #1c6ed1; }
.super-sync-body { margin-top: 0.8rem; }
.super-sync-body h3 {
  font-size: 0.95rem;
  color: #6a7280;
  margin: 0.8rem 0 0.3rem;
}
.planned-order {
  margin: 0;
  padding-left: 1.4rem;
  font-size: 0.85rem;
  color: #4a5160;
}

/* Inline badge list used for site-access chips on the device detail card. */
.inline-badges {
  list-style: none;
  padding: 0; margin: 0;
  display: flex; flex-wrap: wrap; gap: 0.4rem 0.6rem;
  align-items: center;
}
.inline-badges li { display: inline-flex; gap: 0.3rem; align-items: baseline; }

/* Compact `.small` inside `<code>` for version strings in tight table cells. */
code.small { font-size: 0.78rem; }

/* Dashboard roadmap card — lightweight content panel listing the next few
   initiatives on deck. Keeps the dashboard scan-able without a full tracker. */
.roadmap-card {
  background: #f7f4ff;
  border-left: 4px solid #7a5bff;
}
.roadmap-list {
  margin: 0;
  padding-left: 1.4rem;
  line-height: 1.7;
  color: #303641;
}
.roadmap-list li {
  padding: 0.1rem 0;
}
.roadmap-list li:first-child {
  font-weight: 600;
}
