/* MPACT Web -- theme.
   Palette taken from the desktop app's Qt stylesheets (ui_main.py): a dark
   shell at rgb(35,35,35), panels at rgb(40,40,40), controls at rgb(75,75,75),
   text at rgb(212,212,212) and muted labels at rgb(150,150,150), with the
   teal accent from the MPACT documentation theme. Keeping these exact values
   is why the web app reads as the same application rather than a lookalike. */

:root {
  --bg: #232323;
  --panel: #282828;
  --panel-2: #2f2f2f;
  --control: #4b4b4b;
  --control-hover: #5a5a5a;
  --border: #3a3a3a;
  --text: #d4d4d4;
  --muted: #969696;
  --accent: #26a69a;
  --accent-dim: #1d7d74;
  --danger: #e05252;
  --warn: #d8a13a;
  --ok: #4caf80;
  --plot-bg: #e1e1e1;
  --radius: 3px;
  --sidebar-width: 208px;
  --font: "Segoe UI", system-ui, -apple-system, sans-serif;
  /* The desktop sets Bahnschrift SemiBold on its headings, tab buttons and
     labels (ui_main.py) and Bahnschrift on its plot titles, with Segoe UI for
     body text. Same split here: this is the chrome face, --font is the
     reading face. */
  --font-display: "Bahnschrift SemiBold", "Bahnschrift", "Segoe UI Semibold",
                  "Segoe UI", system-ui, sans-serif;
  --mono: "Cascadia Mono", "Consolas", ui-monospace, monospace;
}

* { box-sizing: border-box; }

/* Tell the browser this is a dark UI so form controls and (in Firefox)
   scrollbars follow, then style the WebKit/Blink scrollbars explicitly --
   without this they render as light-mode bars on every dark panel. */
:root { color-scheme: dark; }
* { scrollbar-color: #4b4b4b #1c1c1c; scrollbar-width: thin; }
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: #1c1c1c; }
::-webkit-scrollbar-corner { background: #1c1c1c; }
::-webkit-scrollbar-thumb {
  background: #4b4b4b; border-radius: 6px; border: 2px solid #1c1c1c;
}
::-webkit-scrollbar-thumb:hover { background: #5f5f5f; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 13px;
  overflow: hidden;
}

button, input, select, textarea { font-family: inherit; font-size: inherit; color: inherit; }

/* Base look for text-like controls, so one outside a .field wrapper (the
   feature-set name box, a plot toolbar's threshold box) doesn't fall back to
   the browser default and read as disabled on a dark ground. */
input[type="text"], input[type="number"], input[type="search"], select, textarea {
  background: #1c1c1c; color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius); padding: 5px 7px;
}
input[type="text"]:focus, input[type="number"]:focus, select:focus, textarea:focus {
  outline: 1px solid var(--accent); border-color: var(--accent);
}
input:disabled, select:disabled { opacity: .5; }
input[type="color"] {
  width: 34px; height: 24px; padding: 1px; background: #1c1c1c;
  border: 1px solid var(--border); border-radius: var(--radius); cursor: pointer;
}

/* --- app shell ---------------------------------------------------------- */

#app { display: flex; flex-direction: column; height: 100vh; }

.titlebar {
  display: flex; align-items: center; gap: 12px;
  height: 38px; padding: 0 14px;
  background: #1b1b1b;
  border-bottom: 1px solid var(--border);
  flex: 0 0 auto;
}
/* The desktop application's icon, so the browser tab and the window header
   carry the same mark as the installed program. */
.titlebar .app-icon { width: 20px; height: 20px; display: block; }
.titlebar .brand { font-family: var(--font-display); font-weight: 700; letter-spacing: 1px; }
.titlebar .brand span { color: var(--accent); }
.titlebar .spacer { flex: 1; }
.titlebar .run-chip {
  display: flex; align-items: center; gap: 8px;
  padding: 3px 10px; border-radius: 12px;
  background: var(--panel-2); border: 1px solid var(--border);
  color: var(--muted); font-size: 12px;
}
.titlebar .run-chip.is-running { color: var(--warn); border-color: var(--warn); }
.titlebar .run-chip.is-complete { color: var(--ok); border-color: var(--accent-dim); }
.titlebar .run-chip.is-failed { color: var(--danger); border-color: var(--danger); }

.body { display: flex; flex: 1; min-height: 0; }

/* Persistent selection readout, the web form of the desktop's
   lbl_featurename / lbl_featuremz / lbl_featurert / lbl_injname labels: what
   is selected has to stay on screen, not flash past in a toast. */
.statusbar {
  display: flex; align-items: center; gap: 18px;
  flex: 0 0 auto; height: 26px; padding: 0 14px;
  background: #1b1b1b; border-top: 1px solid var(--border);
  font-size: 12px; color: var(--muted); overflow: hidden; white-space: nowrap;
}
.statusbar .slot-label { font-family: var(--font-display); color: #6f6f6f; }
.statusbar .value { color: var(--text); font-variant-numeric: tabular-nums; }
.statusbar .value.none { color: #6f6f6f; font-style: italic; }
.statusbar .feature { color: var(--accent); font-weight: 600; }
.statusbar .spacer { flex: 1; }
.statusbar button {
  background: none; border: none; color: var(--muted); cursor: pointer;
  padding: 0 4px; font-size: 12px;
}
.statusbar button:hover { color: var(--text); }

/* --- sidebar ------------------------------------------------------------ */

.sidebar {
  width: var(--sidebar-width); flex: 0 0 var(--sidebar-width);
  background: #1e1e1e; border-right: 1px solid var(--border);
  display: flex; flex-direction: column; overflow-y: auto;
}
.sidebar .group-label {
  font-family: var(--font-display);
  padding: 14px 14px 6px; font-size: 11px; letter-spacing: 1.2px;
  text-transform: uppercase; color: var(--muted);
}
.sidebar button {
  display: flex; align-items: center; gap: 8px;
  width: 100%; padding: 8px 14px; text-align: left;
  background: none; border: none; border-left: 3px solid transparent;
  color: var(--text); cursor: pointer;
}
.sidebar button:hover:not(:disabled) { background: var(--panel); }
.sidebar button.active { background: var(--panel-2); border-left-color: var(--accent); }
.sidebar button:disabled { color: #5e5e5e; cursor: not-allowed; }
.sidebar button .badge {
  margin-left: auto; font-size: 10px; color: var(--muted);
  background: var(--panel-2); border-radius: 8px; padding: 1px 6px;
}

/* --- main --------------------------------------------------------------- */

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; overflow: hidden; }
.view { flex: 1; overflow: auto; padding: 14px 20px 18px; display: none; }
.view.active { display: block; }
.view > h2 {
  font-family: var(--font-display);
  margin: 0 0 3px; font-size: 17px; font-weight: 600;
}
.view > .lede { margin: 0 0 12px; color: var(--muted); max-width: 70ch; }

/* A plot view fills the window. The heading and sub-tabs sit on the dark
   chrome; below them the working surface runs edge to edge in the desktop's
   grey, with the details rail docked to its right. No dark gutter around the
   plot: the middle of the window is one continuous region. */
.view.plot-view.active {
  display: flex; flex-direction: column; overflow: hidden; padding: 0;
}
/* No title strip above a plot: the view is named in the navigation bar, and
   the graphing window starts at the top of the region. */
.view.plot-view > .tab-header { flex: 0 0 auto; padding: 10px 18px 8px; margin-bottom: 0 !important; }
.view.plot-view .plot-host { flex: 1; min-height: 0; display: flex; gap: 0; }
.view.plot-view .plot-panel { flex: 1; min-width: 0; display: flex; flex-direction: column; }
/* Panels that are documents rather than charts (the Summary tab) scroll. */
.view.plot-view .plot-panel.scrolls { overflow: auto; }

/* --- panels / forms ----------------------------------------------------- */

.panel {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 11px 13px; margin-bottom: 11px;
}
.panel > h3 {
  font-family: var(--font-display);
  margin: 0 0 9px; font-size: 13px; font-weight: 600;
  color: var(--text); display: flex; align-items: center; gap: 8px;
}
.panel > h3 .hint { font-weight: 400; color: var(--muted); font-size: 12px; }

/* Collapsible panel: a disclosure row that toggles its body. Used for the
   demo dataset block and for each section of the details rail. */
.collapsible > .collapsible-head {
  display: flex; align-items: center; gap: 8px; width: 100%;
  background: none; border: none; color: var(--text);
  padding: 0; cursor: pointer; text-align: left; font-weight: 600; font-size: 13px;
}
.collapsible > .collapsible-head:hover { color: #fff; }
.collapsible > .collapsible-head .twisty {
  display: inline-block; width: 10px; flex: 0 0 10px; color: var(--muted);
  transition: transform .12s ease;
}
.collapsible.open > .collapsible-head .twisty { transform: rotate(90deg); }
.collapsible > .collapsible-head .hint { font-weight: 400; color: var(--muted); font-size: 12px; }
.collapsible > .collapsible-body { display: none; padding-top: 10px; }
.collapsible.open > .collapsible-body { display: block; }

/* In a button row, a disclosure sits inline with the button rather than
   stacking under it. */
.btn-row > .collapsible { flex: 1; min-width: 0; }
.btn-row > .collapsible > .collapsible-head { font-weight: 400; color: var(--muted); }
.btn-row > .collapsible > .collapsible-head:hover { color: var(--text); }

.grid { display: grid; gap: 14px; }
.grid.cols-2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.grid.cols-3 { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }

.field { display: flex; flex-direction: column; gap: 4px; margin-bottom: 10px; }
.field label { color: var(--muted); font-size: 12px; }
.field input[type="text"], .field input[type="number"], .field select, .field textarea {
  background: #1c1c1c; border: 1px solid var(--border);
  border-radius: var(--radius); padding: 6px 8px; width: 100%;
}
.field input:focus, .field select:focus { outline: 1px solid var(--accent); border-color: var(--accent); }
.field.inline { flex-direction: row; align-items: center; gap: 8px; }
.field .suffix { color: var(--muted); font-size: 12px; }

.check { display: flex; align-items: center; gap: 8px; padding: 4px 0; cursor: pointer; }
.check input { accent-color: var(--accent); width: 14px; height: 14px; }
.check.disabled { opacity: .45; cursor: not-allowed; }

.radio-row { display: flex; gap: 16px; padding: 4px 0 8px; }
.radio-row label { display: flex; align-items: center; gap: 6px; cursor: pointer; }
.radio-row input { accent-color: var(--accent); }

button.btn {
  background: var(--control); border: 1px solid #565656; color: var(--text);
  border-radius: var(--radius); padding: 6px 14px; cursor: pointer;
}
button.btn:hover:not(:disabled) { background: var(--control-hover); }
button.btn:disabled { opacity: .5; cursor: not-allowed; }
button.btn.primary { background: var(--accent-dim); border-color: var(--accent); color: #fff; }
button.btn.primary:hover:not(:disabled) { background: var(--accent); }
button.btn.danger:hover:not(:disabled) { background: #6b2c2c; border-color: var(--danger); }
button.btn.small { padding: 3px 9px; font-size: 12px; }
.btn-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* --- file slots --------------------------------------------------------- */

.slot {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 10px; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--panel-2); margin-bottom: 5px;
}
.slot:last-of-type { margin-bottom: 0; }
.slot.dragover { border-color: var(--accent); background: #2b3a38; }
.slot .slot-name {
  width: 148px; flex: 0 0 148px; font-family: var(--font-display); font-weight: 600;
}
.slot .slot-name small { display: block; font-weight: 400; color: var(--muted); }
.slot .slot-value { flex: 1; min-width: 0; }
.slot .slot-value .filename {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.slot .slot-value .empty { color: var(--muted); }
.slot .slot-value .meta { color: var(--muted); font-size: 11px; margin-top: 1px; }
.slot .slot-value .meta .bad { color: var(--danger); }
.slot select {
  max-width: 320px;
  background: #1c1c1c; color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius); padding: 5px 7px;
}
/* Native select option lists are painted by the OS, which on a dark page can
   render dark-on-dark; force both sides explicitly. */
select option { background: #1c1c1c; color: var(--text); }

/* --- groupset (Plot Feature Set) editor --------------------------------- */

.groupsets { display: grid; grid-template-columns: 210px 1fr; gap: 14px; }
.groupset-list { border: 1px solid var(--border); border-radius: var(--radius); background: #1c1c1c; }
.groupset-list ul { list-style: none; margin: 0; padding: 0; max-height: 260px; overflow-y: auto; }
.groupset-list li {
  display: flex; align-items: center; gap: 8px; padding: 6px 10px; cursor: pointer;
  border-bottom: 1px solid #262626;
}
.groupset-list li:hover { background: var(--panel); }
.groupset-list li.active { background: var(--panel-2); }
.groupset-list li .swatch {
  width: 12px; height: 12px; border-radius: 2px; border: 1px solid #666; flex: 0 0 12px;
}
.groupset-list li .name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.groupset-list .list-actions { display: flex; gap: 4px; padding: 6px; border-top: 1px solid var(--border); }

.group-buckets { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.bucket { border: 1px solid var(--border); border-radius: var(--radius); background: #1c1c1c; min-height: 130px; }
.bucket.dragover { border-color: var(--accent); }
.bucket h4 { margin: 0; padding: 6px 10px; font-size: 12px; color: var(--muted); border-bottom: 1px solid var(--border); }
.bucket ul { list-style: none; margin: 0; padding: 4px; min-height: 90px; }
.bucket li {
  padding: 4px 8px; margin-bottom: 3px; background: var(--panel-2);
  border: 1px solid var(--border); border-radius: var(--radius); cursor: grab;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bucket li.selected { border-color: var(--accent); background: #2b3a38; }

/* --- plot surfaces ------------------------------------------------------ */

/* A plot is one object: a light canvas carrying its own bars. What is being
   plotted is chosen on the bar across the top of the graphing window; how you
   move around it and save it lives in the navigation strip underneath, where
   the desktop puts matplotlib's toolbar. Both are light-on-grey like the rest
   of the canvas, not dark strips floating over it. */
.plot-canvas {
  flex: 1; min-height: 0; display: flex; flex-direction: column;
  background: var(--plot-bg); overflow: hidden;
  border-top: 1px solid var(--border);
}
.plot-toolbar {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 7px 10px;
}
.plot-canvas .plot-toolbar {
  background: #d7d7d7; color: #2b2b2b;
  border-bottom: 1px solid #c2c2c2;
}

/* The navigation toolbar: this app's NavigationToolbar2QT. */
.plot-navbar {
  flex: 0 0 auto; display: flex; align-items: center; gap: 10px;
  padding: 3px 8px; background: #d7d7d7; color: #2b2b2b;
  border-top: 1px solid #c2c2c2;
}
.plot-navbar .nav-group { display: flex; align-items: center; gap: 2px; }
.plot-navbar .nav-group + .nav-group {
  margin-left: 4px; padding-left: 10px; border-left: 1px solid #bcbcbc;
}
.plot-navbar .spacer { flex: 1; }
.nav-btn {
  display: flex; align-items: center; justify-content: center;
  width: 27px; height: 24px; padding: 0;
  background: transparent; border: 1px solid transparent; border-radius: var(--radius);
  color: #333; cursor: pointer;
}
.nav-btn svg {
  fill: none; stroke: currentColor; stroke-width: 1.4;
  stroke-linecap: round; stroke-linejoin: round;
}
.nav-btn:hover:not(:disabled) { background: #c9c9c9; border-color: #b0b0b0; }
.nav-btn:disabled { color: #a0a0a0; cursor: default; }
/* A latched tool stays visibly pressed, as matplotlib's pan and zoom do. */
.nav-btn.active {
  background: #bcd8d3; border-color: var(--accent-dim); color: #10403b;
}
.plot-navbar .export-format {
  background: #fff; color: #1e1e1e; border: 1px solid #b4b4b4;
  border-radius: var(--radius); padding: 1px 4px; font-size: 11px;
}
.plot-navbar .export-format option { background: #fff; color: #1e1e1e; }
.plot-canvas .plot-toolbar label { color: #4a4a4a; font-size: 12px; display: flex; align-items: center; gap: 5px; }
.plot-canvas .plot-toolbar select,
.plot-canvas .plot-toolbar input[type="number"],
.plot-canvas .plot-toolbar input[type="text"] {
  background: #ffffff; color: #1e1e1e;
  border: 1px solid #b4b4b4; border-radius: var(--radius); padding: 2px 6px;
}
.plot-canvas .plot-toolbar select option { background: #ffffff; color: #1e1e1e; }
.plot-toolbar input[type="number"] { width: 78px; }
.plot-canvas .plot-toolbar input[type="checkbox"] { accent-color: var(--accent-dim); }
.plot-canvas .plot-toolbar .check,
.plot-canvas .plot-toolbar .check span { color: #2b2b2b; }
.plot-toolbar .spacer { flex: 1; }
.plot-canvas .plot-toolbar .status { color: #5c5c5c; }
.plot-toolbar .status { font-size: 12px; }
.plot-canvas .plot-toolbar .btn {
  background: #e0e0e0; color: #222; border-color: #b4b4b4;
}
.plot-canvas .plot-toolbar .btn:hover:not(:disabled) { background: #d2d2d2; }
.plot-canvas .plot-toolbar .btn.primary { background: var(--accent-dim); color: #fff;
  border-color: var(--accent-dim); }

.plot-surface {
  flex: 1; min-height: 240px; position: relative;
  background: var(--plot-bg);
}
.plot-surface.tall { min-height: 240px; }

/* The caption strip continues the navbar's grey, so the two read as one bar
   under the plot rather than a strip of plot-ground with text on it. */
.plot-footer {
  flex: 0 0 auto; padding: 4px 12px; color: #4a4a4a; font-size: 12px;
  background: #d7d7d7;
}
.plot-footer:empty { display: none; }
.plot-footer p { margin: 0; color: #4a4a4a; }
.plot-footer .muted { color: #5c5c5c; }
.plot-footer .plot-legend .item { color: #4a4a4a; }
.plot-footer .notice { background: #cfcfcf; color: #3a2a2a; }
.plot-surface .placeholder {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  color: #555; text-align: center; padding: 20px;
}
.plot-surface .placeholder.error { color: #8c2f2f; }

.plot-legend { display: flex; flex-wrap: wrap; gap: 12px; padding: 8px 2px 0; }
.plot-legend .item { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); }
.plot-legend .swatch { width: 11px; height: 11px; border-radius: 2px; }

/* --- tables ------------------------------------------------------------- */

table.data { width: 100%; border-collapse: collapse; font-size: 12px; }
table.data th, table.data td {
  text-align: left; padding: 5px 8px; border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
table.data th { color: var(--muted); font-weight: 600; cursor: pointer; user-select: none; position: sticky; top: 0; background: var(--panel); }
table.data th .sort { color: var(--accent); }
table.data tbody tr { cursor: pointer; }
table.data tbody tr:hover { background: var(--panel-2); }
table.data tbody tr.selected { background: #2b3a38; }
table.data td.num { text-align: right; font-variant-numeric: tabular-nums; }
.table-wrap { max-height: 420px; overflow: auto; border: 1px solid var(--border); border-radius: var(--radius); }

.stat-row { display: flex; gap: 24px; flex-wrap: wrap; }
.stat { min-width: 120px; }
.stat .value { font-size: 22px; font-weight: 600; }
.stat .value.accent { color: var(--accent); }
.stat .label { color: var(--muted); font-size: 12px; }

/* --- misc --------------------------------------------------------------- */

.log {
  background: #141414; border: 1px solid var(--border); border-radius: var(--radius);
  font-family: var(--mono); font-size: 11.5px; line-height: 1.45;
  padding: 10px; max-height: 340px; overflow: auto; white-space: pre-wrap;
  color: #b9b9b9;
}

/* The Run page fills the window and gives what is left to the log, which
   scrolls inside itself. The pipeline prints hundreds of lines, and a page
   that grows a scrollbar per line is a page you cannot read the top of. */
.view.run-view.active {
  display: flex; flex-direction: column; overflow: hidden;
}
.view.run-view > * { flex: 0 0 auto; }
.view.run-view > .progress-panel {
  flex: 1 1 auto; min-height: 140px; display: flex; flex-direction: column;
  margin-bottom: 0;
}
.view.run-view > .progress-panel .terminal {
  flex: 1 1 auto; min-height: 90px;
}

/* The log over the dinosaur: the terminal box carries the background, the
   canvas sits in its bottom-right corner, and the text scrolls on top. */
.terminal {
  position: relative; display: flex; flex-direction: column; overflow: hidden;
  background: #141414; border: 1px solid var(--border); border-radius: var(--radius);
}
.terminal > .log {
  position: relative; z-index: 1; flex: 1 1 auto; min-height: 0; max-height: none;
  background: transparent; border: 0; border-radius: 0;
}
.terminal > canvas.dino {
  position: absolute; right: 16px; bottom: 8px; z-index: 0;
  image-rendering: crisp-edges; image-rendering: pixelated; pointer-events: none;
}
.notice {
  padding: 9px 12px; border-radius: var(--radius); margin-bottom: 12px;
  border-left: 3px solid var(--muted); background: var(--panel-2);
}
.notice.error { border-left-color: var(--danger); color: #f0b4b4; }
.notice.warn { border-left-color: var(--warn); color: #e8cf9c; }
.notice.ok { border-left-color: var(--ok); }
.notice.info { border-left-color: var(--accent); }

.progress { height: 4px; background: #1b1b1b; border-radius: 2px; overflow: hidden; }
.progress > div { height: 100%; background: var(--accent); width: 30%; animation: slide 1.4s ease-in-out infinite; }
@keyframes slide { 0% { margin-left: -30%; } 100% { margin-left: 100%; } }

.spinner {
  width: 15px; height: 15px; border: 2px solid var(--border);
  border-top-color: var(--accent); border-radius: 50%;
  animation: spin .7s linear infinite; display: inline-block;
}
@keyframes spin { to { transform: rotate(360deg); } }

.toast-host { position: fixed; right: 18px; bottom: 18px; display: flex; flex-direction: column; gap: 8px; z-index: 50; }
.toast {
  background: var(--panel-2); border: 1px solid var(--border); border-left-width: 3px;
  border-radius: var(--radius); padding: 10px 14px; max-width: 380px;
  box-shadow: 0 4px 18px rgba(0, 0, 0, .5);
}
.toast.error { border-left-color: var(--danger); }
.toast.ok { border-left-color: var(--ok); }
.toast.info { border-left-color: var(--accent); }

.muted { color: var(--muted); }
.mono { font-family: var(--mono); }
/* The session-import panel accepts a dragged .mpct, like the file slots. */
.panel.dragover { border-color: var(--accent); background: #22312f; }
.session-status:empty { display: none; }
.session-status { margin-top: 10px; }

/* --- sign-in ------------------------------------------------------------
   Shown in place of the app, not over it: with no login every API call is
   refused, so there is nothing behind to see. */
.login-screen {
  height: 100vh; display: flex; align-items: center; justify-content: center;
  background: var(--bg); padding: 20px;
}
.login-card {
  width: 340px; max-width: 100%;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 6px; padding: 22px 24px 24px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, .45);
}
.login-brand { display: flex; align-items: center; gap: 11px; margin-bottom: 20px; }
.login-brand .login-icon { width: 30px; height: 30px; }
.login-title {
  font-family: var(--font-display); font-weight: 700; font-size: 17px;
  letter-spacing: 1px;
}
.login-subtitle { color: var(--muted); font-size: 11px; }
.login-form { display: flex; flex-direction: column; gap: 12px; }
.login-field { display: flex; flex-direction: column; gap: 4px; }
.login-field span {
  font-family: var(--font-display); font-size: 11px; color: var(--muted);
  letter-spacing: .5px;
}
.login-field input { padding: 7px 9px; }
.login-form .notice { margin-bottom: 0; }
.login-form .btn { margin-top: 2px; padding: 7px; }
.titlebar .signed-in {
  font-family: var(--font-display); font-size: 12px; color: var(--muted);
}

.hidden { display: none !important; }
.pill {
  display: inline-block; padding: 1px 8px; border-radius: 9px; font-size: 11px;
  background: var(--panel-2); border: 1px solid var(--border); color: var(--muted);
}

/* --- Feature Info -------------------------------------------------------
   The full feature list on top, the selected feature's detail below, with a
   draggable boundary. Only the table body scrolls, so the arrow keys always
   move the selection instead of scrolling the page away underneath it. */

.features-view .plot-host { flex: 1; min-height: 0; display: flex; gap: 0;
  padding: 14px 18px; }
.table-pane { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; }
.table-pane > .plot-toolbar {
  padding: 4px 10px; gap: 8px; font-size: 12px;
  background: var(--panel-2); color: var(--text);
  border: 1px solid var(--border); border-bottom: none;
  border-radius: var(--radius) var(--radius) 0 0;
}
.table-pane > .plot-toolbar .status { color: var(--muted); }
.table-pane > .plot-toolbar label,
.table-pane > .plot-toolbar .check,
.table-pane > .plot-toolbar .check span { color: var(--muted); }
.table-pane > .plot-toolbar input[type="checkbox"] { accent-color: var(--accent); }
.table-pane > .plot-toolbar .btn { background: var(--control); color: var(--text); border-color: #565656;
  padding: 2px 8px; font-size: 12px; }
.table-pane > .plot-toolbar .check { padding: 0; gap: 5px; }
.table-pane > .plot-toolbar .btn:hover:not(:disabled) { background: var(--control-hover); }
.table-scroll {
  flex: 1; min-height: 0; overflow: auto;
  border: 1px solid var(--border); border-top: none;
  border-radius: 0 0 var(--radius) var(--radius); background: var(--panel);
  outline: none;
}
.table-scroll:focus-visible { box-shadow: inset 0 0 0 1px var(--accent); }

table.features { width: 100%; table-layout: fixed; }
table.features th, table.features td { padding: 4px 7px; }
table.features tbody tr { height: 25px; }        /* must match ROW_HEIGHT in featureinfo.js */
table.features tbody tr.spacer-row { height: 0; }
table.features tbody tr.spacer-row td { padding: 0; border: none; }
table.features td { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
table.features thead th { z-index: 2; }
table.features thead tr:nth-child(2) th {
  top: 27px; padding: 3px 5px; font-weight: 400; background: var(--panel);
}
table.features thead input, table.features thead select { width: 100%; padding: 2px 5px; font-size: 11px; }
table.features .range-filter { display: flex; gap: 3px; }
table.features .range-filter input { width: 50%; min-width: 0; padding: 2px 3px;
  appearance: textfield; -moz-appearance: textfield; }
table.features .range-filter input::-webkit-inner-spin-button,
table.features .range-filter input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
/* Column widths, set on the heading cells (the table's layout is fixed, so
   the first row decides). Compound ids and set lists are long; the numbers
   share what is left, and the two leading marks take only what they need. */
table.features th.col-0 { width: 19%; }
table.features th.col-4 { width: 16%; }
table.features th.col-sel { width: 30px; }
table.features th.col-flag { width: 36px; }
table.features th.col-sel, table.features td.col-sel,
table.features th.col-flag, table.features td.col-flag {
  text-align: center; padding-left: 1px; padding-right: 1px; text-overflow: clip;
}
/* The filter row pads its cells more than this; not under these two. */
table.features thead tr:nth-child(2) th.col-sel,
table.features thead tr:nth-child(2) th.col-flag { padding-left: 1px; padding-right: 1px; }
/* The Flag filter's button, narrowed to its column: just the count and caret. */
table.features thead th.col-flag .cat-button { padding: 2px 2px; gap: 1px; }
table.features thead th.col-flag .cat-caret { font-size: 8px; }
/* Headings line up with what is under them: numbers are right-aligned. */
table.features th.num { text-align: right; }
table.features td.col-sel { color: var(--accent); font-weight: 700; cursor: pointer; }
table.features td.col-flag { cursor: pointer; }
table.features td.col-sel:hover, table.features td.col-flag:hover { background: rgba(255,255,255,0.06); }

/* Category (Sets) column filter: a button that opens a checkbox popup, the
   web form of the desktop's checkable-action menu. A multi-select listbox
   one row tall, which this replaces, is not operable with a mouse. */
.cat-filter { position: relative; }
.cat-button {
  display: flex; align-items: center; gap: 4px; width: 100%;
  background: #1c1c1c; color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 2px 5px; font-size: 11px; cursor: pointer; text-align: left;
}
.cat-button:hover { border-color: #565656; }
.cat-filter.active .cat-button { border-color: var(--accent); color: #fff; }
.cat-button .cat-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cat-button .cat-caret { color: var(--muted); font-size: 9px; }
.cat-menu {
  position: absolute; z-index: 20; top: 100%; left: 0; min-width: 100%;
  max-height: 240px; overflow: auto; margin-top: 2px;
  background: var(--panel-2); border: 1px solid #565656;
  border-radius: var(--radius); padding: 3px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .45);
}
.cat-option {
  display: flex; align-items: center; gap: 6px; white-space: nowrap;
  padding: 3px 6px; border-radius: var(--radius); cursor: pointer; font-size: 12px;
}
.cat-option:hover { background: var(--panel); }
.cat-option input { accent-color: var(--accent); margin: 0; }
.cat-empty { padding: 4px 6px; font-size: 12px; }
.tri-option { width: 100%; background: none; border: none; color: var(--text); text-align: left; }
.tri-box {
  width: 14px; height: 14px; flex: none; display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid #6a6a6a; border-radius: 2px; background: #1c1c1c; font-size: 11px; line-height: 1;
}
.tri-box.in { background: var(--accent); border-color: var(--accent); color: #fff; }
.tri-box.out { background: var(--danger); border-color: var(--danger); color: #fff; }

.kv.wide { grid-template-columns: max-content 1fr; column-gap: 20px; }

/* --- database match browser (details rail) ------------------------------
   Structure and hit list together, with the structure following the
   highlighted hit, as the desktop's compound window shows them. */
.matches-panel { display: flex; flex-direction: column; gap: 8px; }
.match-nav { display: flex; align-items: center; justify-content: center; gap: 10px; }
.match-nav.with-toggle { justify-content: space-between; }
.match-steps { display: flex; align-items: center; gap: 8px; }
.source-toggle { display: flex; }
.source-toggle .btn { border-radius: 0; }
.source-toggle .btn:first-child { border-radius: var(--radius) 0 0 var(--radius); }
.source-toggle .btn:last-child { border-radius: 0 var(--radius) var(--radius) 0; border-left: none; }
.matches-body { display: flex; flex-direction: column; gap: 8px; }
.match-nav .btn { padding: 1px 9px; line-height: 1.3; }
/* A constant height, so stepping from hit to hit -- each drawing a different
   size, and the box empty while the next one loads -- never changes the
   rail's length under you. (At the bottom of the rail a shorter box pulled
   the whole panel up a step.) */
.matches-panel .structure {
  background: #ffffff; border-radius: var(--radius); padding: 6px;
  height: 204px; display: flex; align-items: center; justify-content: center;
}
.matches-panel .structure img { max-height: 190px; max-width: 100%; }
.match-caption { text-align: center; font-size: 12px; min-height: 6.2em; }
.match-caption .match-title { font-weight: 600; color: var(--text); margin-bottom: 2px; }
.match-list {
  max-height: 168px; overflow: auto;
  border: 1px solid var(--border); border-radius: var(--radius); background: #1c1c1c;
  outline: none;
}
.match-list:focus-visible { box-shadow: inset 0 0 0 1px var(--accent); }
.match-row {
  display: flex; width: 100%; gap: 8px; align-items: baseline;
  padding: 4px 8px; background: none; border: none; border-bottom: 1px solid #262626;
  color: var(--text); cursor: pointer; text-align: left; font-size: 12px;
}
.match-row:last-child { border-bottom: none; }
.match-row:hover { background: var(--panel); }
.match-row.active { background: #2b3a38; color: #fff; }
.match-row .match-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.match-row .match-ppm { color: var(--muted); font-variant-numeric: tabular-nums; }
.match-row.active .match-ppm { color: #cfe9e5; }
.kv dd.ok { color: var(--ok); }
.kv dd.bad { color: var(--warn); }
.detail-fields { display: flex; gap: 46px; flex-wrap: wrap; align-items: flex-start; }
.detail-fields h5 {
  margin: 0 0 8px; font-size: 11px; letter-spacing: 1px; text-transform: uppercase;
  color: var(--muted); font-weight: 600;
}
.matches { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 14px; align-items: start; }
.matches-table { max-height: 100%; overflow: auto; }
.matches .structure { width: 260px; }

.kv { display: grid; grid-template-columns: auto 1fr; gap: 3px 14px; font-size: 12px; }
.kv dt { color: var(--muted); }
.kv dd { margin: 0; font-variant-numeric: tabular-nums; }

/* Details rail: the app's right-hand panel, the counterpart of the navigation
   bar on the left. It runs the full height of the window and carries its own
   header, including the control that hides it, so clicking a point answers
   "what is this?" without leaving the tab. Mirrors the desktop's feature
   labels + Details window. */
.details-rail {
  flex: 0 0 auto; min-height: 0; overflow: hidden;
  display: flex; flex-direction: column;
  background: var(--panel); border-left: 1px solid var(--border);
}
.rail-header {
  flex: 0 0 auto; display: flex; align-items: center; gap: 8px;
  padding: 8px 8px 8px 14px;
  background: var(--panel-2); border-bottom: 1px solid var(--border);
}
.rail-header .rail-title {
  font-size: 11px; letter-spacing: 1px; text-transform: uppercase;
  color: var(--muted); font-weight: 600;
}
.rail-header .spacer { flex: 1; }
.rail-collapse {
  background: none; border: 1px solid transparent; border-radius: var(--radius);
  color: var(--muted); cursor: pointer; font-size: 15px; line-height: 1;
  padding: 1px 8px;
}
.rail-collapse:hover {
  color: var(--text); border-color: var(--border); background: var(--panel);
}
.details-rail.empty .rail-sections { align-items: center; justify-content: center; }
.details-rail.collapsed {
  width: 0 !important; flex-basis: 0 !important;
  padding: 0; border: none; overflow: hidden;
}

/* Drag handle between the main region and the rail. */
.rail-splitter {
  flex: 0 0 5px; cursor: col-resize; position: relative;
  background: var(--bg);
}
.rail-splitter::before {
  content: ''; position: absolute; inset: 0 1px;
  background: var(--border);
}
.rail-splitter:hover::before, .rail-splitter.dragging::before { background: var(--accent); }
.rail-splitter.hidden-splitter { display: none; }

/* The tab that reopens a collapsed rail. */
.rail-toggle {
  flex: 0 0 22px; width: 22px; align-self: stretch;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--radius); color: var(--muted);
  cursor: pointer; padding: 0; font-size: 11px;
  writing-mode: vertical-rl; text-orientation: mixed;
}
.rail-toggle:hover { color: var(--text); border-color: var(--accent); }
.details-rail h4 {
  margin: 0 0 10px; font-size: 13px; font-weight: 600;
  word-break: break-all; line-height: 1.35;
}
.details-rail .rail-head { display: flex; align-items: flex-start; gap: 8px; }
.details-rail .rail-head button { margin-left: auto; flex: 0 0 auto; }
.details-rail .rail-sections {
  flex: 1; min-height: 0; overflow: auto; padding: 12px 14px;
  display: flex; flex-direction: column; gap: 7px;
}
.details-rail .collapsible { border-top: 1px solid var(--border); padding-top: 6px; }
.details-rail .collapsible > .collapsible-body { padding-top: 7px; }
.details-rail .collapsible:first-of-type { border-top: none; padding-top: 0; }
.details-rail .mini-plot {
  /* Two panels now (group means beside the per-injection strip, as the
     desktop draws them), which needs more than a single bar chart did. The
     height is set inline from the rail's saved layout and dragged by the
     handle below. */
  background: var(--plot-bg); border-radius: var(--radius); height: 235px;
}
.details-rail .mini-plot-wrap { display: flex; flex-direction: column; }
/* The boundary under a plot panel: drag it to divide the rail's height
   between the abundance chart and the spectrum. */
.details-rail .section-resizer {
  flex: 0 0 9px; height: 9px; cursor: row-resize; position: relative;
}
.details-rail .section-resizer::before {
  content: ''; position: absolute; left: 38%; right: 38%; top: 4px; height: 2px;
  background: #4a4a4a; border-radius: 1px;
}
.details-rail .section-resizer:hover::before,
.details-rail .section-resizer.dragging::before { background: var(--accent); }
.details-rail .mini-plot .placeholder {
  position: static; display: flex; align-items: center; justify-content: center;
  height: 100%; font-size: 11px; padding: 8px; text-align: center;
}
.details-rail .rail-actions { margin-top: auto; padding-top: 10px; display: flex; gap: 6px; }
.details-rail .rail-actions .btn { width: 100%; }

.structure { background: #fff; border-radius: var(--radius); padding: 6px; text-align: center; }
.structure svg, .structure img { max-width: 100%; height: auto; }

/* --- links styled as buttons (downloads) ------------------------------- */

a.btn {
  display: inline-block; text-decoration: none; line-height: normal;
  background: var(--control); border: 1px solid #565656; color: var(--text);
  border-radius: var(--radius); padding: 6px 14px; cursor: pointer;
}
a.btn:hover { background: var(--control-hover); }
a.btn.small { padding: 3px 9px; font-size: 12px; }

/* --- sample list / metadata editor ------------------------------------- */

dialog.mapping {
  background: var(--panel); color: var(--text); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 0;
  width: min(1180px, 96vw); height: min(880px, 92vh);
}
dialog.mapping[open] { display: flex; flex-direction: column; }
dialog.mapping::backdrop { background: rgba(0, 0, 0, .55); }
.mapping .spacer { flex: 1; }
.mapping .m-head, .mapping .m-rules, .mapping .m-example, .mapping .m-status, .mapping .m-foot {
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap; padding: 8px 16px;
}
.mapping .m-head { border-bottom: 1px solid var(--border); padding-top: 12px; }
.mapping .m-head h3 { margin: 0 8px 0 0; font-family: var(--font-display); font-size: 15px; }
.mapping .m-rules { gap: 14px; padding-top: 10px; }
.mapping .m-rules .rule { display: inline-flex; align-items: center; gap: 4px; }
.mapping .m-rules .check { padding: 0; gap: 5px; }
.mapping input.short { width: 52px; font-family: var(--mono); }
dialog.mapping:focus, dialog.mapping:focus-visible { outline: none; }
.mapping input.mid { width: 110px; }
.mapping .m-example { padding-top: 2px; font-size: 12px; }
.mapping .m-example .mono { font-size: 12px; }
.mapping .tokens { display: inline-flex; align-items: center; gap: 1px; font-family: var(--mono); }
.mapping .tok {
  padding: 1px 6px; border-radius: 3px; background: #1c1c1c; border: 1px solid var(--border);
  font-family: var(--mono); font-size: 12px;
}
.mapping .tok.click { cursor: pointer; }
.mapping .tok.click:hover { border-color: var(--muted); }
.mapping .tok.tech { border-color: var(--warn); color: #e8cf9c; }
.mapping .tok.bio { border-color: var(--accent); color: #9fe0d8; }
.mapping .tok.drop { opacity: .45; text-decoration: line-through; }
.mapping .sep { color: var(--muted); }
.mapping .legend { margin-left: auto; display: inline-flex; gap: 6px; }
.mapping .legend .tok { font-family: var(--font); font-size: 11px; }
.mapping .m-status { border-top: 1px solid var(--border); font-size: 12px; }
.mapping .m-status input[type="search"] { width: 180px; }
.mapping .m-status .stats { color: var(--muted); }
.mapping .m-status .warn { color: var(--warn); }
.mapping .m-status .bad { color: var(--danger); }
.mapping .m-status .okay { color: var(--ok); }
.mapping .pill.click { cursor: pointer; color: var(--text); border-color: var(--accent); }
.mapping .m-body { flex: 1; min-height: 0; display: flex; gap: 12px; padding: 0 16px 8px; }
.mapping .m-table, .mapping .m-groups {
  min-height: 0; overflow: auto; border: 1px solid var(--border); background: var(--panel-2);
}
.mapping .m-table { flex: 1; min-width: 0; }
.mapping .m-table table { width: 100%; border-collapse: collapse; }
.mapping .m-table th {
  position: sticky; top: 0; z-index: 1; background: #333; text-align: left;
  padding: 5px 8px; font-weight: 600; font-size: 12px;
}
.mapping .m-table td { padding: 2px 6px; border-top: 1px solid #343434; }
.mapping .m-table td input { width: 100%; padding: 3px 6px; }
.mapping .m-table td input:placeholder-shown { border-color: var(--danger); }
.mapping .m-table td.inj { font-family: var(--mono); font-size: 12px; white-space: nowrap; }
.mapping .m-table tr.missing td.inj { color: var(--warn); }
.mapping .m-groups { width: 300px; flex: 0 0 300px; }
.mapping .m-groups .g {
  display: flex; gap: 6px; align-items: center; padding: 3px 6px; border-top: 1px solid #343434;
}
.mapping .m-groups .g.head {
  position: sticky; top: 0; background: #333; border-top: none; font-weight: 600; font-size: 12px;
  padding: 5px 8px; justify-content: space-between;
}
.mapping .m-groups .g.active { background: #2b3a38; }
.mapping .m-groups .g input { flex: 1; min-width: 0; padding: 3px 6px; }
.mapping .m-groups .g .n {
  color: var(--muted); font-size: 11px; white-space: nowrap; cursor: pointer; min-width: 44px;
  text-align: right;
}
.mapping .m-groups .g .n.single { color: var(--warn); }
.mapping .m-groups .g.head .n { cursor: default; color: var(--muted); font-weight: 400; }
.mapping .m-foot { border-top: 1px solid var(--border); padding: 10px 16px; }
.mapping .m-foot .notice { margin: 0; flex: 1 1 100%; }
.mapping .m-empty {
  flex: 1; display: flex; flex-direction: column; gap: 10px; align-items: center; justify-content: center;
}

/* Costume menu for the Run terminal's dinosaur, opened from the MPACT icon. */
.dino-menu {
  position: fixed; z-index: 50; min-width: 150px;
  display: flex; flex-direction: column;
  background: var(--panel-2); border: 1px solid #565656;
  border-radius: var(--radius); padding: 3px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .45);
}
.dino-menu button {
  background: none; border: 0; color: var(--text); text-align: left;
  padding: 3px 8px 3px 20px; border-radius: var(--radius);
  font: inherit; font-size: 12px; cursor: default; position: relative;
}
.dino-menu button:hover, .dino-menu button:focus-visible { background: var(--panel); outline: none; }
.dino-menu button[aria-checked="true"]::before {
  content: "\2713"; position: absolute; left: 6px; color: var(--accent);
}

/* --- Feature Info hit filters ------------------------------------------ */
.table-pane > .plot-toolbar.hit-filters {
  border-radius: 0; border-top: 1px solid var(--border);
  flex-direction: column; align-items: stretch; gap: 4px;
}
.hit-filters .hit-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.hit-filters .hit-row .spacer { flex: 1; }

.hit-filters input.cosine-min { width: 58px; }
.collapse-toggle {
  background: none; border: none; color: var(--muted); cursor: pointer;
  font-size: 12px; padding: 0 2px; width: 16px;
}
.collapse-toggle:hover { color: var(--text); }
.table-pane > .plot-toolbar .hit-row .btn { background: var(--control); color: var(--text);
  border-color: #565656; padding: 2px 8px; font-size: 12px; }
.hit-filters label, .hit-filters .hit-field {
  display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted);
}
.hit-filters input[type="text"], .hit-filters input[type="number"], .hit-filters select {
  background: #1c1c1c; color: var(--text); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 2px 6px; font-size: 12px;
}
.hit-filters input.hit-name { width: 130px; }
.hit-filters input.hit-name:not(:placeholder-shown) { border-color: var(--accent); }
.hit-filters .cat-filter { width: 130px; }
.hit-filters .cat-button { font-size: 12px; padding: 2px 6px; }
.hit-filters .activity-filter .cat-menu { min-width: 260px; }
.hit-filters .cat-option input.conj-min { width: 52px; padding: 1px 4px; }
.hit-filters .substructure-filter { display: flex; gap: 2px; width: auto; }
.substructure-filter .cat-button { width: auto; }
.cat-clear {
  background: none; border: none; color: var(--muted); cursor: pointer; padding: 0 3px; font-size: 14px;
}
.cat-clear:hover { color: var(--text); }
.taxon-picker { display: flex; align-items: center; gap: 6px; }
.taxon-picker select { width: auto; flex: none; }
.taxon-picker .suggest { flex: 1; min-width: 0; }
.field .taxon-picker .suggest input.taxon-input { width: 100%; }
.suggest { position: relative; }
.suggest input.taxon-input { width: 120px; }
.suggest.active input.taxon-input { border-color: var(--accent); }
.suggest-menu { min-width: 260px; }
.suggest-option { justify-content: space-between; gap: 14px; }
.suggest-option.active { background: var(--panel); }

/* --- substructure sketcher --------------------------------------------- */
dialog.sketcher {
  background: var(--panel); color: var(--text); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 0; width: 676px;
}
dialog.sketcher::backdrop { background: rgba(0, 0, 0, .55); }
dialog.sketcher:focus, dialog.sketcher:focus-visible { outline: none; }
.sketcher .sk-head { padding: 12px 16px 6px; }
.sketcher .sk-head h3 { margin: 0; font-family: var(--font-display); font-size: 15px; }
.sketcher .sk-editor {
  width: 640px; height: 380px; margin: 0 16px; background: #fff; border-radius: var(--radius);
  display: flex; align-items: center; justify-content: center; color: #555;
}
.sketcher .sk-row { padding: 8px 16px 0; }
.sketcher .sk-smiles { width: 100%; font-family: var(--mono); }
.sketcher .sk-foot { display: flex; align-items: center; gap: 8px; padding: 10px 16px 14px; }
.sketcher .sk-foot .spacer { flex: 1; }
.sketcher .sk-error { color: var(--danger); font-size: 12px; }

/* --- rail match tags --------------------------------------------------- */
.match-caption .match-tags { color: var(--warn); margin-top: 2px; }
.match-caption .match-tags:empty { display: none; }
.match-row.filtered-out { opacity: .45; }

/* --- multiple selection -------------------------------------------------- */

/* Rows are picked like files: the focused one (the feature the details rail
   describes) is marked among the selected. */
table.features tbody tr { cursor: default; }
table.features tbody tr.selected.focused {
  background: #35504b; box-shadow: inset 3px 0 0 var(--accent);
}
table.features tbody tr.pending td { color: var(--muted); }

/* The selection, at the top of the details rail when it is more than one. */
.rail-selection {
  border-bottom: 1px solid var(--border); padding: 8px 10px 10px; flex: 0 0 auto;
}
.rail-selection .selection-head { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; }
.rail-selection .selection-head strong { font-size: 12px; }
.rail-selection .selection-list {
  max-height: 150px; overflow-y: auto; background: #1c1c1c;
  border: 1px solid var(--border); border-radius: var(--radius);
}
.rail-selection .selection-item { display: flex; align-items: stretch; border-bottom: 1px solid #262626; }
.rail-selection .selection-item:last-child { border-bottom: none; }
.rail-selection .selection-item.active { background: #2b3a38; }
.rail-selection .selection-item button {
  background: none; border: none; color: var(--text); font: inherit; font-size: 12px;
  cursor: pointer; padding: 3px 7px;
}
.rail-selection .selection-name {
  flex: 1; min-width: 0; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rail-selection .selection-item button:hover { color: #fff; background: var(--panel); }
.rail-selection .selection-remove { color: var(--muted); flex: 0 0 auto; }
.rail-selection .selection-more { padding: 3px 7px; font-size: 12px; }

/* Group buckets: picked groups, and the row that moves them. */
.bucket li { user-select: none; }
.move-row .pick-note { font-size: 12px; }

/* The label for the next run. */
.run-label { display: flex; align-items: center; gap: 8px; margin: 4px 0 10px; }
.run-label input { flex: 1; max-width: 460px; }

/* --- flags ---------------------------------------------------------------- */

/* A flag: a disc of the flag's colour with a dark rim, like its plot marker. */
.flag-dot {
  display: inline-block; width: 11px; height: 11px; border-radius: 50%;
  border: 1px solid #000; box-shadow: 0 0 0 1px rgba(255,255,255,0.22);
  vertical-align: middle;
}
.flag-controls { display: inline-flex; align-items: center; gap: 5px; }
input.flag-colour {
  -webkit-appearance: none; appearance: none;
  width: 20px; height: 20px; padding: 0; flex: 0 0 20px;
  border: 1px solid #000; border-radius: 50%; background: none; cursor: pointer;
  box-shadow: 0 0 0 1px rgba(255,255,255,0.22); overflow: hidden;
}
input.flag-colour::-webkit-color-swatch-wrapper { padding: 0; }
input.flag-colour::-webkit-color-swatch { border: none; border-radius: 50%; }
input.flag-colour::-moz-color-swatch { border: none; border-radius: 50%; }

.rail-selection .selection-flag { margin-bottom: 6px; }
.rail-selection .selection-flag .btn { padding: 2px 8px; font-size: 12px; }

/* The focused feature's flag, beside its name in the rail. */
.details-rail .rail-head button.flag-toggle {
  margin-left: auto; width: 20px; height: 20px; padding: 0; flex: 0 0 20px;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: 1px solid transparent; border-radius: 50%; cursor: pointer;
}
.details-rail .rail-head button.flag-toggle:hover { border-color: var(--border); background: var(--panel-2); }
.details-rail .rail-head button.flag-toggle .flag-dot { border-style: dashed; border-color: var(--muted); box-shadow: none; }
.details-rail .rail-head button.flag-toggle.flagged .flag-dot {
  border-style: solid; border-color: #000; box-shadow: 0 0 0 1px rgba(255,255,255,0.22);
}
.details-rail .rail-head button.flag-toggle + button { margin-left: 4px; }

/* The Sel and Flag filters, in the filter row under their headings. */
table.features thead input.sel-only {
  width: 14px; height: 14px; margin: 0; padding: 0; vertical-align: middle;
  accent-color: var(--accent); cursor: pointer;
}
.flag-filter .cat-button { padding: 2px 3px; gap: 2px; }
.flag-filter .cat-button .cat-label { text-align: center; }
.flag-menu { min-width: 120px; }
.flag-menu .tri-option .muted { margin-left: auto; padding-left: 10px; font-size: 11px; }
table.features tbody tr.empty-row td {
  text-align: center; color: var(--muted); padding: 18px 10px; white-space: normal;
}
table.features tbody tr.empty-row:hover { background: none; }

/* Holds the rail's height while a new feature's sections load (see
   detailsrail.js); must not shrink, or it holds nothing. */
.details-rail .rail-hold { flex: none; margin-top: -7px; }
/* No scroll anchoring here: the rail restores its own position across
   features, and the browser's anchoring then moved it again as each section
   above filled in, so it crept down a little further with every feature. */
.details-rail .rail-sections { overflow-anchor: none; }

/* --- email sign-in -------------------------------------------------------- */
.login-step { display: flex; flex-direction: column; gap: 12px; }
.login-note { margin: 0; color: var(--muted); font-size: 12px; line-height: 1.45; }
.login-code { font-size: 20px; letter-spacing: 4px; text-align: center; font-variant-numeric: tabular-nums; }
.login-links { display: flex; justify-content: space-between; gap: 10px; }
.link-button {
  background: none; border: none; padding: 0; color: var(--accent); cursor: pointer;
  font: inherit; font-size: 12px;
}
.link-button:hover:not(:disabled) { text-decoration: underline; }
.link-button:disabled { color: var(--muted); cursor: default; }

/* --- admin ------------------------------------------------------------------ */
.admin-view .panel h3 input[type=search] { margin-left: auto; width: 220px; font-weight: 400; }
.admin-view table.admin-users select { padding: 2px 4px; font-size: 12px; }
.admin-view .pill { margin-left: 6px; }
.admin-view .allowlist { display: flex; flex-wrap: wrap; gap: 6px; }
.admin-view .allow-entry { display: inline-flex; align-items: center; gap: 4px; margin-left: 0; }
.admin-view .allow-entry button {
  background: none; border: none; color: var(--muted); cursor: pointer; padding: 0 2px; font-size: 13px;
}
.admin-view .allow-entry button:hover { color: var(--text); }
.admin-view form input[type=text] { width: 300px; }
