:root {
  --bg: #0f1420;
  --panel: #171e2e;
  --panel2: #1f2940;
  --text: #e6ebf4;
  --muted: #8b96ab;
  --accent: #4f7cff;
  --accent-hover: #6b90ff;
  --danger: #e5484d;
  --ok: #46a758;
  --warn: #f5a524;
  --border: #2a3550;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: "Segoe UI", system-ui, sans-serif;
  background: var(--bg);
  color: var(--text);
}

.hidden { display: none !important; }
.muted { color: var(--muted); }
.error { color: var(--danger); min-height: 1.2em; }

/* Clean Enterprise Login View */
.login-view {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #0f172a;
  padding: 24px;
}

.login-card {
  width: 100%;
  max-width: 380px;
  background: #1e293b;
  border: 1px solid #334155;
  border-radius: 12px;
  padding: 32px 28px;
  display: flex;
  flex-direction: column;
  gap: 20px;
  box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.5), 0 8px 10px -6px rgba(0, 0, 0, 0.5);
}

.login-brand-header {
  margin-bottom: 2px;
}
.login-title {
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: #f8fafc;
  margin: 0;
}
.login-subtitle {
  font-size: 13px;
  color: #94a3b8;
  margin: 4px 0 0;
  line-height: 1.4;
}

.form-field-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.form-field-group label {
  font-size: 13px;
  font-weight: 500;
  color: #cbd5e1;
}

.input-icon-wrap {
  position: relative;
  display: flex;
  align-items: center;
}

.input-icon-wrap input {
  width: 100%;
  background: #0f172a;
  border: 1px solid #334155;
  border-radius: 8px;
  color: #f8fafc;
  padding: 10px 38px 10px 12px;
  font-size: 14px;
  outline: none;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.input-icon-wrap input:focus {
  border-color: #3b82f6;
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);
}

.pwd-toggle-btn {
  position: absolute;
  right: 8px;
  background: transparent;
  border: none;
  cursor: pointer;
  font-size: 14px;
  padding: 4px 6px;
  border-radius: 4px;
  opacity: 0.6;
  transition: opacity 0.15s;
}
.pwd-toggle-btn:hover {
  opacity: 1;
}

/* Enterprise Primary Login Button */
.login-btn-primary {
  width: 100%;
  height: 42px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #2563eb;
  border: none;
  border-radius: 8px;
  color: #ffffff;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background-color 0.15s ease, transform 0.08s ease;
}
.login-btn-primary:hover {
  background: #1d4ed8;
}
.login-btn-primary:active {
  background: #1e40af;
  transform: scale(0.99);
}
.login-btn-primary:disabled {
  opacity: 0.75;
  cursor: not-allowed;
  transform: none;
}

/* Sign-in page ka single download link (operator request: download sirf yahan). */
.login-download-link {
  display: block;
  margin-top: 10px;
  text-align: center;
  font-size: 12.5px;
  color: #58a6ff;
  text-decoration: none;
}
.login-download-link:hover { text-decoration: underline; }

/* Spinner */
.btn-spinner {
  width: 15px;
  height: 15px;
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-top-color: #ffffff;
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
  display: inline-block;
  margin-right: 8px;
}
@keyframes spin {
  to { transform: rotate(360deg); }
}

/* Error Banner */
.error-banner {
  background: rgba(239, 68, 68, 0.12);
  border: 1px solid rgba(239, 68, 68, 0.35);
  border-radius: 6px;
  padding: 9px 12px;
  font-size: 12.5px;
  color: #fca5a5;
  line-height: 1.4;
}

/* Global Base Controls */
input, button {
  font: inherit;
  border-radius: 8px;
}
input {
  background: var(--panel2);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 9px 12px;
}
input:focus { outline: 1px solid var(--accent); }

button {
  cursor: pointer;
  border: 1px solid var(--border);
  background: var(--panel2);
  color: var(--text);
  padding: 8px 14px;
}
button:hover { background: #27334f; }
button.primary, #add-device-btn { 
  background: var(--accent); 
  border-color: var(--accent); 
  transition: all 0.2s ease;
}
button.primary:hover, #add-device-btn:hover { 
  background: var(--accent-hover); 
  box-shadow: 0 4px 12px rgba(79, 124, 255, 0.35);
}
button.ghost { background: transparent; }
button.danger { background: var(--danger); border-color: var(--danger); }
button.danger:hover { background: #ff5f63; }

/* ---------- topbar ---------- */
/* Topbars wrap at any width: the session header carries seven controls plus
   the device name, which does not fit on one line on smaller laptops. The
   workspace is height-agnostic now, so a second line is harmless. */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  padding: 12px 20px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  gap: 12px;
}
.topbar-right { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; justify-content: flex-end; }
.download-agent-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  background: rgba(88, 166, 255, 0.1);
  color: #58a6ff;
  border: 1px solid rgba(88, 166, 255, 0.3);
  border-radius: 6px;
  text-decoration: none;
  font-size: 13px;
  font-weight: 500;
  transition: all .15s ease;
}
.download-agent-btn:hover {
  background: rgba(88, 166, 255, 0.2);
  border-color: #58a6ff;
  color: #fff;
}

/* ---------- devices table ---------- */
main { padding: 20px; }
#devices-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
}
#devices-table th, #devices-table td {
  text-align: left;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  font-size: 14px;
}
#devices-table th { color: var(--muted); font-weight: 600; font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; }
#devices-table tr:last-child td { border-bottom: none; }

.status-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
}
.status-badge::before { content: ""; width: 8px; height: 8px; border-radius: 50%; }
.status-online { background: rgba(70,167,88,0.15); color: var(--ok); }
.status-online::before { background: var(--ok); }
.status-online-no-access { background: rgba(245,165,36,0.15); color: var(--warn); }
.status-online-no-access::before { background: var(--warn); }
.status-offline { background: rgba(139,150,171,0.15); color: var(--muted); }
.status-offline::before { background: var(--muted); }
.status-expired { background: rgba(229,72,77,0.15); color: var(--danger); }
.status-expired::before { background: var(--danger); }

.actions-col { width: 55%; }
td.actions { display: flex; gap: 6px; flex-wrap: wrap; }
td.actions button { font-size: 12px; padding: 5px 10px; }

/* ---------- dialogs ---------- */
dialog {
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 24px;
  min-width: 340px;
  max-width: calc(100vw - 24px);
}
dialog::backdrop { background: rgba(0,0,0,0.6); }
dialog h2 { margin-top: 0; font-size: 17px; }
dialog label { display: block; margin-bottom: 6px; font-size: 13px; color: var(--muted); }
dialog input { width: 100%; }
/* Session length: a number plus its unit side by side. The unit dropdown is not
   a cosmetic toggle — app.js multiplies by 60 for hours before the value reaches
   the relay, which only ever speaks minutes. */
.duration-row { display: flex; gap: 8px; align-items: center; }
.duration-row input { flex: 1 1 auto; width: auto; min-width: 0; }
.duration-row select { flex: 0 0 auto; height: 100%; }
/* The unit labels sit next to their own field, so "2 hr 30 min" reads as one
   length instead of two numbers. */
.duration-row .duration-unit { flex: 0 0 auto; color: var(--muted, #9aa4b2); font-size: 13px; }
.dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 16px;
}
.pairing-code {
  font-family: Consolas, monospace;
  font-size: 32px;
  letter-spacing: 0.35em;
  text-align: center;
  background: var(--panel2);
  border: 1px dashed var(--border);
  border-radius: 8px;
  padding: 12px;
  margin: 16px 0;
  color: var(--accent-hover);
  user-select: all;
}

/* ---------- session view ---------- */
#session-view {
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  position: relative;
  overflow: hidden;
}
.session-topbar { position: relative; z-index: 5; }
.session-info { display: flex; align-items: center; gap: 16px; min-width: 0; }
#session-device-name { font-weight: 700; }
.timer {
  font-family: Consolas, monospace;
  font-size: 18px;
  background: var(--panel2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 4px 12px;
}
.timer.low { color: var(--danger); border-color: var(--danger); }

/* ---------- Session Workspace: Side-by-Side Layout ---------- */
/* The workspace simply takes the height that is left under the topbar. It used
   to be pinned to "100dvh - 54px", which broke on any screen where the topbar
   wraps onto a second line (small laptops, high DPI, narrow windows) and cut
   the bottom of the canvas/sidebar off. */
.session-workspace {
  flex: 1 1 auto;
  display: flex;
  flex-direction: row;
  min-height: 0;
  overflow: hidden;
  position: relative;
  background: #060911;
}

.canvas-wrap {
  position: relative;
  flex: 1;
  min-width: 0;
  min-height: 0;
  height: 100%;
  max-height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #05070d;
  overflow: hidden;
}

/* Live WebRTC video. While live video owns the picture this element PRESENTS it
   (`.canvas-wrap.rtc-live` below), sized to the canvas' own rendered box by the
   dashboard so the two surfaces cannot disagree about where the screen is. The
   alternative — copying every decoded frame into #screen-canvas with drawImage
   — cost a full-screen 1920x1080 resample per frame on the main thread for a
   picture the compositor already had.

   Outside `.rtc-live` it is only the decoder sink: kept on-screen, full-size and
   effectively invisible so Chromium never throttles decoding of the peer's
   stream before the agent's verdict says the picture has moved there. */
#rtc-video {
  position: absolute;
  inset: 0;
  margin: auto; /* centres it in the box the dashboard gives it */
  width: 100%;
  height: 100%;
  object-fit: contain; /* never distort a stream whose size differs from the pane */
  opacity: 0.002;
  pointer-events: none;
  z-index: 0;
}

/* Set by the dashboard for exactly as long as live video owns the picture: the
   video presents the frames, and the canvas stops being the picture surface —
   it keeps the pointer coordinates and stays on top, so it must lose both its
   opaque background and (done in JS) the pixels of the last frame it painted. */
.canvas-wrap.rtc-live #rtc-video {
  opacity: 1;
}

.canvas-wrap.rtc-live #screen-canvas {
  background: transparent;
}

/* The operator's own pointer IS the remote pointer: the coordinates this canvas
   sends are exactly where the native cursor arrow sits, so the arrow is both the
   zero-latency feedback for aiming and the icon the operator already knows. The
   drawn crosshair + ring this used to show were a second, invented cursor: the
   "small circle and plus" an operator could not aim with (the real pointer is in
   the picture Chromium captures, so nothing has to be drawn over it). The cursor
   rule here is a deliberate choice of ONE cursor, not a missing style. */
#screen-canvas {
  position: relative;
  z-index: 1;
  background: #000;
  box-shadow: 0 0 40px rgba(0, 0, 0, 0.9);
  max-width: 100%;
  max-height: 100%;
  cursor: default;
  object-fit: contain;
}

.session-status {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  color: var(--muted);
  background: rgba(5, 7, 13, 0.85);
  z-index: 15;
}

/* Admin-side HUD preview: mirrors what the candidate sees. Its box is synced
   to the canvas' rendered rectangle from JS (left/top/width/height), so anchors
   and the 33% text column match the candidate's screen — never the letterbox.
   Inside it the same layers as agent/overlay.html are stacked in the same order:
   the text column (#hud-preview-column == #hud-container), the plate that hugs
   the text (#hud-preview-plate == #hud-editor), the text itself
   (#hud-preview-text == #hud-text-layer) and the continuation strip
   (#hud-preview-strip == #hud-overflow-note). Every size comes from
   hud-contract.js — the file the overlay itself reads — scaled to the canvas by
   JS, so there is no second set of numbers to drift. */
.hud-preview-overlay {
  position: absolute;
  z-index: 5;
  pointer-events: none;
  overflow: hidden;
}
#hud-preview-column {
  position: absolute;
  /* width, like every other size here, is set from hud-contract.js (the same
     widthPct the overlay is sent) — never a second copy of the number. */
}
/* Font family, size, line height, radius, padding, background and the screen cap
   are painted from hud-contract.js (paintPlate / plateCapPx), so this rule holds
   only what the contract does not own: how the plate is laid out. */
#hud-preview-plate {
  position: relative;
  width: fit-content;
  max-width: 100%;
  white-space: normal;
  word-break: break-word;
  color: #ffffff;
  overflow: hidden;
  pointer-events: none;
  transition: background-color 0.12s linear;
}
#hud-preview-text {
  display: block;
  /* `pre-wrap` belongs to the ANSWER, not to the plate: the answer keeps its own
     newlines, while the markup's indentation between the plate's children
     collapses instead of becoming blank line boxes above and below the text. */
  white-space: pre-wrap;
  word-break: break-word;
  pointer-events: none;
}
/* Same honesty strip as the candidate's (#hud-overflow-note): shown only while
   the text is really clipped, legible whatever the plate's colour/alpha is. Its
   wording, colours, padding, type and radius are painted from hud-contract.js
   (paintStrip), which is what makes it the candidate's strip; only where it sits
   lives here. */
#hud-preview-strip {
  display: none;
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  pointer-events: none;
}
#hud-preview-plate.overflowing #hud-preview-strip { display: block; }

.admin-locked-badge {
  position: absolute;
  top: 14px;
  left: 14px;
  background: rgba(79, 124, 255, 0.92);
  color: #ffffff;
  padding: 6px 14px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.5px;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.5);
  pointer-events: none;
  z-index: 20;
  animation: pulse-blue 2s infinite;
}

@keyframes pulse-blue {
  0%, 100% { opacity: 0.95; }
  50% { opacity: 0.7; }
}

#lock-admin-btn.active {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent-hover);
  font-weight: 700;
}

#lock-user-btn.locked {
  background: var(--danger);
  color: #fff;
  border-color: var(--danger);
  font-weight: 700;
  animation: pulse-danger 2s infinite;
}

@keyframes pulse-danger {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.8; }
}

/* ---------- Persistent Control Sidebar ---------- */
/* Fluid width: the 390px fixed sidebar ate too much of a 1024-1280px laptop
   screen. It keeps a comfortable minimum, follows the viewport, and stacks
   under the canvas below 900px (see the media queries at the end). */
.admin-sidebar {
  width: clamp(320px, 32vw, 400px);
  min-width: 320px;
  flex: 0 0 clamp(320px, 32vw, 400px);
  min-height: 0;
  height: 100%;
  max-height: 100%;
  flex-shrink: 0;
  background: var(--panel);
  border-left: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  overflow-y: auto !important;
  overflow-x: hidden;
  padding: 12px;
  padding-bottom: 80px; /* Extra bottom breathing space so all cards scroll into view */
  gap: 12px;
  z-index: 10;
  scrollbar-width: thin;
  scrollbar-color: #4a5d87 rgba(0, 0, 0, 0.2);
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

.admin-sidebar::-webkit-scrollbar {
  width: 8px;
}
.admin-sidebar::-webkit-scrollbar-track {
  background: rgba(0, 0, 0, 0.2);
}
.admin-sidebar::-webkit-scrollbar-thumb {
  background: #4a5d87;
  border-radius: 4px;
}
.admin-sidebar::-webkit-scrollbar-thumb:hover {
  background: var(--accent);
}

/* Accordions */
.sidebar-accordion {
  background: var(--panel2);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  flex-shrink: 0; /* Never collapse when children expand */
  transition: border-color 0.2s ease;
}

.sidebar-accordion.open {
  border-color: rgba(79, 124, 255, 0.4);
}

/* AI Accordion Highlights */
#ai-accordion {
  border-color: rgba(79, 124, 255, 0.55);
  box-shadow: 0 0 16px rgba(79, 124, 255, 0.08);
}
#ai-accordion.open {
  border-color: #4f7cff;
}
#ai-accordion .accordion-header {
  background: linear-gradient(90deg, rgba(79, 124, 255, 0.15) 0%, rgba(16, 185, 129, 0.1) 100%);
}
#ai-accordion .accordion-header:hover {
  background: linear-gradient(90deg, rgba(79, 124, 255, 0.22) 0%, rgba(16, 185, 129, 0.16) 100%);
}

.accordion-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 11px 14px;
  background: rgba(255, 255, 255, 0.025);
  cursor: pointer;
  user-select: none;
  border-bottom: 1px solid transparent;
  gap: 8px;
  flex-shrink: 0;
}

.accordion-header:hover {
  background: rgba(255, 255, 255, 0.05);
}

.sidebar-accordion.open .accordion-header {
  border-bottom-color: var(--border);
}

.accordion-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
}

.accordion-arrow {
  font-size: 10px;
  transition: transform 0.2s ease;
  color: var(--muted);
  display: inline-block;
}

.sidebar-accordion:not(.open) .accordion-arrow {
  transform: rotate(-90deg);
}

.sidebar-accordion:not(.open) .accordion-body {
  display: none;
}

.accordion-body {
  padding: 12px;
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  gap: 10px;
}

.sidebar-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.card-label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--muted);
}

.card-label-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--muted);
}

.card-btn-row {
  display: flex;
  gap: 8px;
}

.card-btn-row button {
  flex: 1;
  padding: 7px 10px;
  font-size: 12px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

.sidebar-hint {
  font-size: 11px;
  margin: 0;
  line-height: 1.4;
  color: var(--muted);
}

/* Voice: compact pinned bar (Meet-style). Pinned to the top of the sidebar so
   a mute is never more than one click away mid-session. Audio itself starts
   with the session; these are the two mutes plus the listening volume. */
.voice-bar {
  position: sticky;
  top: 0;
  z-index: 4;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 12px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
}

.voice-bar-head {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* Collapse caret: poora options-block chhupa leta hai — voice bar collapsed
   state mein sirf ek patli head line leta hai (operator request: space). */
.voice-collapse-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 5px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  flex: none;
}
.voice-collapse-btn:hover {
  color: var(--fg);
  border-color: var(--muted);
}

.voice-start-btn {
  margin-left: auto;
  padding: 2px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: rgba(88, 166, 255, 0.12);
  color: var(--fg);
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
  flex: none;
}
.voice-start-btn:hover { border-color: #58a6ff; }
.voice-start-btn.active {
  background: rgba(248, 81, 73, 0.16);
  border-color: rgba(248, 81, 73, 0.6);
  color: #ff8f86;
}

.voice-bar-content.collapsed {
  display: none;
}

.voice-bar-title {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--muted);
}

.voice-bar-btns {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
}

/* The voice bar's own button class. Deliberately NOT `.voice-btn`, which the
   Voice Dictation card already uses: two different controls must not share one
   class, or a change to the call bar silently restyles dictation too. */
.voice-bar-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 10px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  background: var(--panel2);
  border: 1px solid var(--border);
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.voice-bar-btn:hover {
  border-color: var(--accent);
}

.voice-bar-btn.muted {
  color: var(--danger);
  border-color: var(--danger);
  background: rgba(229, 72, 77, 0.16);
}

/* The browser never gave us a microphone: the call is up but the operator's
   voice is not going out, so the control says so instead of reading "On". */
.voice-bar-btn.unavailable {
  color: var(--danger);
  border-color: var(--danger);
  border-style: dashed;
  background: rgba(229, 72, 77, 0.10);
}

.voice-bar-vol {
  display: flex;
  align-items: center;
  gap: 8px;
}

.voice-vol-icon {
  font-size: 12px;
  line-height: 1;
}

.voice-vol-label {
  min-width: 34px;
  text-align: right;
  font-size: 11px;
  color: var(--muted);
}

.audio-badge {
  font-size: 11px;
  padding: 2px 8px;
  border-radius: 999px;
  font-weight: 700;
  text-transform: uppercase;
}

.audio-badge.off {
  background: rgba(139, 150, 171, 0.2);
  color: var(--muted);
}

.audio-badge.live {
  background: rgba(70, 167, 88, 0.25);
  color: var(--ok);
  animation: pulse-green 1.5s infinite;
}

/* Live call, but the admin's microphone is not transmitting (refused or
   stopped): green would be a lie here. */
.audio-badge.warn {
  background: rgba(229, 72, 77, 0.25);
  color: var(--danger);
}

/* The user device's own audio report: their microphone and the interviewer's
   system audio are two separate captures, so this line tracks the second one. */
.voice-src-row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
}

.src-badge {
  flex: 1 1 auto;
  font-size: 11px;
  font-weight: 600;
  padding: 4px 8px;
  border-radius: 999px;
  background: rgba(139, 150, 171, 0.2);
  color: var(--muted);
}

.src-badge.live { background: rgba(70, 167, 88, 0.22); color: var(--ok); }
.src-badge.missing { background: rgba(229, 72, 77, 0.22); color: var(--danger); }
.src-badge.unknown { background: rgba(139, 150, 171, 0.2); color: var(--muted); }

/* A second, smaller shape of the call bar's own button — still `.voice-bar-btn`,
   never the dictation card's `.voice-btn`. */
.voice-bar-btn.compact {
  flex: 0 0 auto;
  padding: 4px 10px;
  font-size: 11px;
}

.status-indicator {
  font-size: 11px;
  color: var(--muted);
  font-weight: 500;
}

.status-indicator.active {
  color: var(--ok);
  font-weight: 700;
}

.status-indicator.muted-tag {
  color: var(--danger);
  font-weight: 700;
}

.audio-meter-wrap {
  width: 100%;
  height: 8px;
  background: var(--panel2);
  border-radius: 4px;
  overflow: hidden;
  border: 1px solid var(--border);
}

.audio-meter-bar {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, #46a758 60%, #f5a524 85%, #e5484d 100%);
  border-radius: 4px;
  transition: width 0.08s ease-out;
}

.vol-slider {
  width: 100%;
  accent-color: var(--accent);
  cursor: pointer;
}

/* Ghost Prompter Controls in Sidebar */
.hud-toggle-label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 700;
  cursor: pointer;
  background: var(--panel);
  padding: 3px 9px;
  border-radius: 20px;
  border: 1px solid var(--border);
}

.hud-toggle-label input:checked + .toggle-text {
  color: var(--ok);
}

.voice-controls {
  display: flex;
  gap: 8px;
  align-items: center;
}

.voice-btn {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 12px;
  font-size: 12px;
  font-weight: 700;
  background: var(--panel2);
  border: 1px solid var(--border);
  cursor: pointer;
}

.voice-btn.recording {
  background: var(--danger);
  color: #fff;
  border-color: var(--danger);
}

.voice-badge {
  font-size: 10px;
  padding: 2px 6px;
  border-radius: 4px;
  background: rgba(139, 150, 171, 0.2);
  color: var(--muted);
}

.voice-badge.recording {
  background: rgba(229, 72, 77, 0.25);
  color: var(--danger);
  animation: pulse-danger 1.2s infinite;
}

.hud-select {
  font-size: 12px;
  padding: 6px 8px;
  background: var(--panel2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 6px;
}

#hud-text-input {
  width: 100%;
  resize: vertical;
  font-family: inherit;
  font-size: 13px;
  line-height: 1.5;
  padding: 8px 10px;
  background: var(--panel2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 6px;
}

.hud-row {
  display: flex;
  gap: 6px;
  align-items: center;
}
.hud-row select {
  flex: 1;
}

/* Text / background colour controls */
.hud-color-input {
  width: 36px;
  height: 28px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: transparent;
  cursor: pointer;
  flex: 0 0 auto;
}
.hud-hex-label {
  font-size: 11px;
  color: var(--muted);
  min-width: 62px;
  font-variant-numeric: tabular-nums;
}
.hud-field-label {
  font-size: 11px;
  color: var(--muted);
  white-space: nowrap;
}
.hud-value-label {
  font-size: 11px;
  color: var(--muted);
  min-width: 34px;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.hud-slider-row {
  gap: 8px;
}
.hud-slider-row .vol-slider {
  flex: 1;
}

.auto-replace-label {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  cursor: pointer;
  color: var(--accent-hover);
  text-transform: none;
  letter-spacing: normal;
  font-weight: 500;
  user-select: none;
}
.auto-replace-label input {
  accent-color: var(--accent);
  cursor: pointer;
}

.hud-btn-row {
  display: flex;
  gap: 6px;
}
.hud-btn-row button {
  flex: 1;
  padding: 7px 6px;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}

.hud-notice {
  font-size: 11px;
  background: rgba(245, 165, 36, 0.2);
  color: var(--warn);
  padding: 5px 8px;
  border-radius: 4px;
  display: block;
  font-weight: 600;
}

.image-upload-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.image-upload-row button {
  padding: 6px 12px;
  font-size: 12px;
}

.image-preview-container {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 4px;
}

.image-preview-container img {
  max-width: 100%;
  max-height: 140px;
  object-fit: contain;
  border-radius: 6px;
  background: #000;
  border: 1px solid var(--border);
}

.image-preview-actions {
  display: flex;
  gap: 8px;
}
.image-preview-actions button {
  flex: 1;
  padding: 6px 10px;
  font-size: 12px;
}

/* Responsive side-by-side on smaller displays: the canvas keeps 45% of the
   space and the sidebar takes the rest with its own scroll, so nothing is
   pushed off-screen and no double scrollbar appears. */
@media (max-width: 900px) {
  .session-workspace {
    flex-direction: column;
  }
  .canvas-wrap {
    flex: 0 0 45%;
    height: auto;
    min-height: 180px;
  }
  .admin-sidebar {
    width: auto;
    min-width: 0;
    flex: 1 1 auto;
    height: auto;
    max-height: none;
    border-left: none;
    border-top: 1px solid var(--border);
    padding-bottom: 60px;
  }
}

/* Tablets / phones: the devices table gets its own horizontal scroll and the
   dialogs can never be wider than the screen. */
@media (max-width: 720px) {
  main {
    padding: 12px;
    overflow-x: auto;
  }
  #devices-table {
    min-width: 620px;
  }
  .actions-col {
    width: auto;
  }
  dialog {
    min-width: 0;
    width: calc(100vw - 24px);
    max-width: calc(100vw - 24px);
    padding: 18px;
  }
  .pairing-code {
    font-size: clamp(20px, 7vw, 32px);
    letter-spacing: clamp(0.12em, 1.6vw, 0.35em);
  }
}

@media (max-width: 600px) {
  .topbar {
    padding: 8px 10px;
    gap: 8px;
  }
  .session-info {
    gap: 8px;
    font-size: 13px;
  }
  .timer {
    font-size: 13px;
    padding: 2px 6px;
  }
  .topbar-right {
    gap: 6px;
  }
  .topbar-right button {
    padding: 5px 9px;
    font-size: 11px;
  }
  .net-latency {
    font-size: 11px;
    padding: 3px 8px;
  }
}

/* ---------- AI Exam Pills & Module Tabs ---------- */
.ai-exam-pill {
  padding: 5px 12px;
  border-radius: 16px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.15s ease;
}
.ai-exam-pill:hover {
  border-color: var(--accent);
  color: var(--text);
}
.ai-exam-pill.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.ai-module-tab {
  padding: 7px 4px;
  border: none;
  background: var(--panel);
  color: var(--muted);
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.15s ease;
  border-right: 1px solid var(--border);
}
.ai-module-tab:last-child { border-right: none; }
.ai-module-tab:hover {
  background: var(--panel2);
  color: var(--text);
}
.ai-module-tab.active {
  background: var(--accent);
  color: #fff;
}

/* ---- live latency readout (control-channel round trip) ---- */
.net-latency {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 600;
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--border);
  color: var(--muted, #9aa4b2);
  font-variant-numeric: tabular-nums;
}
.net-latency.lat-good { color: #3ddc84; border-color: rgba(61, 220, 132, 0.4); }
.net-latency.lat-ok   { color: #e2b53d; border-color: rgba(226, 181, 61, 0.4); }
.net-latency.lat-bad  { color: #e5484d; border-color: rgba(229, 72, 77, 0.45); }

