/* Klados sim — dendrimer Monte Carlo live monitor — 16:9 no-scroll shell
   Auto-loaded by Dash from monitor/assets/.                           */

:root {
  --bg:       #f0f4fa;
  --card:     #ffffff;
  --panel:    #f5f8fd;     /* left-panel background */
  --input-bg: #ffffff;
  --ink:      #0f172a;
  --muted:    #64748b;
  --line:     #e2e8f0;
  --accent:   #4f46e5;
  --green:    #16a34a;
  --red:      #dc2626;
  --sky:      #0ea5e9;
  --amber:    #d97706;
  --radius:   10px;
  --rsm:      7px;
  --pill:     999px;
  --left-w:   345px;
  --log-h:    112px;
  --tog-h:    28px;
  /* Tell the browser which palette this page is using so it paints native
     form-control chrome (input text/caret, select text, autofill) to match
     -- without this, some browsers keep rendering light-scheme (dark) text
     by default even though --ink/--input-bg say otherwise, which is what
     made dark-mode field/dropdown values unreadable. */
  color-scheme: light;
}

/* Dark theme — set on <html data-theme="dark"> by the nav toggle. Only the
   surface tokens flip; the accent/status/semantic colours are shared. */
html[data-theme="dark"] {
  --bg:       #0b1120;
  --card:     #131a2a;
  --panel:    #0e1626;
  --input-bg: #1a2336;
  --ink:      #e2e8f0;
  --muted:    #94a3b8;
  --line:     #283449;
  color-scheme: dark;
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;
  background: var(--bg);
  color: var(--ink);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  font-size: 13px;
}

/* ── full-viewport shell ──────────────────────────────────────── */
/* .root = persistent top nav + the active page; each page fills the rest. */
.root {
  display: flex; flex-direction: column;
  height: 100vh; overflow: hidden;
}
.page-content { flex: 1; min-height: 0; overflow: hidden; display: flex; }
.app {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  width: 100%;
  overflow: hidden;
}

/* ── persistent top nav (links + theme toggle) ────────────────── */
.topnav {
  display: flex; align-items: center; gap: 16px; flex-shrink: 0;
  background: linear-gradient(135deg, #0b1f3f 0%, #123166 55%, #1d4ed8 100%);
  color: #fff; padding: 7px 18px;
  box-shadow: 0 2px 10px rgba(11,31,63,.45);
}
.topnav .nav-logo {
  height: 26px; width: 26px; border-radius: 50%; object-fit: cover;
  background: #f5f7fb; margin-right: -8px;
}
.topnav .nav-title { font-size: 15px; font-weight: 750; letter-spacing: .1px; }
.topnav .nav-links { display: flex; gap: 6px; }
.topnav a {
  color: #fff; text-decoration: none; font-size: 12px; font-weight: 650;
  padding: 4px 12px; border-radius: var(--pill);
  background: rgba(255,255,255,.10); transition: background .12s;
}
.topnav a:hover { background: rgba(255,255,255,.24); }
.topnav .nav-spacer { flex: 1; }
#theme-toggle {
  background: rgba(255,255,255,.16); color: #fff; height: 26px;
  font-size: 11.5px; font-weight: 650; box-shadow: none;
}
#theme-toggle:hover { background: rgba(255,255,255,.30); filter: none; }

/* ── main: left + right ───────────────────────────────────────── */
.main-layout {
  display: flex;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

/* ── left panel ──────────────────────────────────────────────── */
.left-panel {
  width: var(--left-w);
  min-width: 260px;            /* clamp used by the drag resizer (resizer.js) */
  max-width: 640px;
  flex-shrink: 0;
  overflow-y: scroll;          /* always visible scrollbar, never layout-shift */
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  background: var(--panel);
}

/* ── Run tab: stacked top (parameters) / bottom (console) ────────
   Its form has far more rows than fit comfortably beside anything else
   (target/driver/seed/topology/potential/eff-method/cycles/sampling/...),
   so it gets its own top/bottom layout instead of the shared left/right
   .main-layout the other three pages use. Equal halves, each scrolling
   independently so a tall form or a long console never squeezes the
   other out. */
.run-layout {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  gap: 8px;
}
.run-top-panel {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 6px;
  background: var(--panel);
  padding: 8px;
}
.run-bottom-panel {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  padding: 8px;
}
.run-bottom-panel .card {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}
.run-bottom-panel .run-console-box {
  flex: 1;
  height: auto;   /* override the fixed 420px default -- fill the card instead */
  min-height: 0;
}

/* ── draggable splitter between the parameter panel and the graphs ─ */
.resizer {
  flex: 0 0 6px;
  cursor: col-resize;
  background: var(--line);
  position: relative;
  transition: background .12s;
}
.resizer:hover, .resizer.dragging { background: var(--accent); }
/* a subtle grip in the middle of the bar */
.resizer::before {
  content: "";
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 2px; height: 26px; border-radius: 2px;
  background: var(--muted); opacity: .55;
}
.resizer:hover::before, .resizer.dragging::before { background: #fff; opacity: .9; }

/* ── right panel ──────────────────────────────────────────────── */
.right-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
  padding: 8px 8px 0 8px;
  gap: 7px;
}

/* toolbar to pick which graph panels are shown (dynamic) */
.graphs-toolbar {
  display: flex; align-items: center; gap: 12px;
  flex-shrink: 0;
  padding: 2px 4px;
}
.graphs-toolbar-label {
  font-size: 9.5px; text-transform: uppercase; letter-spacing: .07em;
  color: var(--muted); font-weight: 750;
}

.graphs-row {
  flex: 1;
  display: flex;
  flex-direction: row;         /* side by side; never stacks */
  min-height: 0;
  gap: 8px;
}

/* prevent any card from going so narrow the graph disappears */
.obs-card      { min-width: 280px; }
.acf-card      { min-width: 220px; }
.effpot-card   { min-width: 280px; }
.topology-card { min-width: 280px; }

/* ── cards ────────────────────────────────────────────────────── */
.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 10px 12px;
  box-shadow: 0 1px 4px rgba(15,23,42,.06);
}
.card h3 {
  margin: 0 0 9px; font-size: 9.5px; text-transform: uppercase;
  letter-spacing: .08em; color: var(--muted); font-weight: 750;
}

/* graph cards fill the flex row */
.obs-card, .acf-card, .effpot-card, .topology-card {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
  min-width: 0;
}

.card-header-row {
  display: flex; align-items: center; flex-shrink: 0;
  gap: 10px; margin-bottom: 6px;
}
.card-header-row h3 { margin: 0; flex-shrink: 0; }

/* graph container stretches to remaining height */
.graph-wrap {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  position: relative;
}
/* force every Plotly div inside to fill the wrapper */
.graph-wrap > div,
.graph-wrap .js-plotly-plot,
.graph-wrap .plot-container,
.graph-wrap .plotly {
  height: 100% !important;
}

/* ── stat strip (mean / variance under multigraph) ────────────── */
.stat-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  padding: 5px 0 2px;
  flex-shrink: 0;
  border-top: 1px solid var(--line);
  min-height: 30px;
}
.stat-chip {
  display: flex; align-items: center; gap: 7px;
  background: var(--bg); border: 1px solid var(--line);
  border-radius: var(--rsm); padding: 3px 9px; font-size: 11.5px;
}
.stat-chip-name { font-weight: 750; color: var(--accent); min-width: 34px; }
.stat-chip-val  { color: var(--ink); }
.stat-chip-n    { color: var(--muted); font-size: 10.5px; }

/* ── ACF info strip ───────────────────────────────────────────── */
.acf-info {
  font-size: 11.5px; line-height: 1.5; flex-shrink: 0;
  border-top: 1px solid var(--line);
  padding-top: 5px; margin-top: 2px;
  max-height: 82px; overflow-y: auto;
}
.acf-info p  { margin: 0; }
.acf-info ul { margin: 2px 0 0 14px; padding: 0; }
.acf-info li { margin: 0; }

/* ── field rows ──────────────────────────────────────────────── */
.row { display: flex; flex-wrap: wrap; gap: 7px; align-items: flex-end; }
.row + .row { margin-top: 7px; }
.field { display: flex; flex-direction: column; gap: 3px; }

/* Trajectory force-width sliders: rc-slider marks + tooltip are positioned
   below the 14px track and overflow their auto-height .field, colliding with
   the viewer below. Reserve enough vertical room so the box fully contains the
   slider (track + marks + bottom tooltip). */
.an-traj-slider-row { align-items: flex-start; margin-bottom: 10px; }
.an-traj-slider-row .field { min-height: 62px; }
.an-traj-slider-row .rc-slider { margin: 6px 6px 0; }
.field > label {
  font-size: 9.5px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted); font-weight: 750;
}
.btn-row { display: flex; gap: 8px; align-items: center; }
/* Let a button's own label wrap onto a second line instead of forcing the
   button (and its card) wider or overflowing -- long labels like "＋ Add
   to queue" otherwise fight the shared `button { white-space: nowrap }`
   rule. Scoped to .btn-row (grouped action buttons like Run tab's Launch
   box) rather than every button, so unrelated single-button spots keep
   the default no-wrap sizing. */
.btn-row button {
  white-space: normal;
  text-align: center;
  flex: 1 1 0;
  min-width: 0;
}

/* ── titled sub-panel ("box") that groups related controls ─────── */
.field-group {
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 9px 11px 11px;
  background: var(--panel);
  display: flex;
  flex-direction: column;
  gap: 7px;
  box-shadow: inset 0 1px 2px rgba(15,23,42,.03);
}
.field-group + .field-group { margin-top: 8px; }

/* Run tab: the boxes (Target — with the Cloud-server fields folded in,
   Physical parameters, Driver & run, Equilibration/dense/production,
   Launch, Batch queue) flow next to each other and wrap based on window
   width, the same "let it flow, don't force one per line" idea already
   used for the fields inside each box's own .row. The parent's flex gap
   replaces .field-group's own stacked margin-top (would double up with
   the gap and misalign wrapped rows). Each box shares a common
   flex-basis and grows/shrinks from there (rather than sizing purely to
   its own content) so a row of boxes fills evenly instead of packing
   raggedly with an odd gap at the end; min/max-width keep a tiny box
   (Target) from going unreadably narrow or a wide one (Batch queue) from
   stretching arbitrarily far on a huge monitor. align-items: stretch
   makes every box on the SAME wrapped line match that line's tallest
   box's height -- Target and Physical parameters are listed first so
   they land on one line together on a typical window width and come out
   the same height, and every other line of boxes gets the same even
   treatment rather than sitting at ragged, ad-hoc heights. */
#run-params-view {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 10px;
}
#run-params-view > .field-group,
#run-params-view > .field-group + .field-group {
  margin-top: 0;
  flex: 1 1 260px;
  min-width: 220px;
  max-width: 640px;
}
.field-group-title {
  display: flex; align-items: center; gap: 7px;
  font-size: 9px; text-transform: uppercase; letter-spacing: .09em;
  color: var(--muted); font-weight: 800;
  margin-bottom: 1px;
}
/* small accent tick before the caption */
.field-group-title::before {
  content: ""; width: 13px; height: 2.5px; border-radius: 2px;
  background: linear-gradient(90deg, var(--accent), #7c3aed);
  flex-shrink: 0;
}

/* ── inputs ──────────────────────────────────────────────────── */
input {
  height: 30px; padding: 4px 8px; border: 1px solid var(--line);
  border-radius: var(--rsm); font-size: 13px; color: var(--ink);
  background: var(--input-bg); outline: none;
  transition: border-color .15s, box-shadow .15s;
  width: 100%;
}
input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px rgba(79,70,229,.14);
}
/* Dash wraps every dcc.Input's native <input> in its own
   `.dash-input-element` class, which sets `background: inherit` — a class
   selector, so it out-specifies the plain `input` rule above and silently
   falls back to whatever's behind it (effectively white), leaving text
   unreadable in dark mode. Pin it back to the theme explicitly. */
input.dash-input-element {
  background: var(--input-bg) !important;
  color: var(--ink) !important;
}

/* Hide the native number-input spinner (+/- steppers) on all number fields. */
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
  -webkit-appearance: none; margin: 0;
}
input[type="number"] { -moz-appearance: textfield; appearance: textfield; }

/* dcc.Dropdown (Dash 4's Radix-based rewrite -- NOT react-select; class
   names below are what the component actually renders, verified against
   the live DOM). The closed trigger is a <button class="dash-dropdown">;
   the open popup ("dash-dropdown-content") renders through a portal, so
   these rules target it by class, not DOM position. */
.dash-dropdown {
  border-radius: var(--rsm) !important;
  border: 1px solid var(--line) !important;
  min-height: 30px !important;
  font-size: 13px !important;
  background: var(--input-bg) !important;
  color: var(--ink) !important;
}
.dash-dropdown[data-state="open"],
.dash-dropdown:focus-visible {
  border-color: var(--accent) !important;
  box-shadow: 0 0 0 2px rgba(79,70,229,.14) !important;
}
.dash-dropdown-value,
.dash-dropdown-value-item,
.dash-dropdown-trigger-icon {
  color: inherit;
}
.dash-dropdown-content {
  background: var(--input-bg) !important;
  color: var(--ink) !important;
  border: 1px solid var(--line) !important;
  border-radius: var(--rsm) !important;
  box-shadow: 0 8px 24px rgba(15,23,42,.25) !important;
}
.dash-dropdown-search {
  background: var(--input-bg) !important;
  color: var(--ink) !important;
}
.dash-dropdown-search-icon { color: var(--muted) !important; }
.dash-dropdown-option {
  color: var(--ink) !important;
  background: transparent !important;
}
.dash-dropdown-option:hover,
.dash-dropdown-option[aria-selected="true"] {
  background: var(--line) !important;
}

/* ── buttons (pill) ──────────────────────────────────────────── */
button {
  height: 30px; padding: 0 13px; border: none; border-radius: var(--pill);
  font-size: 13px; font-weight: 650; cursor: pointer; color: #fff;
  background: var(--accent); box-shadow: 0 1px 3px rgba(15,23,42,.12);
  transition: filter .12s ease, box-shadow .12s ease, transform .05s ease;
  white-space: nowrap; flex-shrink: 0;
}
button:hover  { filter: brightness(1.07); box-shadow: 0 3px 10px rgba(15,23,42,.18); }
button:active { transform: translateY(1px); }

#start-btn {
  background: var(--green); height: 34px; font-size: 14px; padding: 0 22px;
}
#stop-btn { background: var(--red); }
#attach-btn, #attach-remote-btn { background: var(--accent); }

#delete-btn {
  background: var(--card); color: var(--red);
  border: 1.5px solid var(--red); box-shadow: none;
}
#delete-btn:hover { background: var(--red); color: #fff; filter: none; }

/* log toggle — subtler, lives on a dark bar */
#log-toggle-btn {
  height: 22px; padding: 0 10px; font-size: 11px;
  background: transparent; color: #8faabf;
  border: 1px solid #2a3a4e; border-radius: var(--rsm);
  font-weight: 650; box-shadow: none; filter: none;
}
#log-toggle-btn:hover {
  background: #1e2d3e; color: #c8def0; box-shadow: none; filter: none;
}

/* ── checklist ───────────────────────────────────────────────── */
/* Match .field > label's caption color -- the checklist's own <label>
   (wrapping "controllable" / "dense calibration") isn't a direct child of
   .field so it doesn't inherit that rule, and was falling through to a
   default (accent-colored) look inconsistent with every other field caption. */
.dash-checklist label { margin-right: 10px; font-size: 13px; color: var(--muted); white-space: normal; }
input[type="checkbox"] { margin-right: 5px; width: 13px; height: 13px; }

/* ── status badge ────────────────────────────────────────────── */
.status {
  background: #0f172a; color: #e2e8f0; border-radius: var(--rsm);
  padding: 6px 12px; font-size: 11px; flex-shrink: 0; line-height: 1.5;
}
.status p { margin: 0; }

/* ── action status ───────────────────────────────────────────── */
.action-status { color: var(--muted); font-size: 11.5px; min-height: 14px; margin-top: 6px; }
.action-status p { margin: 0; }

/* ── cloud-attach spinner ────────────────────────────────────── */
/* Shown next to "Attach cloud" from n_clicks until the first row of
   remote data arrives (or the connection fails); driven by the tick
   interval, since the actual SSH connect happens on the background
   poller thread, not inside the button's own callback. */
.attach-spinner {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11.5px; color: var(--muted);
}
.attach-spinner .spinner-dot {
  width: 11px; height: 11px; border-radius: 50%;
  border: 2px solid rgba(148, 163, 184, 0.35);
  border-top-color: var(--accent, #2a9d8f);
  animation: attach-spin 0.7s linear infinite;
}
.attach-spinner.attach-error { color: #ec835a; }
.attach-spinner.attach-error .spinner-dot {
  animation: none; border: none; border-radius: 0;
  width: auto; height: auto;
}
@keyframes attach-spin {
  to { transform: rotate(360deg); }
}

/* ── log footer ──────────────────────────────────────────────── */
.log-footer {
  flex-shrink: 0;
  background: #0b1020;
  border-top: 1px solid #182230;
}
.log-toggle-bar {
  display: flex; align-items: center; gap: 10px;
  height: var(--tog-h);
  padding: 0 10px;
  background: #101d2e;
  border-bottom: 1px solid #182230;
}

.log {
  height: var(--log-h); overflow-y: auto;
  background: #0b1020; color: #9fe7c5;
  padding: 7px 12px; font-size: 11px; line-height: 1.5; margin: 0;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  transition: height .18s ease, padding .18s ease;
}
.log.collapsed {
  height: 0; overflow: hidden; padding-top: 0; padding-bottom: 0;
}

/* ── equilibration badges ────────────────────────────────────── */
.equil-badge {
  font-size: 10px; font-weight: 750; padding: 1px 7px;
  border-radius: var(--pill); flex-shrink: 0;
}
.equil-ok      { background: #dcfce7; color: #166534; border: 1px solid #86efac; }
.equil-warn    { background: #fef3c7; color: #92400e; border: 1px solid #fcd34d; }
.equil-pending { background: #f1f5f9; color: #64748b; border: 1px solid #cbd5e1; }

/* ── cloud attach (collapsible details) ───────────────────────── */
details {
  border: 1px solid var(--line);
  border-radius: var(--rsm);
  padding: 5px 9px;
  margin-top: 7px;
}
details[open] { padding-bottom: 9px; }
summary {
  font-size: 9.5px; font-weight: 750; color: var(--muted);
  text-transform: uppercase; letter-spacing: .07em;
  cursor: pointer; user-select: none; list-style: none; padding: 2px 0;
}
summary::-webkit-details-marker { display: none; }
summary::before { content: "▶  "; font-size: 8px; }
details[open] summary::before { content: "▼  "; }
details .row { margin-top: 7px; }

/* ── read-only auto-config display (replaces the Config dropdown) ─ */
.config-display {
  height: 30px; display: flex; align-items: center;
  padding: 4px 9px; border: 1px dashed var(--line);
  border-radius: var(--rsm); font-size: 12px; color: var(--muted);
  background: var(--panel);
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ── running output-folder name (Run Control header) ──────────── */
.run-folder {
  font-size: 11px; font-weight: 650; color: var(--accent);
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  margin-left: auto; max-width: 180px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ── Sokal recommendation badge + follow-toggle (sampling row) ─── */
.sokal-badge {
  display: flex; align-items: center; gap: 8px;
  font-size: 11px; color: var(--muted); margin-top: 7px;
}
.sokal-badge b { color: var(--accent); }
.sokal-badge .samp-mode-tag {
  font-size: 9.5px; font-weight: 750; text-transform: uppercase;
  letter-spacing: .05em; padding: 1px 7px; border-radius: var(--pill);
}
.samp-auto        { background: #dcfce7; color: #166534; border: 1px solid #86efac; }
.samp-manual      { background: #fef3c7; color: #92400e; border: 1px solid #fcd34d; }
.samp-fixed       { background: #e2e8f0; color: #334155; border: 1px solid #cbd5e1; }
.samp-calculating { background: #dbeafe; color: #1e40af; border: 1px solid #93c5fd; }

/* ── analysis page ────────────────────────────────────────────── */
.analysis-results {
  flex: 1; display: flex; flex-direction: row; min-height: 0; gap: 8px;
}
.analysis-table-card { width: 360px; flex-shrink: 0;
  display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
.analysis-table-card h3 { flex-shrink: 0; }
.analysis-graph-card { flex: 1; display: flex; flex-direction: column;
  min-height: 0; overflow: hidden; min-width: 0; }
.analysis-hint { color: var(--muted); font-size: 11.5px; margin-top: 6px; }

/* The table scrolls INSIDE its card (sticky header), never the page — the
   cells themselves ellipsize (fixed-layout table), so neither axis of the
   card can ever be blown open by long content. */
.obs-table { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; }
.obs-table .dash-table-container,
.obs-table .dash-spreadsheet-container,
.obs-table .dash-spreadsheet-inner { max-width: 100%; }
.obs-table table { width: 100%; table-layout: fixed; }

/* DataTable themed through tokens so it follows light/dark. */
.obs-table .dash-spreadsheet-inner th {
  background: var(--panel) !important; color: var(--ink) !important;
  border-color: var(--line) !important; font-weight: 700;
  position: sticky; top: 0; z-index: 2;
  font-size: 10px; text-transform: uppercase; letter-spacing: .05em;
}
.obs-table .dash-spreadsheet-inner td {
  background: var(--card) !important; color: var(--ink) !important;
  border-color: var(--line) !important;
}
/* zebra rows — quiet contrast so long tables stay scannable */
.obs-table .dash-spreadsheet-inner tr:nth-child(even) td {
  background: var(--panel) !important;
}

/* ── cloud page ───────────────────────────────────────────────── */
.cloud-console-card {
  flex: 1; display: flex; flex-direction: column;
  min-height: 0; overflow: hidden;
}
.cloud-console {
  flex: 1; min-height: 0; overflow-y: auto; margin: 0;
  background: #0b1020; color: #9fe7c5;
  border: 1px solid #182230; border-radius: var(--rsm);
  padding: 9px 12px; font-size: 11.5px; line-height: 1.55;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  white-space: pre-wrap; word-break: break-word;
}
.cloud-cmd-row {
  flex-shrink: 0; margin-top: 7px; align-items: center;
  flex-wrap: nowrap;
}
.cloud-cmd-row input { flex: 1; font-family: ui-monospace, "SF Mono", Menlo, monospace; }
.cloud-prompt {
  color: var(--accent); font-weight: 750;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
}
.cloud-quick {
  height: 22px; padding: 0 10px; font-size: 10.5px;
  background: var(--card); color: var(--accent);
  border: 1px solid var(--accent); box-shadow: none;
}
.cloud-quick:hover { background: var(--accent); color: #fff; filter: none; }
.cloud-quick-danger { color: var(--red); border-color: var(--red); }
.cloud-quick-danger:hover { background: var(--red); color: #fff; }
.cloud-note { font-size: 10.5px; color: var(--muted); line-height: 1.45; }

.cloud-queue {
  display: flex; flex-direction: column; gap: 3px;
  font-size: 11px; color: var(--muted);
  max-height: 130px; overflow-y: auto;
}
.cloud-queue-item {
  padding: 2px 8px; border-radius: var(--rsm);
  border: 1px dashed var(--line); background: var(--card);
  color: var(--ink); font-family: ui-monospace, "SF Mono", Menlo, monospace;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.cloud-jobs { display: flex; flex-direction: column; gap: 4px;
  font-size: 11.5px; color: var(--muted); }
.cloud-job {
  padding: 3px 9px; border-radius: var(--rsm); border: 1px solid var(--line);
  background: var(--panel); color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cloud-job-running { border-color: var(--sky);   color: var(--sky); }
.cloud-job-done    { border-color: var(--green); color: var(--green); }
.cloud-job-error   { border-color: var(--red);   color: var(--red); }
/* "no evidence left" (classify_runs), not an error -- stays neutral. */
.cloud-job-muted   { border-color: var(--line);  color: var(--muted); }

/* Clear-by-state menu: the state dropdown sits on the button's baseline
   (.field stacks a label above it, so align to the bottom, not the middle). */
.cloud-clear-row { display: flex; gap: 8px; align-items: flex-end; margin-top: 8px; }
.cloud-clear-del { font-size: 10.5px; color: var(--muted); margin-top: 6px; }
.cloud-clear-del label { display: inline-flex; align-items: center; gap: 2px; }

/* ── generic sub-tab strip (Run: Parameters/Console; Help: Usage/Methods) ─ */
.subtabs {
  display: flex; gap: 4px; margin-bottom: 9px;
  border-bottom: 1px solid var(--line);
}
.subtab-btn {
  background: transparent; color: var(--muted);
  border: 1px solid transparent; border-bottom: none; box-shadow: none;
  font-size: 11.5px; font-weight: 650; height: 27px; padding: 0 12px;
  border-radius: var(--rsm) var(--rsm) 0 0; margin-bottom: -1px;
}
.subtab-btn:hover { background: var(--panel); filter: none; }
.subtab-btn.active {
  background: var(--card); color: var(--accent);
  border-color: var(--line); border-bottom: 1px solid var(--card);
}
.run-console-box {
  height: 420px; overflow-y: auto; margin: 0;
  background: #0b1020; color: #9fe7c5;
  border: 1px solid #182230; border-radius: var(--rsm);
  padding: 9px 12px; font-size: 11.5px; line-height: 1.55;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  white-space: pre-wrap; word-break: break-word;
}

/* ── Help page: centered reading column ──────────────────────────── */
.help-main { justify-content: center; overflow-y: auto; padding: 18px 12px; }
.help-page {
  width: 100%; max-width: 860px;
  display: flex; flex-direction: column; gap: 4px;
}
.help-page h2 { margin: 0 0 4px; font-size: 18px; }
.help-method-select { max-width: 360px; margin-bottom: 10px; }
.help-markdown {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 18px 26px;
  line-height: 1.6; font-size: 13.5px; color: var(--ink);
  overflow-wrap: break-word;
}
.help-markdown h1, .help-markdown h2, .help-markdown h3 {
  color: var(--ink); margin-top: 1.3em;
}
.help-markdown h1:first-child, .help-markdown h2:first-child { margin-top: 0; }
.help-markdown code {
  background: var(--panel); border-radius: 4px; padding: 1px 5px;
  font-size: 12px;
}
.help-markdown pre {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--rsm); padding: 10px 12px; overflow-x: auto;
}
.help-markdown pre code { background: none; padding: 0; }
.help-markdown blockquote {
  border-left: 3px solid var(--accent); margin: 0; padding: 2px 14px;
  color: var(--muted);
}
.help-markdown table { border-collapse: collapse; width: 100%; }
.help-markdown th, .help-markdown td {
  border: 1px solid var(--line); padding: 5px 9px; text-align: left;
}

/* equilibration badges: darker pastels in dark mode for contrast */
html[data-theme="dark"] .equil-ok      { background: #14331f; color: #86efac; border-color: #1f5132; }
html[data-theme="dark"] .equil-warn    { background: #3a2a0c; color: #fcd34d; border-color: #6b4f12; }
html[data-theme="dark"] .equil-pending { background: #1a2336; color: #94a3b8; border-color: #283449; }
html[data-theme="dark"] .samp-auto        { background: #14331f; color: #86efac; border-color: #1f5132; }
html[data-theme="dark"] .samp-manual      { background: #3a2a0c; color: #fcd34d; border-color: #6b4f12; }
html[data-theme="dark"] .samp-fixed       { background: #1e293b; color: #cbd5e1; border-color: #334455; }
html[data-theme="dark"] .samp-calculating { background: #12264d; color: #93c5fd; border-color: #1e3a6e; }

/* ── keyboard focus: a clear, consistent ring on interactive elements so
   keyboard users can always see where they are. :focus-visible means it
   shows on keyboard/programmatic focus, never on a plain mouse click.
   (Text inputs and dropdowns already draw their own accent ring on
   :focus, so they're deliberately left out here to avoid a double ring.) */
a:focus-visible,
summary:focus-visible,
.subtab-btn:focus-visible,
input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}
button:focus-visible {           /* solid-fill buttons: white ring + accent glow reads on any colour */
  outline: 2px solid #fff;
  outline-offset: -1px;
  box-shadow: 0 0 0 3px rgba(79, 70, 229, .55);
}
.topnav a:focus-visible { outline-color: #fff; }

/* ── slim, themed scrollbars (quieter than the default heavy chrome) ── */
* { scrollbar-width: thin; scrollbar-color: var(--line) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--line); border-radius: 6px;
  border: 2px solid transparent; background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--muted); background-clip: padding-box; }

/* ═══════════════════════════════════════════════════════════════════════
   RESPONSIVE — below desktop width the fixed 16:9 "no-scroll" shell turns
   into a normal single-column, scrollable page, so laptops, tablets and
   small/short windows aren't clipped or squeezed. Wide screens keep the
   original viewport-fill layout untouched (these rules simply don't apply).
   ═══════════════════════════════════════════════════════════════════════ */
@media (max-width: 1024px) {
  html, body { overflow-x: hidden; overflow-y: auto; height: auto; }
  .root { height: auto; min-height: 100vh; overflow: visible; }
  .page-content, .app, .run-layout, .help-main { overflow: visible; min-height: 0; }

  /* Side-by-side panels stack; the page scrolls instead of every panel
     fighting for a slice of one locked viewport height. */
  .main-layout, .analysis-results, .graphs-row {
    flex-direction: column; overflow: visible;
  }
  .left-panel {
    /* !important so a width the user dragged on desktop (resizer.js writes an
       inline width) can't keep the panel pinned narrow once it stacks. */
    width: auto !important; max-width: none !important; min-width: 0;
    flex-shrink: 1; overflow: visible;
  }
  .right-panel { overflow: visible; padding: 8px; }
  .resizer { display: none; }                 /* nothing to drag when stacked */

  /* Graphs need a definite height once the page (not the viewport) drives
     layout — a flex:1 child of an auto-height parent would collapse to 0. */
  .obs-card, .acf-card, .effpot-card, .topology-card,
  .analysis-graph-card { min-height: 400px; }
  .graph-wrap { min-height: 340px; }

  .analysis-table-card { width: auto; max-height: 460px; }

  /* Run tab: both halves size to content; the page scrolls. */
  .run-top-panel, .run-bottom-panel { flex: none; overflow: visible; }
  .run-console-box { height: 340px; }
}

/* Phones / very small windows: tighten chrome, one form-box and one graph
   per line. */
@media (max-width: 560px) {
  .topnav { gap: 10px; padding: 7px 12px; flex-wrap: wrap; }
  #run-params-view > .field-group,
  #run-params-view > .field-group + .field-group { flex-basis: 100%; max-width: none; }
  .obs-card, .acf-card, .effpot-card, .topology-card,
  .analysis-graph-card { min-height: 340px; }
}

/* ── Analysis "Mode": a RadioItems rendered as a segmented tab bar ─────── */
.mode-tabs {
  display: inline-flex; border: 1px solid var(--line);
  border-radius: var(--rsm); overflow: hidden;
}
.mode-tabs label {
  display: inline-flex; align-items: center; margin: 0; padding: 5px 14px;
  font-size: 11.5px; font-weight: 650; color: var(--muted); cursor: pointer;
  border-right: 1px solid var(--line); user-select: none;
}
.mode-tabs label:last-child { border-right: none; }
.mode-tabs input[type="radio"] { display: none; }
.mode-tabs label:has(input:checked) { background: var(--accent); color: #fff; }
.mode-tabs label:hover:not(:has(input:checked)) { background: var(--panel); }

/* ── Overview / home page ─────────────────────────────────────────────── */
.overview-page { max-width: 760px; margin: 0 auto; padding: 22px 16px;
  overflow-y: auto; }
.overview-status { color: var(--muted); font-size: 13px; margin: 4px 0 18px; }
.overview-links { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 22px; }
.overview-link {
  padding: 8px 16px; border: 1px solid var(--line); border-radius: var(--rsm);
  background: var(--card); color: var(--accent); font-weight: 650;
  text-decoration: none;
}
.overview-link:hover { background: var(--panel); }
.overview-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.overview-table th, .overview-table td {
  text-align: left; padding: 6px 10px; border-bottom: 1px solid var(--line);
}
.overview-table th { color: var(--muted); font-weight: 650; }
.overview-empty { color: var(--muted); font-style: italic; }

/* ── Top-nav active tab (set by a clientside callback on pathname) ─────── */
.topnav .nav-links a.active { color: var(--accent); font-weight: 750; }

/* ── Accounts (Admin tab) and the sign-in link in the nav ─────────────── */
.admin-table { border-collapse: collapse; font-size: 13px; }
.admin-table th, .admin-table td {
  text-align: left; padding: 7px 10px; border-bottom: 1px solid var(--line);
}
.admin-table th { color: var(--muted); font-weight: 650; }
.admin-table button { font-size: 12px; height: 26px; padding: 0 11px; }
/* Delete is the one irreversible action here, so it is outlined rather than
   filled — it should not read as the obvious thing to click. */
.admin-table button.danger {
  background: transparent; color: var(--red);
  border: 1px solid var(--red); box-shadow: none;
}
.admin-table button.danger:hover { background: var(--red); color: #fff; }
.topnav .nav-account a { padding: 2px 6px; }
