/* ==========================================================================
   RenderDeck - application stylesheet
   Served at /static/css/app.css (see modules/server/api.py static mount).

   Tailwind (CDN) supplies the utility layer; everything here is the component
   layer on top of it: theme tokens, surfaces, controls and page-specific prose.
   Loaded from index.html at the same point in <head> the inline <style> used
   to sit, so the cascade order against Tailwind is unchanged.
   ========================================================================== */

/* ── Theme tokens ─────────────────────────────────────────────── */

/* The graphite workspace palette, fixed rather than themed. The Overview and
   the Queue Manager are dark-only instruments - a render wall is read in a
   dark room - so their planes reference these directly and stay put when the
   rest of the app switches to light. Dark maps its own tokens onto them, which
   is what keeps every other page on the same surfaces. 
   16191c   or 181b1d test graphite panel 
   */
:root {
  --gr-canvas: #0d0f11;
  --gr-panel:  #15161d;
  --gr-raised: #1a1b23;
  --gr-line:   #34373a;
  --gr-line-strong: #43464a;
  --gr-input:  #141618;
  /* Hover is a wash, not a colour: a translucent white laid over whatever
     surface the element already sits on, so every plane keeps its own hue
     instead of drifting toward the old #1d2023 teal. -soft is for table and
     list rows, the plain token for controls. */
  --gr-hover:      rgba(255,255,255,.05);
  --gr-hover-soft: rgba(255,255,255,.035);
}

/* Dark is the graphite workspace the Queue Manager established: #0D0F11 is
   navigation and header chrome, #15181A is the working canvas, and every
   separator is a flat #34373A hairline. Opaque planes on purpose - the old
   translucent panels stacked into muddy greys once two of them overlapped. */
html.dark {
  --bg-0: var(--gr-canvas);
  --bg-1: var(--gr-canvas);
  --bg-2: var(--gr-raised);
  --panel: var(--gr-panel);
  --panel-hover: var(--gr-hover);
  --border: var(--gr-line);
  --border-strong: var(--gr-line-strong);
  --text: rgba(255,255,255,0.92);
  --text-mid: rgba(255,255,255,0.66);
  --text-dim: rgba(255,255,255,0.45);
  --text-faint: rgba(255,255,255,0.30);
  --input-bg: var(--gr-input);
  --shadow: 0 18px 40px -18px rgba(0,0,0,0.7);
  --scroll: rgba(255,255,255,0.14);
  --code-bg: #101214;
}
html.light {
  --bg-0: #f5f6fb;
  --bg-1: #ffffff;
  --bg-2: #eef0f7;
  --panel: rgba(255,255,255,0.9);
  --panel-hover: rgba(15,17,23,.045);
  --border: rgba(15,17,23,0.09);
  --border-strong: rgba(15,17,23,0.16);
  --text: #14151d;
  --text-mid: rgba(20,21,29,0.66);
  --text-dim: rgba(20,21,29,0.48);
  --text-faint: rgba(20,21,29,0.32);
  --input-bg: #ffffff;
  --shadow: 0 18px 40px -22px rgba(31,41,90,0.28);
  --scroll: rgba(15,17,23,0.18);
  --code-bg: rgba(15,17,23,0.05);
}

/* ── Typeface tokens ──────────────────────────────────────────────
   --f-ui   drives html/body plus Tailwind's font-sans utility.
   --f-data drives .mono and the .doc code/dt/pre rules below.
   Switched at runtime via html[data-font="..."] - see setFont() /
   applyFont() in app.js (Settings -> Display -> Typeface) and the
   pre-paint script in index.html that sets the attribute from
   localStorage('rd_font') before first render, same pattern as
   html.dark/html.light for theme. All families load unconditionally
   in index.html's Google Fonts <link> so switching never triggers a
   network fetch or a flash of fallback type. Default: Red Hat. ── */
html, html[data-font="redhat"] {
  --f-ui: 'Red Hat Text', system-ui, -apple-system, sans-serif;
  --f-data: 'Red Hat Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
/* Inter ships no monospace, so --f-data used to drop to whatever the OS calls
   ui-monospace - which is not a face the user picked, and made every id, path
   and counter on the data pages ignore the setting. IBM Plex Mono is already
   in the same Google Fonts request and pairs with Inter's grotesque shapes. */
html[data-font="inter"] {
  --f-ui: 'Inter', system-ui, -apple-system, sans-serif;
  --f-data: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
html[data-font="jetbrains"] {
  --f-ui: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  --f-data: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
html[data-font="plex"] {
  --f-ui: 'IBM Plex Sans', system-ui, -apple-system, sans-serif;
  --f-data: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

html, body { font-family: var(--f-ui); -webkit-font-smoothing: antialiased; }
/* The dark shell is a flat plane: the indigo/violet wash the app used to sit
   on fought every opaque panel above it. Light keeps its tint. */
body {
  background: var(--bg-0);
  color: var(--text);
  background-attachment: fixed;
}
html.light body {
  background-image:
    radial-gradient(1200px 600px at 0% -10%, rgba(99,102,241,0.10), transparent 60%),
    radial-gradient(900px 500px at 100% 8%, rgba(168,85,247,0.07), transparent 55%),
    radial-gradient(900px 700px at 50% 115%, rgba(34,211,238,0.06), transparent 60%);
}
[x-cloak] { display: none !important; }

::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--scroll); border-radius: 999px; }
::-webkit-scrollbar-thumb:hover { background: var(--border-strong); }

.text-mid { color: var(--text-mid); }
.text-dim { color: var(--text-dim); }
.text-faint { color: var(--text-faint); }

/* ── Surfaces ────────────────────────────────────────────────── */
.card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 1rem;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

.surface-2 { background: var(--bg-2); border: 1px solid var(--border); }
.divide-border > * + * { border-top: 1px solid var(--border); }

/* ── Buttons ─────────────────────────────────────────────────── */
.btn-primary {
  background: linear-gradient(135deg, #6366f1 0%, #a855f7 52%, #ec4899 100%);
  color: #fff;
  transition: filter .18s ease, transform .12s ease, box-shadow .18s ease;
  box-shadow: 0 10px 26px -10px rgba(168,85,247,0.55);
}
.btn-primary:hover { filter: brightness(1.08); }
.btn-primary:active { transform: translateY(1px); }
.btn-primary:disabled { filter: grayscale(0.5) brightness(0.8); opacity: .6; cursor: not-allowed; box-shadow: none; }

/* Path Maps view switcher: the two modes are page-level views, not filters. */
.pm-mode-switch {
  display: inline-flex; align-items: center; gap: 4px; padding: 4px;
  border: 1px solid var(--border); border-radius: 12px;
  background: rgba(0,0,0,.16); width: fit-content;
}
.pm-mode-button {
  display: inline-flex; align-items: center; gap: 8px; min-height: 36px;
  padding: 0 14px; border-radius: 8px; color: var(--text-mid);
  font-size: 13px; font-weight: 600; transition: all .18s ease;
}
.pm-mode-button svg { width: 16px; height: 16px; }
.pm-mode-button:hover { color: var(--text); background: var(--panel-hover); }
.pm-mode-button.is-active {
  color: #fff; background: linear-gradient(135deg, #6366f1, #a855f7);
  box-shadow: 0 8px 20px -10px rgba(168,85,247,.8);
}
html.light .pm-mode-button.is-active { color: #fff; }

.btn-ghost {
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--text);
  transition: all .15s ease;
}
.btn-ghost:hover { background: var(--panel-hover); border-color: var(--border-strong); }
.btn-ghost:disabled { opacity: .4; cursor: not-allowed; }

.btn-danger { background: rgba(244,63,94,0.14); border: 1px solid rgba(244,63,94,0.35); color: #fb7185; transition: all .15s ease; }
.btn-danger:hover { background: rgba(244,63,94,0.22); }
.btn-danger:disabled { opacity: .4; cursor: not-allowed; }

.btn-warning { background: rgba(245,158,11,0.14); border: 1px solid rgba(245,158,11,0.35); color: #fbbf24; transition: all .15s ease; }
.btn-warning:hover { background: rgba(245,158,11,0.22); }
.btn-warning:disabled { opacity: .4; cursor: not-allowed; }

/* Same sky blue as .st-ready, as a button shell rather than a status chip -
   Reset uses it so it reads as its own tinted action instead of a plain
   .icon-btn grey box, matching how Delete (rose) and Clear completed
   (amber) already carry their colour at rest, not just on hover. */
.btn-info { background: rgba(56,189,248,0.14); border: 1px solid rgba(56,189,248,0.35); color: #38bdf8; transition: all .15s ease; }
.btn-info:hover { background: rgba(56,189,248,0.22); }
.btn-info:disabled { opacity: .4; cursor: not-allowed; }

/* Top-bar notice chips - the trial licence notice and the demo notice. They
   sit side by side, so anything that sizes them from their own contents lets
   them drift apart: the demo chip was 9px taller than the trial one purely
   because its reset control was a 30px .icon-btn (Tailwind-trimmed to 24px)
   against the trial's 15px text button. One height and one button footprint
   for both, so a future chip cannot reintroduce the mismatch. Colour stays
   inline per chip - that is the part that legitimately differs. */
.rd-topbar-chip { height:26px; display:flex; align-items:center; gap:8px; padding:0 8px; border-radius:4px; font-size:10px; line-height:1; }
.rd-topbar-chip-btn { height:18px; flex-shrink:0; display:inline-flex; align-items:center; justify-content:center; padding:0 6px; border-radius:3px; font-size:10px; font-weight:500; line-height:1; }
.rd-topbar-chip-btn:hover { opacity:.8; }
.rd-topbar-chip-btn svg { width:12px; height:12px; }

.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 8px;
  background: var(--panel); border: 1px solid var(--border);
  color: var(--text-mid); transition: all .15s ease; cursor: pointer;
}
.icon-btn:hover { background: var(--panel-hover); border-color: var(--border-strong); color: var(--text); }
.icon-btn:disabled { opacity: .3; cursor: not-allowed; }
.icon-btn:disabled:hover { background: var(--panel); border-color: var(--border); color: var(--text-mid); }

/* ── Priority stepper (job cards) ────────────────────────────────
   Same shell as the .icon-btn action buttons it now sits beside: 32px tall,
   --panel fill, hairline border, 8px radius. The difference is that the
   border wraps the whole control rather than each button, so the row reads
   as one stepper instead of three boxes. */
.prio {
  display: inline-flex; align-items: center; height: 32px;
  border-radius: 8px; background: var(--panel); border: 1px solid var(--border);
  overflow: hidden; transition: border-color .15s ease;
}
.prio:hover { border-color: var(--border-strong); }
.prio-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 100%; cursor: pointer;
  color: var(--text-mid);
  transition: color .14s ease, background .14s ease, opacity .14s ease;
}
.prio-btn:hover { color: var(--text); background: var(--panel-hover); }
.prio-btn:disabled { opacity: .3; cursor: not-allowed; }
.prio-btn:disabled:hover { color: var(--text-mid); background: transparent; }
.prio-val {
  min-width: 20px; padding: 0 1px; text-align: center;
  font-size: 12px; font-weight: 600; color: var(--text-mid);
}
/* A priority of 0 is the default on most rows - keep it out of the way.
   Needs both classes to outrank .prio-val's own colour. */
.prio-val.text-faint { color: var(--text-faint); }

/* ── Inputs ──────────────────────────────────────────────────── */
.input-base {
  background: var(--input-bg);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 0.7rem;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.input-base::placeholder { color: var(--text-faint); }
.input-base:focus { outline: none; border-color: rgba(99,102,241,0.6); box-shadow: 0 0 0 3px rgba(99,102,241,0.18); }
select.input-base option { background: var(--bg-1); color: var(--text); }

/* ── Nav pills ───────────────────────────────────────────────── */
.nav-active {
  background: linear-gradient(135deg, rgba(99,102,241,0.22), rgba(168,85,247,0.18));
  color: var(--text);
  border: 1px solid rgba(168,85,247,0.32);
}
html.light .nav-active { color: #4c1d95; }
.nav-inactive { color: var(--text-mid); border: 1px solid transparent; }
.nav-inactive:hover { background: var(--panel-hover); color: var(--text); }
/* Queue Manager is an ordinary nav row now. The standing violet outline it
   used to wear competed with the active-page marker for the same job; the
   hero accent moves onto the icon alone, which still reads as the primary
   action without framing one item differently from its neighbours. */
.nav-hero svg { color:#a855f7; }
.nav-hero:hover svg { color:#c084fc; }
.nav-active.nav-hero svg { color:#c4b5fd; }
html.light .nav-hero svg { color:#7c3aed; }

/* ── Status chips ────────────────────────────────────────────── */
.chip { display:inline-flex; align-items:center; gap:6px; padding:3px 10px; border-radius:999px;
  font-size:11px; font-weight:600; line-height:1.4; letter-spacing:.015em;
  border:1px solid transparent; white-space:nowrap; }
/* Job-card status: the same neutral grey shell as the priority stepper, so the
   two sit on the row as a matched pair. The st-* class still supplies the
   colour, which now lives only in the dot and the label. */
.chip.chip-neutral {
  background: var(--panel); border-color: var(--border);
  border-radius: 8px; height: 32px; padding: 0 10px;
}
/* Labels are title-cased in JS (statusLabel), so the dot needs a hair more
   optical spacing from the cap height than the old lowercase text wanted. */
.chip-dot { width:5px; height:5px; border-radius:999px; margin-right:1px; flex-shrink:0; }
/* Mobile job-row status indicator: same chip shell, label stripped out so the
   name/status/actions fit one line on narrow viewports. Collapses to a small
   circle instead of a pill now that there's no text to pad around. */
.chip-dot-only { width:22px; height:22px; padding:0; justify-content:center; flex-shrink:0; }
.chip-dot-only .chip-dot { width:6px; height:6px; margin-right:0; }
.st-success   { background: rgba(16,185,129,0.14); color:#34d399; border-color: rgba(16,185,129,0.30); }
.st-progress  { background: rgba(245,158,11,0.14); color:#fbbf24; border-color: rgba(245,158,11,0.32); }
.st-error     { background: rgba(244,63,94,0.14);  color:#fb7185; border-color: rgba(244,63,94,0.32); }
/* Cancelled: the error rose, faded out. Same family, deliberately quieter -
   a cancelled render is not a failure and must not out-shout one. Kept in
   sync with the "Cancelled" slice of the reports donut. */
.st-cancelled { background: rgba(244,63,94,0.07); color:#c98d99; border-color: rgba(244,63,94,0.18); }
.st-idle      { background: rgba(148,163,184,0.14);color:#94a3b8; border-color: rgba(148,163,184,0.30); }
.st-ready     { background: rgba(56,189,248,0.14); color:#38bdf8; border-color: rgba(56,189,248,0.30); }
.st-paused    { background: rgba(168,85,247,0.14); color:#c084fc; border-color: rgba(168,85,247,0.30); }
html.light .st-success  { color:#059669; }
html.light .st-progress { color:#b45309; }
html.light .st-error    { color:#e11d48; }
html.light .st-cancelled{ color:#b0707c; }
html.light .st-idle     { color:#475569; }
html.light .st-ready    { color:#0284c7; }
html.light .st-paused   { color:#7c3aed; }

/* Bare glowing status dot for job rows - same visual language as the worker
   "online" indicator on Overview (a plain currentColor dot with a soft glow),
   not the boxed chip-dot-only pill. Pair it with an st-* class for colour:
   declared after the st-* rules above so this background/border win over
   theirs at equal specificity, while colour (and so currentColor here) still
   comes from st-*. */
.status-dot {
  width: 8px; height: 8px; border-radius: 999px; flex-shrink: 0;
  background: currentColor; border: none;
  box-shadow: 0 0 8px currentColor;
}

/* Status-chip filter buttons (jobs view + overview strip use the same st-*
   chips; only the ones wired up as a filter get this behaviour). A
   colour-matched ring (currentColor, so no per-key rule is needed) marks the
   active filter instead of one flat indigo highlight. */
.chip.chip-filter {
  cursor: pointer; padding: 5px 11px;
  transition: filter .15s ease, box-shadow .15s ease, transform .08s ease;
}
.chip.chip-filter:hover { filter: brightness(1.16); }
.chip.chip-filter:active { transform: translateY(1px); }
.chip.chip-filter.is-active { box-shadow: 0 0 0 1.5px currentColor; filter: brightness(1.22); }

/* Instant hover tooltip - icon-only buttons (job bulk actions and similar)
   pair an .icon-btn with a sibling .tip inside a .tip-anchor wrapper. The
   wrapper (not the button) owns :hover so a disabled button still shows its
   tip. Near-zero delay on purpose: the point is to beat the browser's slow
   native title tooltip, not to replicate it. */
.tip-anchor { position: relative; }
.tip-anchor .tip {
  position: absolute; bottom: calc(100% + 7px); left: 50%;
  transform: translateX(-50%) translateY(2px);
  background: var(--bg-1); color: var(--text);
  border: 1px solid var(--border-strong); box-shadow: var(--shadow);
  font-size: 11px; font-weight: 600; white-space: nowrap;
  padding: 5px 9px; border-radius: 7px;
  opacity: 0; pointer-events: none; z-index: 30;
  transition: opacity .08s ease, transform .08s ease;
}
.tip-anchor .tip::after {
  content: ''; position: absolute; top: 100%; left: 50%; transform: translateX(-50%);
  border: 5px solid transparent; border-top-color: var(--border-strong);
}
.tip-anchor .tip::before {
  content: ''; position: absolute; top: calc(100% - 1px); left: 50%; transform: translateX(-50%);
  border: 4px solid transparent; border-top-color: var(--bg-1);
}
.tip-anchor:hover .tip, .tip-anchor:focus-within .tip { opacity: 1; transform: translateX(-50%) translateY(0); }
/* Rightmost icon in a row (e.g. Delete) - on a phone width a centred tip
   clips off the edge of the screen, so anchor it to the button's right edge
   instead. Desktop has room to spare, so keep it centred (and the arrow
   pointing straight at the icon) above that breakpoint. */
@media (max-width: 639px) {
  .tip-anchor.tip-right .tip { left: auto; right: 0; transform: translateY(2px); }
  .tip-anchor.tip-right:hover .tip, .tip-anchor.tip-right:focus-within .tip { transform: translateY(0); }
  .tip-anchor.tip-right .tip::after { left: auto; right: 10px; transform: none; }
  .tip-anchor.tip-right .tip::before { left: auto; right: 11px; transform: none; }
}

.tag-chip { display:inline-flex; align-items:center; padding:2px 8px; border-radius:6px; font-size:11px; font-weight:500;
  background: var(--bg-2); color: var(--text-mid); border:1px solid var(--border); }

/* Meta chips on job cards - clickable (chip-link) vs informational (chip-static).
   Sized down twice now from the original 11px/2.5px-9px/5px-gap: the worker +
   preset chips on a job row still out-weighed the job name at the first pass
   (10px/2px-7px/4px-gap), so this is a second, larger step down. Icons are
   constrained to match via a descendant rule (they were riding the un-scaled
   w-3 h-3 Tailwind class in the markup) rather than edited at every call site. */
.chip-key { color: var(--text-faint); text-transform: uppercase; letter-spacing:.05em; font-size:8px; font-weight:700; }
.chip-link, .chip-static {
  display:inline-flex; align-items:center; gap:3px; white-space:nowrap;
  padding:1px 6px; border-radius:999px; font-size:9px; font-weight:500;
  border:1px solid var(--border); background: var(--bg-2); color: var(--text-mid);
}
.chip-link svg, .chip-static svg { width:8px; height:8px; flex-shrink:0; }
.chip-link { cursor:pointer; transition: color .14s ease, border-color .14s ease, background .14s ease, box-shadow .14s ease; }
.chip-link:hover { color: var(--text); border-color: rgba(99,102,241,0.55); background: var(--panel-hover); box-shadow: 0 0 0 3px rgba(99,102,241,0.13); }
.chip-link:active { transform: translateY(0.5px); }
.chip-static { opacity:.85; }

.mono { font-family: var(--f-data); }

/* ── Progress bar ────────────────────────────────────────────── */
.pbar-track { height: 8px; border-radius: 999px; background: var(--bg-2); overflow: hidden; border:1px solid var(--border); }
.pbar-fill { height: 100%; border-radius: 999px; transition: width .4s ease; }
.pbar-default { background: linear-gradient(90deg, #6366f1, #a855f7); }
.pbar-success { background: linear-gradient(90deg, #10b981, #34d399); }
.pbar-error   { background: linear-gradient(90deg, #f43f5e, #fb7185); }
.pbar-cancelled { background: linear-gradient(90deg, #a8636e, #c98d99); }

/* ── Job card left status rail ───────────────────────────────── */
.rail { position:absolute; left:0; top:0; bottom:0; width:3px; border-radius: 1rem 0 0 1rem; }
.rail-success { background: linear-gradient(180deg,#10b981,#34d399); }
.rail-progress{ background: linear-gradient(180deg,#f59e0b,#fbbf24); }
.rail-error   { background: linear-gradient(180deg,#f43f5e,#fb7185); }
.rail-cancelled { background: linear-gradient(180deg,#a8636e,#c98d99); }
.rail-idle    { background: var(--border-strong); }

/* ── Checkbox ────────────────────────────────────────────────── */
input[type="checkbox"].rd-check {
  appearance: none; -webkit-appearance: none;
  width: 17px; height: 17px; border: 1.5px solid var(--border-strong);
  border-radius: 5px; background: var(--input-bg); cursor: pointer;
  display: inline-grid; place-content: center; transition: all .12s ease; flex-shrink:0;
}
input[type="checkbox"].rd-check:checked { background: linear-gradient(135deg,#6366f1,#a855f7); border-color: transparent; }
input[type="checkbox"].rd-check:checked::after {
  content:""; width:10px; height:10px;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='white'><path d='M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z'/></svg>") center/contain no-repeat;
}

/* ── Toggle switch ───────────────────────────────────────────── */
.switch { position:relative; width:38px; height:22px; border-radius:999px; background: var(--bg-2); border:1px solid var(--border); cursor:pointer; transition: background .18s ease, border-color .18s ease; flex-shrink:0; }
.switch.on { background: linear-gradient(135deg,#6366f1,#a855f7); border-color: transparent; }
.switch .knob { position:absolute; top:2px; left:2px; width:16px; height:16px; border-radius:999px; background:#fff; transition: transform .18s ease; box-shadow:0 1px 3px rgba(0,0,0,.3); }
.switch.on .knob { transform: translateX(16px); }

/* Modal + toast animation */
@keyframes rdPop { from { transform: translateY(8px) scale(.98); opacity:0; } to { transform: translateY(0) scale(1); opacity:1; } }
.rd-pop { animation: rdPop .16s cubic-bezier(.2,.8,.2,1); }
@keyframes rdSlide { from { transform: translateX(120%); opacity:0; } to { transform: translateX(0); opacity:1; } }
.rd-slide { animation: rdSlide .22s cubic-bezier(.2,.8,.2,1); }

/* ── Notification centre ───────────────────────────────────── */
.rd-notification-button { position:relative; }
.rd-notification-dot { position:absolute; top:5px; right:5px; width:7px; height:7px; border-radius:50%; background:#fb7185; border:1px solid var(--bg-1); }
.rd-notification-popover { position:absolute; top:calc(100% + 9px); right:0; width:min(360px, calc(100vw - 24px)); background:var(--bg-1); border:1px solid var(--border-strong); border-radius:6px; box-shadow:var(--shadow); overflow:hidden; z-index:80; }
.rd-notification-header { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:10px 12px; border-bottom:1px solid var(--border); }
.rd-notification-header strong { display:block; font-size:12px; }
.rd-notification-header small { display:block; color:var(--text-dim); font-size:10px; margin-top:2px; }
.rd-notification-clear { color:#a5b4fc; font-size:10px; white-space:nowrap; }
.rd-notification-list { max-height: min(420px, calc(100vh - 110px)); overflow-y:auto; }
.rd-notification-item { display:flex; align-items:flex-start; gap:9px; padding:10px 10px 10px 12px; border-bottom:1px solid color-mix(in srgb, var(--border) 65%, transparent); }
.rd-notification-item:last-child { border-bottom:0; }
.rd-notification-marker { width:7px; height:7px; border-radius:50%; margin-top:5px; flex:0 0 auto; }
.rd-notification-copy { min-width:0; flex:1; }
.rd-notification-copy p { margin:0; color:var(--text); font-size:11px; line-height:1.4; overflow-wrap:anywhere; }
.rd-notification-copy small { display:block; color:var(--text-dim); font-size:10px; margin-top:3px; }
.rd-notification-dismiss { color:var(--text-dim); padding:2px; flex:0 0 auto; }
.rd-notification-dismiss svg { width:13px; height:13px; }
.rd-notification-empty { display:flex; align-items:center; justify-content:center; gap:7px; color:var(--text-dim); font-size:11px; padding:28px 12px; }
.rd-notification-empty svg { width:14px; height:14px; color:#34d399; }

.no-scrollbar::-webkit-scrollbar { display:none; }
.no-scrollbar { scrollbar-width: none; }
.pb-safe { padding-bottom: max(env(safe-area-inset-bottom), 0.5rem); }
.pt-safe { padding-top: max(env(safe-area-inset-top), 0.5rem); }
/* The sidebar brand block and the page top bar share this row so their
   bottom borders line up exactly. The floor is what the top bar already
   measures (a 39px select inside 12px padding); the padding keeps taller
   content from crowding the edges rather than silently overflowing. */
.bar-row { display: flex; align-items: center; min-height: 63px; padding-top: .75rem; padding-bottom: .75rem; }

/* ── Docs page prose ─────────────────────────────────────────── */
/* Each section carries its own accent (set inline as --accent) so the
   contents rail, the heading marker and the card edge all agree. */
.doc { scroll-margin-top: 5rem; position: relative; overflow: hidden; }
.doc::before { content:''; position:absolute; left:0; top:0; bottom:0; width:3px;
  background: var(--accent, transparent); opacity: .85; }
.doc h2 { font-size: 15px; font-weight: 600; letter-spacing: -.01em;
  display: flex; align-items: center; gap: .5rem; }
.doc h2::before { content:''; width: 9px; height: 9px; border-radius: 3px; flex: none;
  background: var(--accent, var(--text-faint));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent, transparent) 18%, transparent); }
.doc h3 { color: var(--accent, var(--text-mid)); }
.doc h3 { font-size: 13px; font-weight: 600; margin-top: 1.25rem; }
.doc p  { font-size: 13px; line-height: 1.65; color: var(--text-mid); }
.doc b  { color: var(--text); font-weight: 600; }
.doc ul, .doc ol { font-size: 13px; line-height: 1.65; color: var(--text-mid); padding-left: 1.15rem; }
.doc ul { list-style: disc; } .doc ol { list-style: decimal; }
.doc li { margin-top: .3rem; }
.doc li::marker { color: var(--text-faint); }
.doc dl { display: grid; grid-template-columns: minmax(7.5rem, auto) 1fr; gap: .45rem 1rem; font-size: 13px; line-height: 1.6; }
.doc dt { font-weight: 600; color: var(--text); font-family: var(--f-data); font-size: 12px; }
.doc dd { color: var(--text-mid); }
.doc code { font-family: var(--f-data); font-size: 12px;
  background: var(--bg-2); border: 1px solid var(--border); border-radius: 5px; padding: 1px 5px; color: var(--text); }
.doc pre { font-family: var(--f-data); font-size: 11.5px; line-height: 1.6;
  background: var(--bg-2); border: 1px solid var(--border); border-radius: 10px; padding: .85rem 1rem;
  color: var(--text-mid); overflow-x: auto; white-space: pre; }
@media (max-width: 640px) { .doc dl { grid-template-columns: 1fr; gap: .15rem; } .doc dd { margin-bottom: .5rem; } }

pre.json { white-space: pre-wrap; word-break: break-word; background: var(--code-bg); border:1px solid var(--border); border-radius:.75rem; padding:14px; font-size:12px; line-height:1.55; color: var(--text); }

/* New Queue: dense full-height workspace matching the production reference.
   The top bar hide lives in queue-manager.css, next to the header that
   replaces it, rather than being declared in two stylesheets. */
.rd-newqueue-page { height:100%; min-height:0; display:flex; flex-direction:column; gap:12px; }
.rd-newqueue-workspace { height:100%; min-height:0; }
.rd-newqueue-page > .rd-newqueue-workspace { flex:1; }
.rd-workspace-toolbar { min-height:40px; display:flex; align-items:center; justify-content:space-between; gap:12px; flex-shrink:0; }
.rd-workspace-actions { display:flex; align-items:center; gap:8px; }
.rd-newqueue-workspace { display:flex; flex-direction:column; gap:16px; }
.rd-newqueue-titlebar { display:flex; align-items:center; justify-content:space-between; min-height:40px; }
.rd-newqueue-titlebar h1 { font-size:25px; font-weight:700; letter-spacing:-.03em; }
.rd-nq-button { display:inline-flex; align-items:center; justify-content:center; gap:8px; height:38px; padding:0 17px; border-radius:7px; font-size:14px; font-weight:600; white-space:nowrap; transition:.15s ease; }
.rd-nq-button svg { width:17px; height:17px; }.rd-nq-button-muted { color:var(--text); background:rgba(255,255,255,.045); border:1px solid var(--border-strong); }.rd-nq-button-primary { color:#fff; background:linear-gradient(135deg,#4d55e8,#4547d3); border:1px solid rgba(116,121,255,.65); box-shadow:0 7px 20px -9px #5561ff; }.rd-nq-button:disabled { opacity:.42; cursor:not-allowed; filter:grayscale(.4); box-shadow:none; }
.rd-newqueue-grid { display:grid; grid-template-columns:383px minmax(0,1fr); gap:12px; flex:1; min-height:0; }
.rd-shot-panel,.rd-batch-panel,.rd-draft-panel { background:linear-gradient(145deg,rgba(255,255,255,.045),rgba(255,255,255,.018)); border:1px solid var(--border-strong); border-radius:8px; overflow:hidden; }
.rd-shot-panel { display:flex; flex-direction:column; min-height:0; }.rd-panel-heading { min-height:52px; padding:0 18px; display:flex; align-items:center; justify-content:space-between; border-bottom:1px solid var(--border); }.rd-panel-heading h2,.rd-draft-heading h2 { font-size:16px; font-weight:700; }.rd-selected-count { font-size:12px; color:#cbd5e1; }.rd-link { color:#777dff; font-size:13px; }
.rd-shot-search { height:59px; padding:10px 12px; display:flex; align-items:center; gap:9px; border-bottom:1px solid var(--border); }.rd-shot-search>svg { width:18px; height:18px; color:var(--text-dim); }.rd-shot-search input { flex:1; min-width:0; height:35px; background:rgba(0,0,0,.16); border:1px solid var(--border); color:var(--text); padding:0 10px; outline:none; font-size:13px; }.rd-filter-button { width:34px; height:35px; border-radius:6px; background:rgba(255,255,255,.04); border:1px solid var(--border); color:var(--text-mid); display:grid; place-items:center; }.rd-filter-button svg { width:17px; height:17px; }.rd-shot-list { flex:1; min-height:0; overflow-y:auto; }
.rd-scene-group + .rd-scene-group { border-top:1px solid var(--border); }.rd-scene-heading { width:100%; height:50px; padding:0 18px; display:flex; justify-content:space-between; align-items:center; text-align:left; color:var(--text); }.rd-scene-heading strong { font-size:14px; margin-right:4px; }.rd-scene-heading em { font-size:14px; font-style:normal; color:var(--text-mid); }.rd-scene-heading b { font-size:12px; font-weight:500; color:var(--text-mid); }.rd-scene-heading svg { width:15px; height:15px; color:var(--text-mid); transition:transform .15s; }
.rd-scene-heading > span:first-child { min-width:0; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; }
.rd-shot-row { min-height:63px; padding:7px 12px 7px 15px; display:flex; align-items:center; gap:9px; border-top:1px solid rgba(255,255,255,.055); }.rd-shot-row.is-selected { background:rgba(78,86,238,.12); }.rd-thumb { width:70px; height:47px; flex-shrink:0; border-radius:6px; border:1px solid rgba(255,255,255,.14); background:linear-gradient(135deg,#182d4a,#633864 45%,#101722); position:relative; overflow:hidden; }.rd-thumb::after { content:''; position:absolute; inset:16px 9px 0; border-top:1px solid rgba(255,255,255,.35); transform:skewY(-20deg); box-shadow:0 -7px 0 rgba(255,255,255,.18),17px 8px 0 rgba(255,193,102,.32); }.rd-thumb-1{background:linear-gradient(135deg,#274b70,#a26c55 45%,#162435)}.rd-thumb-2{background:linear-gradient(135deg,#101928,#3d4560 52%,#9a7146)}.rd-thumb-3{background:linear-gradient(135deg,#263b3f,#6f4b59 48%,#121b26)}.rd-thumb-4{background:linear-gradient(135deg,#172c4c,#405d7a 46%,#171e2a)}.rd-thumb-5{background:linear-gradient(135deg,#4d3b36,#172d46 48%,#836947)}
.rd-shot-row.is-queued { opacity:.42; background:rgba(255,255,255,.018); }
.rd-shot-row.is-queued .rd-add-shot { filter:grayscale(1); }
.rd-shot-copy { flex:1; min-width:0; display:flex; flex-direction:column; gap:3px; }.rd-shot-copy strong { font-size:12px; font-weight:500; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }.rd-shot-copy small,.rd-batch-fields small,.rd-draft-table small { color:var(--text-dim); font-size:11px; white-space:nowrap; }.rd-shot-state { width:28px; height:24px; display:grid; place-items:center; flex-shrink:0; border:1px solid; border-radius:7px; }.rd-shot-state svg { width:16px; height:16px; }.rd-shot-state.linked { color:#5cdb91; border-color:rgba(92,219,145,.35); background:rgba(92,219,145,.10); }.rd-shot-state.missing { color:#ffb52c; border-color:rgba(255,181,44,.35); background:rgba(255,181,44,.10); }.rd-add-shot { width:30px; height:30px; border-radius:6px; border:1px solid var(--border-strong); background:rgba(255,255,255,.05); display:grid; place-items:center; color:var(--text); flex-shrink:0; }.rd-add-shot svg { width:17px; height:17px; }.rd-shot-footer,.rd-draft-footer { min-height:60px; padding:0 18px; display:flex; align-items:center; justify-content:space-between; border-top:1px solid var(--border); font-size:12px; color:var(--text-mid); }.rd-shot-footer .rd-nq-button { height:36px; padding:0 14px; font-size:12px; font-weight:500; }
.rd-queue-column { display:flex; flex-direction:column; gap:12px; min-width:0; min-height:0; }.rd-batch-panel { flex:0 0 auto; }.rd-batch-heading { min-height:52px; }.rd-collapse-button { color:var(--text-mid); }.rd-collapse-button svg { width:16px; height:16px; transition:transform .15s; }.rd-batch-fields { display:grid; grid-template-columns:1.05fr 1.05fr 1.05fr 1.05fr; padding:14px 10px 13px; }.rd-batch-fields>label { min-width:0; padding:0 12px; border-right:1px solid var(--border); }.rd-batch-fields>label:last-child { border-right:0; }.rd-batch-fields label>span:first-child { display:block; color:#d0d7e7; font-size:12px; margin-bottom:9px; }.rd-select-wrap { position:relative; }.rd-select-wrap::after { content:'⌄'; position:absolute; right:11px; top:7px; color:var(--text-mid); pointer-events:none; }.rd-batch-fields select,.rd-master-select { width:100%; height:36px; border-radius:6px; border:1px solid var(--border-strong); padding:0 12px; color:var(--text); background:rgba(0,0,0,.14); font-size:13px; appearance:none; overflow:hidden; text-overflow:ellipsis; }.rd-batch-fields small { display:block; margin:7px 0 0 12px; }.rd-priority-field i { display:inline-grid; place-items:center; width:14px; height:14px; border:1px solid var(--text-dim); border-radius:50%; font-style:normal; font-size:10px; }.rd-range-row { display:flex; align-items:center; gap:9px; }.rd-range-row input { flex:1; accent-color:#6b70ff; }.rd-range-row output { width:40px; height:36px; display:grid; place-items:center; border:1px solid var(--border-strong); border-radius:6px; font-size:13px; }.rd-range-labels { display:flex; justify-content:space-between; }.rd-range-labels small { margin:6px 0 0; }.rd-master-check { height:36px; display:flex; align-items:center; gap:9px; font-size:13px; color:var(--text-mid); }.rd-master-select { height:34px; text-align:left; color:var(--text-dim); }.rd-add-selected-row { display:flex; justify-content:flex-end; min-height:39px; }
.rd-draft-panel { flex:1; min-height:0; display:flex; flex-direction:column; }.rd-draft-heading { min-height:55px; padding:0 17px; display:flex; align-items:center; justify-content:space-between; border-bottom:1px solid var(--border); }.rd-job-count { color:var(--text-mid); font-size:13px; }.rd-draft-tools { display:flex; align-items:center; gap:12px; }.rd-summary-pill { display:inline-flex; gap:8px; align-items:center; padding:7px 12px; border:1px solid rgba(80,100,200,.4); border-radius:6px; color:#aeb9ef; font-size:12px; }.rd-summary-pill svg { width:16px; height:16px; }.rd-warning-pill { color:#ffc02e; border-color:rgba(255,177,0,.3); }.rd-draft-table-wrap { flex:1; min-height:0; overflow:auto; }.rd-draft-table { width:100%; min-width:780px; border-collapse:collapse; table-layout:fixed; }.rd-draft-table th { height:45px; padding:0 12px; background:rgba(255,255,255,.035); color:#c8ceda; font-size:12px; font-weight:500; text-align:left; }.rd-draft-table th:first-child { width:54px; padding-left:35px; }.rd-draft-table td { height:60px; padding:0 12px; border-top:1px solid var(--border); color:#d8deea; font-size:13px; vertical-align:middle; position:relative; }.rd-draft-table td:first-child { padding-left:35px; }.rd-draft-table td strong,.rd-draft-table td small { display:block; overflow:hidden; text-overflow:ellipsis; }.rd-draft-table td small { margin-top:4px; }.rd-row-rail { position:absolute; left:8px; top:0; bottom:0; width:10px; border-radius:3px; background:#676dff; }.rd-row-rail.warning { background:#f3ae27; }.rd-status { font-size:12px; }.rd-status.ready { color:#5cdb91; }.rd-status.warning { color:#ffb52c; }.rd-more-button { color:#d7dce8; letter-spacing:2px; }.rd-empty-row td { text-align:center; color:var(--text-dim); }.rd-draft-footer button { color:#ff5f5f; }.rd-draft-footer button:disabled { opacity:.35; cursor:not-allowed; }
@media (max-width:1100px) { .rd-newqueue-grid { grid-template-columns:315px minmax(0,1fr); }.rd-batch-fields { grid-template-columns:1fr 1fr; row-gap:14px; }.rd-batch-fields>label:nth-child(2) { border-right:0; }.rd-batch-fields>label:nth-child(n+3) { padding-top:12px; border-top:1px solid var(--border); } }
@media (max-width:800px) { .rd-newqueue-app main>.flex-1 { overflow-y:auto; }.rd-newqueue-app main>.flex-1>div { height:auto; }.rd-newqueue-grid { grid-template-columns:1fr; }.rd-shot-panel,.rd-draft-panel { min-height:480px; }.rd-draft-tools { display:none; } }

/* Compact New Queue density: keep the reference hierarchy while making the
   working area show more shots and jobs before scrolling. */
@media (min-width:801px) {
  .rd-newqueue-workspace { gap:12px; }
  .rd-newqueue-titlebar { min-height:36px; }
  .rd-newqueue-titlebar h1 { font-size:23px; }
  .rd-nq-button { height:34px; padding:0 14px; font-size:13px; }
  .rd-panel-heading { min-height:44px; padding:0 14px; }
  .rd-panel-heading h2,.rd-draft-heading h2 { font-size:15px; }
  .rd-shot-search { height:48px; padding:7px 10px; }
  .rd-shot-search input,.rd-filter-button { height:32px; }
  .rd-shot-row { min-height:52px; padding:5px 10px 5px 12px; gap:8px; }
  .rd-thumb { width:60px; height:39px; }
  .rd-add-shot { width:28px; height:28px; }
  .rd-scene-heading { height:42px; padding:0 14px; }
  .rd-shot-footer,.rd-draft-footer { min-height:48px; padding:0 14px; }
  .rd-shot-footer .rd-nq-button { height:32px; }
  .rd-batch-fields { padding:10px 7px; }
  .rd-batch-fields>label { padding:0 10px; }
  .rd-batch-fields label>span:first-child { margin-bottom:6px; }
  .rd-batch-fields select,.rd-master-select,.rd-range-row output { height:32px; }
  .rd-batch-fields small { margin-top:5px; }
  .rd-master-check { height:32px; }
  .rd-add-selected-row { min-height:32px; }
  .rd-add-selected-row .rd-nq-button { height:32px; }
  .rd-draft-heading { min-height:46px; padding:0 14px; }
  .rd-summary-pill { padding:5px 9px; }
  .rd-draft-table th { height:38px; }
  .rd-draft-table td { height:50px; }
}

/* Shot rows are intentionally text-first: the map link is useful metadata,
   while thumbnails consume width without helping queue selection. */
.rd-shot-row .rd-thumb { display:none; }
.rd-shot-version { width:26px; flex-shrink:0; text-align:right; color:var(--text-mid); font-size:11px; font-variant-numeric:tabular-nums; }
.rd-shot-copy small { overflow:hidden; text-overflow:ellipsis; }
.rd-scene-heading { padding:0; }
.rd-scene-toggle { flex:1; min-width:0; height:100%; padding:0 10px 0 14px; display:flex; align-items:center; justify-content:space-between; text-align:left; color:var(--text); }
.rd-scene-select { align-self:stretch; padding:0 10px; color:#8990ff; font-size:11px; white-space:nowrap; border-left:1px solid var(--border); }
.rd-scene-select:hover { background:rgba(99,102,241,.1); color:#b7bbff; }
.rd-scene-toggle svg { width:15px; height:15px; color:var(--text-mid); transition:transform .15s; }
.rd-master-mark { width:20px; height:20px; display:inline-grid; place-items:center; border:1px solid var(--border-strong); border-radius:50%; color:transparent; font-size:14px; font-weight:700; }
.rd-master-mark.is-master { color:#61df9a; border-color:#61df9a; background:rgba(16,185,129,.1); }
.rd-draft-table .rd-row-rail { display:none; }
.rd-draft-table td:first-child { padding-left:35px; }
.rd-output-cell { display:flex; align-items:center; justify-content:space-between; gap:12px; min-width:0; }
.rd-output-cell strong { color:var(--text); font-size:13px; white-space:nowrap; }
.rd-output-cell small { margin-top:0 !important; margin-left:auto; text-align:right; overflow:hidden; text-overflow:ellipsis; }
.rd-table-edit { width:26px; height:26px; display:inline-grid; place-items:center; color:var(--text-mid); border-radius:5px; }
.rd-table-edit:hover { color:var(--text); background:rgba(255,255,255,.08); }
.rd-table-delete:hover { color:#fb7185; }
.rd-table-edit svg { width:15px; height:15px; }
.rd-draft-table th:nth-child(1) { width:54px; }
.rd-draft-table th:nth-child(2) { width:23%; }
.rd-draft-table th:nth-child(3) { width:24%; }
.rd-draft-table th:nth-child(4) { width:15%; }
.rd-draft-table th:nth-child(5) { width:11%; }
.rd-draft-table th:nth-child(6) { width:11%; }
.rd-draft-table th:last-child { width:72px; }
.rd-draft-table td:last-child { padding-left:4px; padding-right:18px; text-align:right; }
.rd-output-cell { flex-direction:column; align-items:flex-start; justify-content:center; gap:2px; }
.rd-output-cell strong { font-size:12px; }
.rd-output-cell small { max-width:100%; margin-left:0 !important; text-align:left; }
.rd-select-wrap::after { display:none; }
.rd-batch-fields select { appearance:auto; -webkit-appearance:auto; padding-right:8px; }
.rd-topbar-collapsed { height:34px; overflow:visible; }
.rd-topbar-collapsed .bar-row { min-height:34px; height:34px; padding-top:0; padding-bottom:0; justify-content:flex-end; }
.rd-topbar-collapsed .bar-row > *:not(.ml-auto), .rd-topbar-collapsed .ml-auto > * { display:none !important; }

/* ── Standard page furniture ──────────────────────────────────────
   The pages that still scroll inside the centred column - Workers, Pipelines,
   Logs, Settings - share these instead of each inventing its own header row
   and card padding. Themed tokens, not the graphite ones: unlike the
   workspaces, these pages work in light mode too. */
.pg-ribbon {
  margin-bottom:10px; padding:6px 12px; min-height:44px;
  display:flex; flex-wrap:wrap; align-items:center; gap:8px 10px;
  border:1px solid var(--border); border-radius:4px; background:var(--panel);
}
.pg-ribbon h2 { margin:0; font-size:13px; font-weight:600; letter-spacing:-.01em; }
.pg-note { min-width:0; color:var(--text-mid); font-size:12px; }
.pg-note b { color:var(--text); font-weight:600; }
.pg-spacer { flex:1; }
.pg-actions { display:flex; align-items:center; gap:6px; }
.pg-btn {
  height:30px; padding:0 11px; display:inline-flex; align-items:center; gap:6px;
  border:1px solid var(--border); border-radius:4px; background:var(--panel);
  color:var(--text); font-size:12px; font-weight:600; white-space:nowrap;
}
.pg-btn:hover { background:var(--panel-hover); border-color:var(--border-strong); }
.pg-btn:disabled { opacity:.4; cursor:not-allowed; }
.pg-btn:disabled:hover { background:var(--panel); border-color:var(--border); }
.pg-btn svg { width:14px; height:14px; flex:none; }
.pg-btn-primary { border-color:transparent; color:#fff; background:linear-gradient(135deg,#6366f1 0%,#a855f7 52%,#ec4899 100%); }
.pg-btn-primary:hover { filter:brightness(1.08); }
.pg-btn-danger { color:#e08b93; }
html.light .pg-btn-danger { color:#b03a48; }

/* Cards on these pages: one padding, one radius, one grid gap. */
.pg-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(360px,1fr)); gap:10px; }
.pg-card { padding:14px; border:1px solid var(--border); border-radius:4px; background:var(--panel); }
.pg-card + .pg-card { margin-top:0; }
.pg-card-head { display:flex; align-items:center; gap:9px; min-width:0; }
.pg-tile { width:26px; height:26px; flex:none; display:grid; place-items:center; border:1px solid var(--border); border-radius:4px; background:var(--bg-2); color:var(--text-mid); }
.pg-tile svg { width:14px; height:14px; }
.pg-title { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:13.5px; font-weight:600; letter-spacing:-.01em; }
/* Label beside value, not above it in a two-up grid: these fields are mostly
   long paths, and half a card's width truncated them to nothing. The value now
   gets every pixel the label does not need. */
.pg-kv { margin-top:11px; display:grid; grid-template-columns:76px minmax(0,1fr); row-gap:6px; column-gap:12px; align-items:baseline; }
.pg-kv dt { color:var(--text-dim); font-size:10px; letter-spacing:.02em; }
.pg-kv dd { margin:0; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font:12px var(--f-data); color:var(--text); }
.pg-kv dd.is-muted { color:var(--text-dim); }
/* Long values wrap rather than ellipsise: a truncated render path identifies
   nothing, and a two-line card is cheaper than a tooltip nobody hovers. */
.pg-kv dd.is-wrap { white-space:normal; overflow-wrap:anywhere; overflow:visible; line-height:1.45; }
.pg-metric { padding:8px 10px; border:1px solid var(--border); border-radius:4px; background:var(--bg-2); }
.pg-metric span { display:block; color:var(--text-dim); font-size:10px; }
.pg-metric b { display:block; margin-top:2px; font-size:16px; font-weight:600; font-variant-numeric:tabular-nums; }
.pg-foot { margin-top:10px; padding-top:9px; display:flex; align-items:center; gap:8px; border-top:1px solid var(--border); }
.pg-empty { padding:34px 16px; display:flex; flex-direction:column; align-items:center; gap:9px; border:1px solid var(--border); border-radius:4px; background:var(--panel); color:var(--text-dim); font-size:12px; }
.pg-empty svg { width:22px; height:22px; opacity:.45; }

/* ── Workspace shell ──────────────────────────────────────────────
   Pages that own the viewport rather than scrolling inside the default
   centred column: Overview, Render Jobs, Reports, Queue Manager. One
   definition instead of the same three lines per page class. */
.rd-workspace main > .flex-1 { overflow:hidden; }
.rd-workspace main > .flex-1 > div { max-width:none; height:100%; padding:0; }

/* ── Application shell ────────────────────────────────────────────
   Sidebar and top bar are chrome, not content. One flat --bg-1 plane, 1px
   hairline separators, square 4px controls and a 48px bar, so every page
   opens at the Queue Manager's density instead of a stack of translucent
   rounded pills. The tokens carry the colour; only geometry lives here. */
header.sticky { background:var(--bg-1) !important; backdrop-filter:none !important; -webkit-backdrop-filter:none !important; }
.bar-row { min-height:48px; padding-top:.35rem; padding-bottom:.35rem; }

header.sticky .icon-btn { width:28px; height:28px; border-radius:4px; }
header.sticky .icon-btn svg { width:15px; height:15px; }
header.sticky .input-base { height:28px; font-size:12px; }
header.sticky .rounded-xl, header.sticky .rounded-lg { border-radius:4px !important; }

/* ── Sidebar ─────────────────────────────────────────────────────
   The active item is a flush rail, not a floating gradient pill: it runs to
   the panel edge and carries a 3px violet marker, which is what keeps the
   navigation quiet next to the data. */
aside nav .nav-active, aside nav .nav-inactive, aside nav a { border-radius:4px; }
aside nav .nav-active {
  position:relative; width:calc(100% + 12px); margin-left:-12px; padding-left:26px !important;
  color:#f0f0f4; border-color:transparent !important; border-radius:0 4px 4px 0 !important;
  background:var(--bg-2) !important; box-shadow:none !important;
}
aside.nav-collapsed nav .nav-active {
   width:calc(100% + 12px); margin-left:-12px; padding-left:12px !important; padding-right:0 !important;
   justify-content:center;
}
aside nav .nav-active::after {
  content:''; position:absolute; inset:0 auto 0 0; width:3px; border-radius:0 2px 2px 0; background:#6d56c9;
}
html.light aside nav .nav-active { color:#1e1b32; }
.nav-inactive:hover { background:var(--panel-hover); color:var(--text); }
aside nav button, aside nav a { padding-top:7px; padding-bottom:7px; font-size:12.5px; }

/* ── Squared control geometry ────────────────────────────────────
   Radii come down across the board so panels, inputs and buttons agree
   with the tables they sit next to. */
.card { border-radius:8px; backdrop-filter:none; -webkit-backdrop-filter:none; }
.input-base { border-radius:4px; }
.icon-btn { border-radius:4px; }

/* ── Shared workspace shell (Render Jobs, Reports) ────────────────────────────────────────
   Same instrument as the Overview and the Queue Manager: fixed toolbar, one
   dense table on the graphite canvas, a persistent inspector instead of
   per-row accordions. Dark-only, so the planes come from --gr-* directly. */
.ws-page { height:100%; min-height:0; display:flex; flex-direction:column; color:#e3e4e7; background:var(--gr-canvas); font-size:13px; }

/* toolbar */
/* Wraps to a second line between the widest one-row fit and the phone
   layout, rather than pushing search off the right edge. */
.ws-ribbon { margin:8px 8px 0; padding:7px 12px; min-height:52px; display:flex; flex-wrap:wrap; align-items:center; gap:8px 10px; border:1px solid var(--gr-line); border-radius:2px; background:var(--gr-panel); }
.ws-segments { display:flex; align-items:stretch; border:1px solid var(--gr-line); border-radius:3px; overflow:hidden; flex-shrink:0; }
.ws-seg { height:30px; padding:0 12px; display:inline-flex; align-items:center; gap:7px; border-right:1px solid var(--gr-line); color:#a4a7ac; background:var(--gr-input); font-size:12px; white-space:nowrap; }
.ws-seg:last-child { border-right:0; }
.ws-seg:hover { color:#e8e8ed; background:var(--gr-hover); }
.ws-seg.is-active { color:#e8e8ed; background:#382b53; }
.ws-seg i { width:7px; height:7px; border-radius:50%; flex:none; }
.ws-seg b { color:#e8e8ed; font-weight:600; font-variant-numeric:tabular-nums; }
.ws-rule { width:1px; height:24px; background:var(--gr-line); flex:none; }
.ws-spacer { flex:1; }

.ws-field { height:30px; padding:0 9px; display:inline-flex; align-items:center; gap:7px; border:1px solid var(--gr-line); border-radius:3px; background:var(--gr-input); color:#a4a7ac; font-size:12px; white-space:nowrap; flex-shrink:0; }
.ws-field svg { width:14px; height:14px; color:#7b7e84; flex:none; }
.ws-button:hover { color:#e8e8ed; background:var(--gr-hover); }
.ws-button.is-on { border-color:#6b57a8; color:#e8e8ed; }
.ws-button b { min-width:16px; height:15px; padding:0 4px; display:inline-grid; place-items:center; border-radius:8px; background:#382b53; color:#d9d4f5; font-size:10px; font-weight:600; }
.ws-select-wrap { position:relative; display:inline-flex; flex-shrink:0; }
.ws-select { appearance:none; -webkit-appearance:none; padding-right:26px; color:#d0d1d6; outline:none; cursor:pointer; }
.ws-select-wrap svg { position:absolute; right:8px; top:50%; width:13px; height:13px; margin-top:-6.5px; pointer-events:none; color:#7b7e84; }
.ws-select option { background:var(--gr-panel); color:#e3e4e7; }
.ws-square { width:30px; height:30px; flex:none; display:inline-grid; place-items:center; border:1px solid var(--gr-line); border-radius:3px; background:var(--gr-input); color:#a4a7ac; }
.ws-square:hover { color:#e8e8ed; background:var(--gr-hover); }
.ws-square svg { width:14px; height:14px; transition:transform .15s ease; }
.ws-square-sm { width:24px; height:24px; }
.ws-square-sm svg { width:12px; height:12px; }
.ws-search { min-width:150px; flex:1 1 210px; max-width:260px; margin-left:auto; }
.ws-search input { min-width:0; width:100%; border:0; outline:0; background:transparent; color:#d2d3d7; font:inherit; }
.ws-search input::placeholder { color:#5d6065; }
.ws-search input::-webkit-search-cancel-button { filter:invert(.6); }
.ws-count { color:#7b7e84; font-size:11px; font-family:var(--f-ui); font-variant-numeric:tabular-nums; white-space:nowrap; flex-shrink:0; }

/* workspace */
.ws-grid { min-height:0; flex:1; display:grid; grid-template-columns:minmax(0,1fr) 336px; gap:8px; padding:8px; }
.ws-grid.is-solo { grid-template-columns:minmax(0,1fr); }
.ws-pane { min-width:0; min-height:0; overflow:hidden; display:flex; flex-direction:column; border:1px solid var(--gr-line); border-radius:2px; background:var(--gr-panel); }
.ws-pane-head { min-height:44px; padding:0 14px; display:flex; align-items:center; gap:8px; border-bottom:1px solid var(--gr-line); flex-shrink:0; }
.ws-pane-head h2 { margin:0; font-size:13px; font-weight:600; letter-spacing:-.01em; }
.ws-pane-head h2 span { color:#7b7e84; font-size:12px; font-weight:400; }
.ws-hint { color:#5d6065; font-size:10px; white-space:nowrap; }
.ws-link { color:#bbacf0; font-size:11px; white-space:nowrap; }
.ws-link:hover { color:#d4caff; }

/* table */
.ws-table-scroll { min-height:0; flex:1; overflow:auto; }
.ws-table { width:100%; min-width:900px; border-collapse:collapse; table-layout:fixed; }
.ws-table th { height:28px; padding:0 12px; position:sticky; top:0; z-index:1; text-align:left; background:var(--gr-raised); border-bottom:1px solid var(--gr-line); color:#8f9298; font-size:10px !important; font-weight:600; letter-spacing:.07em; text-transform:uppercase; }
.ws-table td { height:40px; padding:0 12px; border-bottom:1px solid #282b2e; color:#d5d6da; font-size:12px; overflow:hidden; }
.ws-row { cursor:pointer; }
.ws-row:hover td { background:var(--gr-hover-soft); }
.ws-row.is-focus td { background:#382b53; }
.ws-row.is-focus .ws-jobname { color:#fff; }
.ws-c-check { width:38px; padding-right:0 !important; }
.ws-c-job { width:28%; }
.ws-c-prog { width:27%; }
.ws-c-worker { width:15%; }
.ws-c-preset { width:11%; }
.ws-c-prio { width:86px; text-align:center; }
.ws-c-act { width:120px; padding-left:0 !important; text-align:right; }

.ws-jobcell { display:flex; align-items:center; gap:9px; min-width:0; }
.ws-dot { width:7px; height:7px; border-radius:50%; flex:none; background:#5d6065; }
.ws-dot.st-success { background:#65ca7c; }
.ws-dot.st-progress { background:#7256df; }
.ws-dot.st-error { background:#e66565; }
.ws-dot.st-cancelled { background:#e4a93e; }
.ws-dot.st-ready, .ws-dot.st-paused, .ws-dot.st-idle { background:#8b8e94; }
.ws-dot.is-live { box-shadow:0 0 6px currentColor; color:#7256df; }
.ws-jobname { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:#e8e8ed; font-weight:500; }

/* A single chip: the two flanks are fixed, so the bar occupies the same
   span on every row. The right flank is sized for a full HH:MM:SS - the
   worker reports either that or a short form like 12m. */
/* Ten blocks and the estimate. The ETA flank is sized in ch, not pixels: a
   pixel width measured in one typeface truncates in a wider one, and the app
   ships four. HH:MM:SS is six tabular digits plus two colons, so 9ch clears
   it in any family - the container carries the 10px so ch resolves against
   the size the estimate is actually set in. */
.ws-progcell { display:grid; grid-template-columns:minmax(60px,1fr) 9ch; align-items:center; gap:9px; font-size:9px; }
.ws-cells { display:flex; gap:2px; --cell:#7256df; --cell-off:#24272b; }
/* Only background-COLOR transitions, and every state paints the lit colour
   with it. background-image is not interpolable, so a cell that carried its
   lit half in a gradient and its full state in a colour went transparent for
   the length of the transition on the way from half to full - the cell blinked
   out and came back. The half state is now the fully lit colour with an opaque
   ::after masking the right half, and the mask fades on opacity: half -> full
   uncovers a colour that never changed, so nothing flashes. --cell-off feeds
   both the unlit background and the mask so the two can never drift apart. */
.ws-cells i { position:relative; flex:1; height:11px; border-radius:1px; background-color:var(--cell-off); transition:background-color .3s ease; }
.ws-cells i.is-on { background-color:var(--cell); }
/* half-lit remainder, so 45% does not read as 40%. The lit colour is on the
   cell itself and the right half is covered by a mask that fades - not by a
   gradient, which cannot transition and made the cell blink. */
.ws-cells i.is-part { background-color:var(--cell); }
.ws-cells i::after { content:''; position:absolute; inset:0 0 0 50%; border-radius:inherit; background:var(--cell-off); opacity:0; transition:opacity .3s ease; pointer-events:none; }
/* Asymmetric on purpose. A transition belongs to the state being entered, so
   this rule governs the mask ARRIVING and the rule above governs it leaving:
   the mask snaps on the instant a cell becomes half-lit - fading it in would
   let the lit colour show through the right half first, reading as a full cell
   that then drops back to half - and fades out over .3s when the cell fills,
   which is the step that should feel smooth. */
.ws-cells i.is-part::after { opacity:1; transition:none; }
.ws-cells.is-good { --cell:#65ca7c; }
.ws-cells.is-bad { --cell:#e66565; }
.ws-cells.is-warn { --cell:#e4a93e; }

/* The inspector keeps a continuous bar - it has the room, and it is the one
   place the exact figure is spelled out. Its own class so the row grid above
   can never squeeze it. */
.ws-prog-inline { display:flex; align-items:center; gap:9px; }
.ws-prog-inline .ws-track { flex:1; }
.ws-eta { text-align:right; color:#8b8e94; font-size:inherit; font-family:var(--f-ui); font-variant-numeric:tabular-nums; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ws-track { min-width:34px; height:5px; overflow:hidden; border-radius:3px; background:#2b2e33; }
.ws-track i { display:block; height:100%; border-radius:inherit; background:#7256df; }
.ws-track i.pbar-success { background:#65ca7c; }
.ws-track i.pbar-error { background:#e66565; }
.ws-track i.pbar-cancelled { background:#e4a93e; }
.ws-pct { text-align:left; color:#d5d6da; font-size:10px; font-family:var(--f-ui); font-variant-numeric:tabular-nums; }
.ws-mono { display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:#a4a7ac; font-size:11px; font-variant-numeric:tabular-nums; }
.ws-prio-ctrl { display:inline-flex; align-items:center; gap:1px; }
.ws-row .ws-prio-ctrl .ws-ico { width:20px; height:22px; }
.ws-prio-ctrl .ws-ico svg { width:11px; height:11px; }
.ws-prio { min-width:20px; color:#a4a7ac; font-size:12px; font-family:var(--f-ui); font-variant-numeric:tabular-nums; }
.ws-prio.is-zero { color:#5d6065; }

/* The inspector describes the job; the row operates on it. Both sets of row
   controls stay hidden until hover, which no touch device provides - so there
   they are always lit, and the inspector's stand-in block steps aside. */
.ws-insp-controls { display:none; }


.ws-rowacts { display:inline-flex; gap:3px; }
.ws-ico { width:24px; height:24px; display:inline-grid; place-items:center; border-radius:3px; color:#6f7278; transition:color .12s ease, background .12s ease; }
.ws-row:hover .ws-ico { color:#9a9da3; }
.ws-ico:hover, .ws-row:hover .ws-ico:hover { color:#e8e8ed; background:rgba(255,255,255,.09); }
.ws-ico.ws-danger:hover { color:#ef7c86; }
.ws-ico:disabled { opacity:.28; cursor:not-allowed; }
.ws-ico:disabled:hover { color:#7b7e84; background:transparent; }
.ws-ico svg { width:14px; height:14px; }

.ws-check { appearance:none; -webkit-appearance:none; width:14px; height:14px; margin:0; vertical-align:middle; border:1px solid #656873; border-radius:2px; background:var(--gr-input); cursor:pointer; }
.ws-check:hover { border-color:#989ba7; }
.ws-check:checked { border-color:#a58bfa; background-color:#a58bfa; background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 8.3 6.4 11.5 13 4.8' fill='none' stroke='%23161520' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); background-position:center; background-repeat:no-repeat; background-size:12px; }

.ws-empty { padding:52px 16px; display:flex; align-items:center; justify-content:center; gap:9px; color:#5d6065; font-size:12px; }
.ws-empty svg { width:18px; height:18px; opacity:.6; }

/* inspector */
.ws-inspector { overflow:auto; }
.ws-insp-inner { display:flex; flex-direction:column; min-height:100%; }
.ws-insp-body { padding:14px; }
.ws-insp-title { margin:0 0 9px; font-size:14px; font-weight:600; letter-spacing:-.01em; word-break:break-all; }
.ws-chiprow { display:flex; flex-wrap:wrap; gap:5px; }
.ws-chip { height:22px; padding:0 8px; display:inline-flex; align-items:center; gap:5px; border:1px solid var(--gr-line); border-radius:3px; background:var(--gr-input); color:#a4a7ac; font:10px var(--f-data); max-width:100%; }
.ws-chip:hover { border-color:var(--gr-line-strong); color:#e8e8ed; }
.ws-chip em { color:#5d6065; font-style:normal; flex:none; }
.ws-chip span { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ws-state-chip { height:22px; padding:0 8px; display:inline-flex; align-items:center; gap:6px; border:1px solid currentColor; border-radius:3px; font-size:11px; font-weight:600; }
.ws-state-chip i { width:6px; height:6px; border-radius:50%; background:currentColor; }
.ws-state-chip.st-success { color:#65ca7c; }
.ws-state-chip.st-progress { color:#7256df; }
.ws-state-chip.st-error { color:#e66565; }
.ws-state-chip.st-cancelled { color:#e4a93e; }
.ws-state-chip.st-ready, .ws-state-chip.st-paused, .ws-state-chip.st-idle { color:#8b8e94; }

.ws-insp-sec { margin-top:14px; padding-top:13px; border-top:1px solid var(--gr-line); }
.ws-insp-sec h4 { margin:0 0 9px; color:#5d6065; font-size:9px; font-weight:600; letter-spacing:.1em; text-transform:uppercase; }
.ws-kv { margin:11px 0 0; display:grid; grid-template-columns:86px minmax(0,1fr); row-gap:7px; column-gap:10px; font-size:11px; }
.ws-kv dt { color:#7b7e84; }
.ws-kv dd { margin:0; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:#d5d6da; font-family:var(--f-data); }
.ws-inline-link { color:#bbacf0; font:inherit; }
.ws-inline-link:hover { color:#d4caff; }

.ws-ctrlrow { display:flex; align-items:center; gap:9px; }
.ws-ctrl-label { color:#7b7e84; font-size:11px; }
.ws-stepper { display:inline-flex; align-items:center; height:28px; overflow:hidden; border:1px solid var(--gr-line); border-radius:3px; background:var(--gr-input); }
.ws-stepper button { width:24px; height:100%; display:grid; place-items:center; color:#7b7e84; }
.ws-stepper button:hover { color:#e8e8ed; background:var(--gr-hover); }
.ws-stepper button:disabled { opacity:.3; cursor:not-allowed; }
.ws-stepper button:disabled:hover { color:#7b7e84; background:transparent; }
.ws-stepper button svg { width:12px; height:12px; }
.ws-stepper span { width:30px; text-align:center; font-size:12px; font-family:var(--f-ui); font-variant-numeric:tabular-nums; }

.ws-btnrow { margin-top:9px; display:flex; flex-wrap:wrap; gap:6px; }
.ws-btn { height:28px; padding:0 11px; display:inline-flex; align-items:center; gap:6px; border:1px solid var(--gr-line); border-radius:3px; background:var(--gr-input); color:#d5d6da; font-size:11px; font-weight:600; white-space:nowrap; }
.ws-btn:hover { background:var(--gr-hover); }
.ws-btn:disabled { opacity:.38; cursor:not-allowed; }
.ws-btn:disabled:hover { background:var(--gr-input); }
.ws-btn svg { width:13px; height:13px; flex:none; }
.ws-btn-danger { color:#e08b93; }
/* Reset sits between the quiet buttons and Delete: it throws away finished
   renders and re-queues the work, which is recoverable but far from free, so it
   carries the same amber the "cancelled" stat card and the stopped-short
   progress bars already use rather than reading as an ordinary action. */
.ws-btn-warn { color:#e4b45c; border-color:color-mix(in srgb, #e4a93e 32%, var(--gr-line)); }
.ws-btn-warn:hover { color:#f0c574; background:color-mix(in srgb, #e4a93e 12%, var(--gr-hover)); }
.ws-btn-warn:disabled:hover { color:#e4b45c; background:var(--gr-input); }
.ws-btn-sm { height:24px; padding:0 9px; font-size:10px; }
.ws-btn-sm svg { width:12px; height:12px; }
/* Split action button: a primary whose label carries its own scope, plus a
   caret holding the wider scopes. The menu opens upward - these live in the
   footer strip, at the bottom of the viewport. */
.ws-split { position:relative; display:inline-flex; }
.ws-split > .ws-btn:first-child { border-top-right-radius:0; border-bottom-right-radius:0; }
.ws-split-caret { padding:0 7px; margin-left:-1px; border-top-left-radius:0; border-bottom-left-radius:0; font-size:9px; }
/* Anchored to the button's LEFT edge, not its right. Both split buttons sit
   near the left of the footer strip, and the footer strip lives inside the main
   scroll region - which sets overflow-y:auto, so overflow-x computes to auto
   too and anything reaching past that container's left edge is clipped. A
   right-anchored menu is wider than the gap to that edge, so it was being cut
   off and the sidebar showed through. Opening rightwards keeps it inside the
   container entirely, which no z-index could have done: the problem was
   clipping, not stacking order. max-width keeps that true on a narrow window. */
.ws-menu { position:absolute; left:0; bottom:calc(100% + 6px); z-index:60; min-width:236px;
  max-width:min(320px, calc(100vw - 24px)); padding:4px;
  display:flex; flex-direction:column; border:1px solid var(--gr-line); border-radius:4px;
  background:var(--gr-panel); box-shadow:0 10px 26px rgba(0,0,0,.45); }
/* For a split button close enough to the right edge that opening rightwards
   would clip instead. Nothing uses it yet; it is here so the next one does not
   rediscover the problem. */
.ws-menu.is-right { left:auto; right:0; }
.ws-menu button { display:flex; align-items:center; gap:8px; width:100%; padding:7px 9px; border-radius:3px;
  color:#d5d6da; font-size:11px; font-weight:500; text-align:left; white-space:nowrap; }
.ws-menu button:hover { background:var(--gr-hover); color:#e8e8ed; }
.ws-menu button.is-danger { color:#e08b93; }
.ws-menu button.is-warn { color:#e4b45c; }
/* The count sits hard right, so every scope states its size before the click */
.ws-menu button b { margin-left:auto; padding-left:12px; color:#8b8e94; font-weight:600; font-variant-numeric:tabular-nums; }
.ws-menu-sep { height:1px; margin:4px 2px; background:var(--gr-line); }
/* Tri-state select-all: the dash has to read as clearly as the tick */
.ws-check:indeterminate { accent-color:#7256df; }

.ws-tags { display:flex; flex-wrap:wrap; gap:5px; }
.ws-tag { height:20px; padding:0 8px; display:inline-flex; align-items:center; border-radius:3px; background:var(--gr-raised); color:#a4a7ac; font-size:10px; }
.ws-none { color:#5d6065; font-size:11px; }

/* Footer strip: retain the compact workspace layout on the shared main panel
   surface, matching the other workspace controls. */
.ws-footbar { margin:0 8px 8px; padding:0 12px; min-height:40px; display:flex; align-items:center; gap:8px; flex-wrap:wrap; border:1px solid var(--gr-line); border-radius:2px; background:var(--gr-panel); color:#7b7e84; font-size:11px; }
.ws-selectall { display:inline-flex; align-items:center; gap:7px; cursor:pointer; white-space:nowrap; color:#d5d6da; }
.ws-foot-meta { white-space:nowrap; }
.ws-footbar b { color:#e8e8ed; font-weight:600; font-variant-numeric:tabular-nums; }
.ws-pager { display:flex; align-items:center; gap:4px; }
.ws-pager button { min-width:24px; height:24px; padding:0 8px; border-radius:3px; color:#a4a7ac; font-size:11px; font-family:var(--f-ui); font-variant-numeric:tabular-nums; }
.ws-pager button:hover { color:#e8e8ed; background:var(--gr-hover); }
.ws-pager button:disabled { opacity:.3; cursor:not-allowed; }
.ws-pager button:disabled:hover { background:transparent; color:#a4a7ac; }
.ws-pager span { padding:0 4px; font-size:11px; font-family:var(--f-ui); font-variant-numeric:tabular-nums; }
.ws-pagination { display:flex; align-items:center; gap:18px; min-height:60px; padding:0 18px; color:#aeb0b4; font-size:11px; font-variant-numeric:tabular-nums; }
.ws-pagination-pages { display:flex; align-items:center; gap:5px; }
.ws-pagination-pages button { min-width:30px; height:30px; padding:0 7px; border-radius:3px; color:#b6b8bc; background:#181b1d; font-size:11px; }
.ws-pagination-pages button:hover { color:#fff; background:var(--gr-hover); }
.ws-pagination-pages button.is-active { color:#fff; background:#4a356d; }
.ws-pagination-pages button:disabled { opacity:.3; cursor:not-allowed; }
.ws-pagination select { width:98px; height:35px; margin-left:auto; padding:0 10px; border:1px solid #3a3d40; border-radius:3px; color:#d4d5d8; background:#151719; font-size:12px; outline:none; }
.ws-pagination select:focus { border-color:#8065cb; }

/* The inspector becomes a stacked panel before it becomes a squeeze, and the
   table keeps its true column widths inside its own horizontal scroll. */
@media (max-width:1100px) {
  .ws-grid { grid-template-columns:minmax(0,1fr); grid-template-rows:minmax(0,1fr) auto; }
  .ws-inspector { max-height:44vh; }
}
@media (max-width:820px) {
  .rd-workspace main > .flex-1 { overflow:auto; }
  .rd-workspace main > .flex-1 > div { height:auto; }
  .ws-page { min-height:100%; }
  .ws-ribbon { padding:9px 10px; flex-wrap:wrap; gap:8px; }
  .ws-segments { width:100%; }
  .ws-seg { flex:1; justify-content:center; padding:0 6px; }
  .ws-seg span { display:none; }
  .ws-rule { display:none; }
  .ws-search { width:100%; margin-left:0; }
  /* The row carries the two things worth scanning on a phone - which shot,
     how far along - and nothing else. Worker, preset, priority and the row
     actions are all in the inspector, which is why the table can drop its
     min-width and stop scrolling sideways. */
  .ws-table { min-width:0; }
  .ws-progcell { grid-template-columns:minmax(0,1fr); }
  .ws-progcell .ws-eta { display:none; }
  .ws-cells i { height:10px; }
  .ws-c-worker, .ws-c-preset, .ws-c-prio, .ws-c-act { display:none; }
  .ws-c-job { width:auto; }
  .ws-c-prog { width:33%; }
  .ws-eta { display:none; }
  .ws-track { min-width:40px; }
  .ws-insp-controls { display:block; }
  .ws-list-pane { min-height:420px; }
  .ws-inspector { max-height:none; min-height:340px; }
  .ws-footbar { padding:8px 10px; }
  .ws-pagination { width:100%; justify-content:flex-end; flex-wrap:wrap; }
}

/* ── Reports workspace ────────────────────────────────────────────
   Rides on the shared .ws-* workspace above; only the columns, the stat
   strip and the bar charts are its own. */
.rp-c-pipe { width:14%; }
.rp-c-worker { width:14%; }
.rp-c-fin { width:19%; }
.rp-c-time { width:12%; }
.rp-c-name { width:30%; }
/* Finished is what you scan a completed-render list by, so it reads at full
   strength; the preset is context and steps back to make room for it. */
.rp-fin { display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:#e8e8ed; font-size:12px; font-variant-numeric:tabular-nums; }
.rp-pipe { display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:#7b7e84; font-size:10.5px; }
.rp-c-act { width:56px; padding-left:0 !important; text-align:right; }

/* Four numbers as one strip sharing borders, not four padded cards. */
.rp-stats { display:grid; grid-template-columns:1fr 1fr; gap:1px; overflow:hidden; border:1px solid var(--gr-line); border-radius:2px; background:var(--gr-line); }
.rp-stat { padding:9px 11px; background:var(--gr-panel); }
.rp-stat b { display:block; font-size:17px; font-weight:600; letter-spacing:-.03em; font-variant-numeric:tabular-nums; }
.rp-stat b.is-good { color:#65ca7c; }
.rp-stat span { display:block; margin-top:1px; color:#7b7e84; font-size:10px; }

/* Labelled bars. Status colour never carries meaning on its own - each row
   names its status and prints its count beside the bar. */
.rp-bars { display:flex; flex-direction:column; gap:9px; }
.rp-bar { display:grid; grid-template-columns:minmax(0,1fr) auto; gap:3px 8px; }
.rp-bar-label { min-width:0; display:flex; align-items:center; gap:6px; color:#a4a7ac; font-size:11px; }
.rp-bar-label span { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.rp-bar-label i { width:7px; height:7px; flex:none; border-radius:2px; }
.rp-bar-val { color:#e8e8ed; font-size:11px; font-family:var(--f-ui); font-variant-numeric:tabular-nums; white-space:nowrap; }
.rp-bar-track { grid-column:1 / -1; height:8px; overflow:hidden; border-radius:2px; background:#24272b; }
.rp-bar-track i { display:block; height:100%; border-radius:2px; transition:filter .12s ease; }
.rp-bar:hover .rp-bar-track i { filter:brightness(1.15); }
.rp-bar:hover .rp-bar-label { color:#e8e8ed; }

@media (max-width:820px) {
  .rp-c-pipe, .rp-c-worker, .rp-c-fin, .rp-c-act { display:none; }
  .rp-c-name { width:auto; }
  .rp-c-time { width:34%; }
}

/* ── Card accents ─────────────────────────────────────────────────
   Each card spends its colour in exactly one place: a 3px rail down the left
   edge, the same marker the active nav item uses. On Workers it is state
   (green = rendering); on Pipelines it is the app's hero gradient, because a
   preset has no state to report. Everything else on the card stays graphite. */
.wk-card, .pl-card { position:relative; padding-left:17px; overflow:hidden; }
.wk-card::before, .pl-card::before { content:''; position:absolute; left:0; top:0; bottom:0; width:3px; }

.wk-card.is-idle::before { background:var(--border-strong); }
.wk-card.is-rendering::before { background:#65ca7c; box-shadow:0 0 14px rgba(101,202,124,.5); }
.wk-card.is-rendering .wk-tile { border-color:color-mix(in srgb,#65ca7c 45%,transparent); color:#65ca7c; background:color-mix(in srgb,#65ca7c 12%,transparent); }
.wk-state { flex:none; display:inline-flex; align-items:center; gap:5px; padding:1px 7px; border-radius:3px; background:var(--bg-2); color:var(--text-dim); font-size:10px; font-weight:600; }
.wk-state i { width:6px; height:6px; border-radius:50%; background:currentColor; }
.wk-card.is-rendering .wk-state { color:#65ca7c; background:color-mix(in srgb,#65ca7c 14%,transparent); }
html.light .wk-card.is-rendering .wk-state { color:#2f7a45; }

/* How much of this worker's assigned work is done - the one thing the two
   raw counts above it cannot show at a glance. */
.wk-load { margin-top:11px; display:flex; align-items:center; gap:9px; }
.wk-load-track { flex:1; height:5px; overflow:hidden; border-radius:3px; background:var(--bg-2); }
.wk-load-track i { display:block; height:100%; border-radius:inherit; background:linear-gradient(90deg,#6366f1,#a855f7); transition:width .25s ease; }
.wk-load-label { flex:none; color:var(--text-dim); font-size:10px; font-family:var(--f-ui); font-variant-numeric:tabular-nums; }

.pl-card::before { background:linear-gradient(180deg,#6366f1 0%,#a855f7 52%,#ec4899 100%); }
.pl-tile { border-color:transparent !important; color:#fff !important; background:linear-gradient(135deg,#6366f1,#a855f7) !important; }
.pl-badges { margin-top:4px; display:flex; flex-wrap:wrap; gap:5px; }
.pl-badge { padding:1px 7px; border:1px solid var(--border); border-radius:3px; color:var(--text-mid); font:10px var(--f-data); }
.pl-badge.is-accent { border-color:color-mix(in srgb,#a855f7 45%,transparent); color:#c4b5fd; background:color-mix(in srgb,#a855f7 13%,transparent); }
html.light .pl-badge.is-accent { color:#6d28d9; }

/* ── Workers page ─────────────────────────────────────────────────── */
.wk-metrics { margin-top:11px; display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:6px; }
.wk-ping { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:12.5px !important; font-family:var(--f-data); font-weight:500 !important; }

/* ── Pipelines page ───────────────────────────────────────────────── */
.pl-info { margin:12px 0 0; padding-top:10px; border-top:1px solid var(--border); color:var(--text-mid); font-size:12px; line-height:1.5; }

/* ── Logs page ────────────────────────────────────────────────────── */
.lg-legend { margin:0 0 10px; color:var(--text-dim); font-size:11px; line-height:1.65; }
.lg-legend b { color:var(--text-mid); font-family:var(--f-data); font-weight:500; }
.lg-table-wrap { overflow:hidden; border:1px solid var(--border); border-radius:4px; background:var(--panel); }
.lg-table { width:100%; border-collapse:collapse; table-layout:fixed; }
.lg-table th { height:28px; padding:0 12px; text-align:left; border-bottom:1px solid var(--border); background:var(--bg-2); color:var(--text-dim); font-size:8px; font-weight:600; letter-spacing:.07em; text-transform:uppercase; }
.lg-table td { height:36px; padding:0 12px; border-bottom:1px solid var(--border); color:var(--text-mid); font-size:11px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.lg-table tr:last-child td { border-bottom:0; }
.lg-table tbody tr:hover td { background:var(--panel-hover); }
.lg-name { max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--text); font-size:11px; text-align:left; }
.lg-name:hover { text-decoration:underline; }
.lg-kind { padding:1px 6px; border-radius:3px; background:var(--bg-2); color:var(--text-mid); font-size:10px; }
.lg-c-kind { width:96px; }
.lg-c-size { width:88px; font-variant-numeric:tabular-nums; }
.lg-c-time { width:150px; }
.lg-c-act { width:52px; padding-left:0 !important; text-align:right; }
@media (max-width:700px) { .lg-c-kind, .lg-c-time { display:none; } }

/* ── Overview operations workspace ────────────────────────────────
   The landing page shares Queue Manager's graphite shell: #0D0F11 belongs
   to navigation/header chrome and #15181A is the working canvas. Hierarchy
   comes from 1px #34373A separators, never a stack of rounded dashboard cards. */
.od-page { height:100%; min-height:0; display:flex; flex-direction:column; color:#e3e4e7; background:var(--gr-canvas); }
/* The ribbon is a toolbar panel like the Queue Manager's batch bar, not a
   full-bleed strip: same inset, border and plane as the panels below it. */
.od-ribbon { min-height:64px; margin:8px 8px 0; padding:0 14px; display:flex; align-items:stretch; border:1px solid var(--gr-line); border-radius:2px; background:var(--gr-panel); }
.od-stat { min-width:126px; padding:9px 18px; display:flex; flex-direction:column; justify-content:center; border-right:1px solid var(--gr-line); }
/* The counters follow the typeface chosen in Settings, not --f-data: for the
   Inter and Red Hat options that token is the OS mono, so pinning the ribbon
   to it meant the one number on the page ignored the setting. tabular-nums
   keeps the digits aligned without giving up the selected face. */
.od-stat:first-child { padding-left:0; }.od-stat b { color:#f2f2f3; font-family:var(--f-ui); font-size:17px; font-weight:600; font-variant-numeric:tabular-nums; letter-spacing:-.03em; }.od-stat b.is-green { color:#65ca7c; }.od-stat b.is-amber { color:#e4a93e; }.od-stat span { margin-top:2px; color:#93969d; font-size:11px; }
/* Fleet-load hero cell: label+percentage, then a thinned reuse of the
   capacity slots from the panel below (same is-rendering/is-idle language),
   then the "N of M" phrasing that panel's own caption already uses. */
.od-load-cell { min-width:220px; padding:9px 22px 9px 0; display:flex; flex-direction:column; justify-content:center; gap:6px; border-right:1px solid var(--gr-line); }
.od-load-top { display:flex; align-items:baseline; gap:9px; }
.od-load-lbl { font-family:var(--f-data); font-size:9.5px; font-weight:700; letter-spacing:.08em; color:#8f9298; text-transform:uppercase; }
.od-load-pct { font-family:var(--f-ui); font-size:18px; font-weight:700; color:#65ca7c; letter-spacing:-.03em; font-variant-numeric:tabular-nums; }
.od-load-caption { color:#93969d; font-size:10.5px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* Fixed 10-segment meter - unlike the capacity-slots strip below (one block
   per worker, identity-based) this is a level gauge: always 10 blocks, lit
   left-to-right by load percentage, so its shape doesn't change as the farm
   grows or shrinks. Only two colors on purpose - more workers rendering is
   a good thing here, not a warning state, so there is no amber/red tier. */
.od-load-meter { display:flex; gap:2.5px; width:100%; max-width:190px; height:14px; }
.od-load-meter span { flex:1; border-radius:1.5px; background:#2b2e33; border:1px solid #43464a; }
.od-load-meter span.is-lit { background:#3f9e57; border-color:#65ca7c; }
.od-stat-dot { width:6px; height:6px; border-radius:50%; display:inline-block; margin-right:5px; vertical-align:1px; }
.od-stat .ws-track { max-width:104px; margin-top:6px; }
.od-ribbon-actions { margin-left:auto; padding-left:14px; display:flex; align-items:center; gap:8px; }.od-button { height:30px; padding:0 13px; border:1px solid var(--gr-line-strong); border-radius:4px; font-size:12px; font-weight:600; white-space:nowrap; }.od-button:disabled { opacity:.42; cursor:not-allowed; }.od-button-muted { color:#d5d6da; background:var(--gr-panel); }.od-button-muted:hover { background:var(--gr-hover); }.od-button-primary { color:#fff; border-color:transparent; background:linear-gradient(135deg,#6366f1 0%,#a855f7 52%,#ec4899 100%); box-shadow:0 10px 26px -12px rgba(168,85,247,.55); }.od-button-primary:hover { filter:brightness(1.08); }
.od-grid { min-height:0; flex:1; display:grid; grid-template-columns:minmax(0,1fr) 330px; grid-template-rows:minmax(0,1fr) minmax(180px, 31%); gap:8px; padding:8px; }.od-panel { min-width:0; min-height:0; overflow:hidden; display:flex; flex-direction:column; border:1px solid var(--gr-line); border-radius:2px; background:var(--gr-panel); }.od-renders-panel { grid-row:span 2; }.od-panel-heading { min-height:48px; padding:0 14px; display:flex; align-items:center; gap:12px; border-bottom:1px solid var(--gr-line); }.od-panel-heading h2 { margin:0; color:#e8e8ea; font-size:13px; font-weight:600; }.od-panel-heading p { margin:4px 0 0; display:flex; align-items:center; gap:5px; color:#91949b; font-size:10px; }.od-live-dot,.od-status-dot,.od-worker-dot,.od-review-dot { display:inline-block; flex:0 0 auto; border-radius:50%; }.od-live-dot,.od-status-dot,.od-worker-dot { width:7px; height:7px; background:#65ca7c; box-shadow:0 0 6px rgba(101,202,124,.48); }.od-text-button { margin-left:auto; color:#bbacf0; font-size:10px; white-space:nowrap; }.od-text-button:hover { color:#d4caff; }
.od-table-scroll { min-height:0; flex:1; overflow:auto; }.od-table { width:100%; min-width:650px; border-collapse:collapse; table-layout:fixed; }.od-table th { height:30px; padding:0 12px; color:#8f9298; border-bottom:1px solid var(--gr-line); background:var(--gr-raised); text-align:left; font-size:8px; font-weight:600; letter-spacing:.07em; text-transform:uppercase; }.od-table th:nth-child(1) { width:32%; }.od-table th:nth-child(2) { width:30%; }.od-table th:nth-child(3) { width:17%; }.od-table th:nth-child(4) { width:10%; }.od-table th:last-child { width:76px; }.od-table td { height:44px; padding:0 12px; color:#d5d6da; border-bottom:1px solid #303337; font-size:11px; }.od-table tr:hover td { background:var(--gr-hover-soft); }.od-job-cell { display:flex; align-items:center; gap:8px; font-weight:500; }/* Same segmented mark as the Jobs table - a running job looks identical
   wherever it appears. */
.od-progress { display:flex; align-items:center; gap:9px; }.od-progress .ws-cells { flex:1; min-width:70px; }.od-pct { flex:none; color:#b4b6bc; font-size:10px; font-variant-numeric:tabular-nums; }.od-data { color:#b4b6bc; font-size:10px; }.od-eta { color:#b4b6bc; font-size:10px; font-variant-numeric:tabular-nums; }.od-actions-cell { padding-right:8px !important; white-space:nowrap; }.od-icon-button { width:27px; height:27px; display:inline-grid; place-items:center; border:1px solid #393c3f; border-radius:3px; color:#aeb0b5; background:#17191b; }.od-icon-button + .od-icon-button { margin-left:4px; }.od-icon-button:hover { color:#f0f0f4; background:var(--gr-hover); }.od-icon-button:disabled { opacity:.36; cursor:not-allowed; }.od-icon-button svg { width:13px; height:13px; }.od-empty { padding:26px 14px; color:#888b92; text-align:center; font-size:11px; }.od-panel-footer { min-height:40px; padding:0 14px; display:flex; align-items:center; gap:8px; border-top:1px solid var(--gr-line); color:#95989e; background:var(--gr-canvas); font-size:10px; }.od-panel-footer b { color:#dddde1; font-weight:600; }.od-panel-footer button { margin-left:auto; color:#bbacf0; }
.od-capacity-meter { padding:12px 14px 8px; border-bottom:1px solid #303337; background:var(--gr-panel); }/* One block per connected worker, wrapping as the farm grows, so a small
   farm reads as a short row rather than a mostly-empty grid of twelve. */
.od-capacity-slots { display:flex; flex-wrap:wrap; gap:5px; }.od-capacity-slots span { width:26px; height:32px; flex:0 0 26px; border:1px solid #43464a; border-radius:2px; background:#2b2e33; }.od-capacity-slots span.is-rendering { border-color:#65ca7c; background:#3f9e57; }.od-capacity-slots span.is-idle { border-color:#43464a; background:#2b2e33; }.od-worker-list,.od-review-list { min-height:0; overflow:auto; padding:5px 12px; }.od-worker-row,.od-review-row { width:100%; min-height:37px; padding:0 5px; display:flex; align-items:center; gap:8px; border-bottom:1px solid #303337; color:#d6d7db; text-align:left; font-size:11px; }.od-worker-row:hover,.od-review-row:hover { background:var(--gr-hover-soft); }.od-worker-name { min-width:0; flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-family:var(--f-data); }.od-worker-meta,.od-review-label { color:#93969d; font-size:10px; white-space:nowrap; }.od-review-dot { width:7px; height:7px; background:#e66565; }.od-review-row .truncate { min-width:0; flex:1; }
@media (max-width:900px) { .od-page { min-height:100%; }.od-ribbon { padding:8px 12px; flex-wrap:wrap; gap:8px; }.od-stat { min-width:112px; padding:4px 12px; }.od-load-cell { min-width:100%; padding:6px 0 10px; border-right:0; border-bottom:1px solid var(--gr-line); }.od-ribbon-actions { margin-left:0; padding-left:0; }.od-grid { grid-template-columns:1fr; grid-template-rows:auto; }.od-renders-panel { grid-row:auto; min-height:390px; }.od-workers-panel,.od-review-panel { min-height:220px; } }
@media (max-width:560px) { .od-ribbon { margin:6px 6px 0; padding:8px 10px; }.od-stat { min-width:calc(50% - 4px); border:0; padding:5px 0; }.od-load-cell { min-width:100%; border:0; padding:6px 0 10px; }.od-ribbon-actions { width:100%; }.od-ribbon-actions .od-button { flex:1; }.od-grid { padding:6px; gap:6px; }.od-panel-heading { padding:0 11px; }.od-table th,.od-table td { padding-left:9px; padding-right:9px; } }
.rd-topbar-collapsed .ml-auto { margin-left:0; gap:0; }
.rd-topbar-collapsed .ml-auto .rd-topbar-toggle { display:grid !important; width:30px; height:30px; }
.rd-output-input { width:100%; height:36px; border-radius:6px; border:1px solid var(--border-strong); padding:0 12px; color:var(--text); background:rgba(0,0,0,.14); font-size:13px; outline:none; }
.rd-output-input:focus { border-color:rgba(99,102,241,.7); box-shadow:0 0 0 2px rgba(99,102,241,.16); }
.rd-batch-actions { grid-column:1/-1; display:flex; justify-content:flex-end; gap:8px; padding:10px 10px 0; margin-top:10px; border-top:1px solid var(--border); }
.rd-batch-actions .rd-nq-button { height:34px; }

/* Full-height Pathmapper workspace. The browser and inspector stay side by
   side so the selected shot identity remains readable while navigating. */
.rd-workspace-mode-switch { display:flex; gap:3px; width:max-content; padding:3px; border:1px solid var(--border); border-radius:10px; background:rgba(0,0,0,.18); }
.rd-workspace-mode-switch button { min-height:32px; padding:0 14px; border-radius:7px; color:var(--text-mid); font-size:12px; font-weight:600; transition:.16s ease; }
.rd-workspace-mode-switch button:hover { color:var(--text); background:var(--panel-hover); }
.rd-workspace-mode-switch button.is-active { color:#fff; background:linear-gradient(135deg,#6366f1,#a855f7); box-shadow:0 7px 18px -10px rgba(168,85,247,.85); }
.rd-pathmapper-page { height:100%; min-height:0; display:flex; flex-direction:column; gap:14px; }
.rd-pathmapper-titlebar,.pm-inspector-heading,.pm-coverage-heading { display:flex; align-items:center; justify-content:space-between; gap:16px; }
.rd-pathmapper-titlebar { min-height:40px; }
.rd-pathmapper-titlebar h1 { font-size:23px; font-weight:700; letter-spacing:-.03em; }
.rd-pathmapper-titlebar p,.pm-inspector-heading p,.pm-coverage-heading p { margin-top:3px; color:var(--text-dim); font-size:12px; }
.rd-pathmapper-page > .pm-mode-switch { flex-shrink:0; }
.pm-inspector-layout { display:grid; grid-template-columns:300px minmax(0,1fr); gap:12px; flex:1; min-height:0; }
.pm-scene-browser,.pm-inspector-panel,.pm-coverage-panel { min-height:0; overflow:hidden; }
.pm-scene-browser { display:flex; flex-direction:column; }
.pm-browser-heading { min-height:62px; padding:0 16px; display:flex; align-items:center; justify-content:space-between; border-bottom:1px solid var(--border); }
.pm-browser-heading h2,.pm-inspector-heading h2,.pm-coverage-heading h2 { font-size:16px; font-weight:700; }
.pm-browser-heading span,.pm-browser-footer { color:var(--text-dim); font-size:11px; }
.pm-small-action { color:#8d91ff; font-size:11px; }
.pm-add-shot-heading { display:inline-flex; align-items:center; gap:5px; }
.pm-add-shot-heading svg { width:14px; height:14px; }
.pm-browser-search,.pm-search-inline { display:flex; align-items:center; gap:8px; }
.pm-browser-search { height:48px; padding:0 13px; border-bottom:1px solid var(--border); }
.pm-browser-search svg,.pm-search-inline svg { width:16px; height:16px; color:var(--text-dim); flex-shrink:0; }
.pm-browser-search input,.pm-search-inline input { min-width:0; width:100%; color:var(--text); background:transparent; outline:0; font-size:12px; }
.pm-browser-search input::placeholder,.pm-search-inline input::placeholder { color:var(--text-faint); }
.pm-browser-list { flex:1; min-height:0; overflow:auto; }
.pm-scene-item { width:100%; min-height:66px; padding:0 13px; display:flex; align-items:center; gap:10px; border-bottom:1px solid var(--border); text-align:left; transition:.14s ease; }
.pm-scene-item:hover { background:var(--panel-hover); }
.pm-scene-item.is-selected { background:linear-gradient(90deg,rgba(99,102,241,.20),rgba(168,85,247,.08)); box-shadow:inset 3px 0 #7775ff; }
.pm-scene-item-copy { display:flex; flex-direction:column; gap:4px; min-width:0; flex:1; }
.pm-scene-item-copy strong { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:13px; }
.pm-scene-item-copy small { color:var(--text-mid); font-weight:400; }
.pm-scene-item-copy small b { font-weight:700; }
.pm-scene-item-copy small,.pm-scene-item-meta small { font-size:11px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pm-scene-item-meta { display:flex; flex-direction:column; align-items:flex-end; gap:2px; }
.pm-scene-item-meta b { color:var(--text); font-size:12px; }
.pm-scene-item > svg { width:14px; height:14px; color:var(--text-dim); flex-shrink:0; }
.pm-browser-footer { min-height:52px; padding:0 13px; display:flex; align-items:center; justify-content:space-between; border-top:1px solid var(--border); }
.pm-add-button { display:inline-flex; align-items:center; gap:5px; color:#8d91ff; font-size:11px; }
.pm-add-button svg { width:14px; height:14px; }
.pm-inspector-panel { display:flex; flex-direction:column; }
.pm-inspector-content { display:flex; flex-direction:column; min-height:100%; }
.pm-inspector-heading,.pm-coverage-heading { min-height:88px; padding:0 20px; border-bottom:1px solid var(--border); }
.pm-eyebrow { display:block; margin-bottom:5px; color:#8d91ff; font-size:10px; font-weight:700; letter-spacing:.09em; text-transform:uppercase; }
.pm-inspector-heading h2,.pm-coverage-heading h2 { font-size:20px; letter-spacing:-.02em; }
.pm-inspector-actions { display:flex; align-items:center; justify-content:flex-end; gap:8px; min-width:0; }
.pm-inspector-search { width:210px; }
.pm-inspector-path { margin:14px 20px 0; padding:9px 11px; border:1px solid var(--border); border-radius:7px; color:var(--text-dim); font:11px var(--f-data); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pm-shot-table-wrap,.pm-coverage-table-wrap { flex:1; min-height:0; overflow:auto; padding:14px 20px 20px; }
.pm-shot-table,.pm-coverage-table { width:100%; border-collapse:collapse; table-layout:fixed; font-size:12px; }
.pm-shot-table th,.pm-coverage-table th { height:34px; color:var(--text-faint); font-size:10px; font-weight:600; letter-spacing:.07em; text-align:left; text-transform:uppercase; }
.pm-shot-table td,.pm-coverage-table td { height:58px; padding:0 10px 0 0; border-top:1px solid var(--border); vertical-align:middle; }
.pm-shot-table th:first-child,.pm-shot-table td:first-child { width:38%; }
.pm-shot-table th:nth-child(2),.pm-shot-table td:nth-child(2) { width:16%; }
.pm-shot-table th:nth-child(3),.pm-shot-table td:nth-child(3) { width:10%; }
.pm-shot-table th:nth-child(4),.pm-shot-table td:nth-child(4) { width:27%; }
.pm-shot-table th:last-child,.pm-shot-table td:last-child { width:9%; }
.pm-shot-table td strong,.pm-shot-table td small { display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }.pm-shot-table td strong { font-size:13px; }.pm-shot-table td small { margin-top:4px; color:var(--text-dim); font-size:10px; }
.pm-path-cell { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pm-map-link { max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:#8d91ff; font-size:11px; text-align:left; }
.pm-map-link:hover { color:#c0c2ff; text-decoration:underline; }
.pm-icon-action { width:25px; height:25px; display:inline-grid; place-items:center; color:var(--text-mid); border-radius:5px; }
.pm-icon-action:hover { color:var(--text); background:var(--panel-hover); }.pm-icon-action.danger:hover { color:#fb7185; }.pm-icon-action svg { width:14px; height:14px; }
.pm-coverage-panel { flex:1; display:flex; flex-direction:column; }
.pm-coverage-heading { min-height:94px; }.pm-search-inline { width:190px; height:34px; padding:0 10px; border:1px solid var(--border); border-radius:7px; background:var(--input-bg); }.pm-coverage-table td:first-child { width:21%; }.pm-coverage-table td:nth-child(2) { width:16%; }.pm-coverage-table td:nth-child(3) { width:12%; }.pm-coverage-table td:nth-child(4) { width:10%; }.pm-coverage-table td:nth-child(5) { width:25%; }.pm-coverage-table td:nth-child(6) { width:9%; }.pm-coverage-table td:last-child { width:7%; }
.pm-coverage-count { color:#61df9a; font-weight:600; }
.pm-coverage-body { display:flex; flex:1; min-height:0; gap:18px; padding:22px; }
.pm-map-inventory { width:52%; min-width:280px; padding:18px; overflow:auto; border:1px solid var(--border); border-radius:8px; background:rgba(0,0,0,.08); }
.pm-map-inventory-item { width:100%; margin-bottom:7px; padding:12px; display:block; border:1px solid transparent; border-radius:7px; text-align:left; color:var(--text); }
.pm-map-inventory-item:hover { background:var(--panel-hover); }.pm-map-inventory-item.is-selected { background:linear-gradient(100deg,rgba(99,102,241,.28),rgba(99,102,241,.10)); border-color:rgba(111,120,255,.75); }
.pm-map-inventory-item strong,.pm-map-inventory-item small,.pm-map-inventory-item span { display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }.pm-map-inventory-item strong { font-size:14px; }.pm-map-inventory-item small { color:var(--text-dim); font:11px var(--f-data); }.pm-map-inventory-meta { display:flex !important; justify-content:space-between; align-items:center; gap:12px; margin-top:7px; font-size:11px; }.pm-map-inventory-meta small { min-width:0; }.pm-map-inventory-meta b { flex-shrink:0; color:var(--text-mid); font-size:11px; font-weight:600; }
.pm-map-detail { flex:1; min-width:0; padding:0; }.pm-map-card { border:1px solid var(--border); border-radius:8px; background:var(--bg-2); padding:18px; }.pm-map-card h3 { margin:0 0 9px; font-size:18px; }.pm-map-path { color:var(--text-dim); font-size:11px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }.pm-map-metrics { display:grid; grid-template-columns:repeat(3,1fr); gap:10px; margin-top:22px; }.pm-map-metrics div { padding:11px 0; border-top:1px solid var(--border); }.pm-map-metrics span,.pm-map-metrics b { display:block; }.pm-map-metrics span { color:var(--text-dim); font-size:11px; }.pm-map-metrics b { margin-top:5px; font-size:18px; }.pm-map-metrics b.is-warning { color:#f6b52e; }.pm-coverage-meter { height:10px; margin:19px 0 14px; overflow:hidden; border-radius:99px; background:rgba(255,255,255,.12); }.pm-coverage-meter i { display:block; height:100%; border-radius:inherit; background:linear-gradient(90deg,#5fe39c,#6974ff); }.pm-map-note { margin:0 0 18px; color:var(--text-dim); font-size:11px; line-height:1.5; }.pm-coverage-footer { min-height:52px; padding:0 18px; display:flex; align-items:center; justify-content:space-between; border-top:1px solid var(--border); color:var(--text-dim); font-size:11px; }
.pm-pie-card { margin-bottom:16px; padding:17px; border:1px solid var(--border); border-radius:8px; background:var(--bg-2); }
.pm-pie-layout { display:flex; align-items:center; gap:20px; margin-top:13px; }
.pm-pie-chart { width:132px; height:132px; flex-shrink:0; border-radius:50%; box-shadow:inset 0 0 0 1px rgba(255,255,255,.10); }
.pm-pie-chart::after { content:''; display:block; width:48px; height:48px; position:relative; top:42px; left:42px; border:1px solid var(--border); border-radius:50%; background:var(--bg-2); }
.pm-pie-legend { flex:1; min-width:0; display:flex; flex-direction:column; gap:9px; }
.pm-pie-legend > div { display:grid; grid-template-columns:10px minmax(0,1fr) auto; align-items:center; gap:8px; font-size:11px; }
.pm-pie-legend i { width:9px; height:9px; border-radius:50%; }.pm-pie-legend span { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--text-mid); }.pm-pie-legend b { font-size:11px; color:var(--text); }
.pm-pie-legend > div.is-selected { padding:5px 7px; margin:-5px -7px; border:1px solid rgba(141,145,255,.48); border-radius:6px; background:rgba(99,102,241,.12); }
.pm-pie-chart.is-selected { box-shadow:0 0 0 3px rgba(141,145,255,.32), inset 0 0 0 1px rgba(255,255,255,.14); }
.pm-map-detail { align-self:flex-start; }
.pm-pie-card { padding:13px; margin-bottom:10px; }
.pm-pie-layout { gap:14px; margin-top:9px; }
.pm-pie-chart { width:104px; height:104px; }
.pm-pie-chart::after { width:38px; height:38px; top:33px; left:33px; }
.pm-map-card { padding:14px; }
.pm-map-metrics { margin-top:13px; }
.pm-map-metrics div { padding:8px 0; }
.pm-coverage-meter { margin:12px 0 10px; }
.pm-map-note { margin-bottom:12px; }
@media (max-width:900px) { .pm-inspector-layout { grid-template-columns:230px minmax(0,1fr); }.pm-inspector-heading,.pm-coverage-heading { padding:0 14px; }.pm-shot-table-wrap,.pm-coverage-table-wrap { padding-left:14px; padding-right:14px; }.pm-inspector-actions { flex-wrap:wrap; }.pm-inspector-search { width:100%; order:3; } }
@media (max-width:680px) { .rd-pathmapper-page { height:auto; }.pm-inspector-layout { grid-template-columns:1fr; }.pm-scene-browser { min-height:300px; max-height:380px; }.pm-inspector-panel,.pm-coverage-panel { min-height:500px; }.rd-pathmapper-titlebar { align-items:flex-start; }.pm-coverage-heading { align-items:flex-start; flex-direction:column; padding-top:16px; padding-bottom:16px; }.pm-search-inline { width:100%; }.pm-coverage-body { flex-direction:column; padding:14px; }.pm-map-inventory { width:100%; min-width:0; max-height:300px; }.pm-map-detail { min-height:360px; }.pm-map-metrics { grid-template-columns:1fr; gap:0; }.pm-pie-chart { width:112px; height:112px; }.pm-pie-chart::after { top:34px; left:34px; } }

/* ── Link-map picker rows ───────────────────────────────────────
   The old row used two competing rings (one for the pick, one for the
   existing link) which read as the same state at a glance. Now the pick owns
   the accent - left bar, tinted fill, check - and the existing link is a
   labelled chip instead of a second outline. */
.map-pick {
  position: relative;
  background: var(--bg-2);
  border: 1px solid var(--border);
  padding-left: 1.4rem;
  transition: border-color .15s ease, background .15s ease, box-shadow .15s ease;
}
.map-pick::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  border-radius: 4px 0 0 4px; background: transparent; transition: background .15s ease;
}
.map-pick:hover { border-color: var(--border-strong); background: var(--panel-hover, var(--bg-2)); }
.map-pick .map-pick-check { opacity: 0; color: #a855f7; transition: opacity .15s ease; }
.map-pick.is-selected {
  border-color: #8b5cf6;
  background: color-mix(in srgb, #8b5cf6 12%, var(--bg-2));
  box-shadow: 0 8px 22px -14px rgba(168, 85, 247, .8);
}
.map-pick.is-selected::before { background: linear-gradient(180deg, #6366f1, #a855f7); }
.map-pick.is-selected .map-pick-check { opacity: 1; }
.map-pick:focus-visible { outline: 2px solid #a855f7; outline-offset: 1px; }
.map-pick-chip {
  font-size: 10px; line-height: 1; letter-spacing: .04em; text-transform: uppercase;
  padding: 3px 6px; border-radius: 999px; color: var(--text-mid);
  border: 1px solid var(--border-strong); background: var(--bg-1);
}

/* ── Sign-in screen ────────────────────────────────────────────────────────
   The front door. Nothing behind it is rendered or fetched until /auth/me
   answers with an account, so this is the whole page rather than a modal over
   a greyed-out app - there is no app underneath to grey out.

   It is deliberately dark-only, like the Queue Manager and the Overview: the
   theme toggle lives inside Settings, which nobody can reach from here, so
   honouring a stored light theme would mean maintaining a second palette for a
   screen that is on for four seconds. */
.rd-login {
  /* Below the modal overlay (z-60) and the toasts (z-80): "Create super user"
     opens a modal from this screen and has to land on top of it. */
  position: fixed; inset: 0; z-index: 50;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  background: var(--gr-canvas);
  overflow-y: auto;
}
/* Two soft brand-coloured pools behind the card. Fixed, blurred, and well
   under the content - the card carries a solid background of its own so the
   form never sits on a moving gradient. */
.rd-login::before,
.rd-login::after {
  content: ""; position: absolute; border-radius: 50%;
  filter: blur(90px); opacity: .5; pointer-events: none;
}
.rd-login::before {
  width: 460px; height: 460px; top: -140px; left: -120px;
  background: radial-gradient(circle, rgba(99,102,241,.55), transparent 70%);
}
.rd-login::after {
  width: 520px; height: 520px; right: -160px; bottom: -180px;
  background: radial-gradient(circle, rgba(168,85,247,.45), transparent 70%);
}
@media (prefers-reduced-motion: no-preference) {
  .rd-login::before { animation: rd-login-drift 18s ease-in-out infinite alternate; }
  .rd-login::after  { animation: rd-login-drift 22s ease-in-out infinite alternate-reverse; }
}
@keyframes rd-login-drift {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(40px, 30px, 0); }
}

.rd-login-card {
  position: relative; z-index: 1;
  width: 100%; max-width: 400px;
  padding: 28px;
  border-radius: 16px;
  background: var(--gr-panel);
  border: 1px solid var(--gr-line);
  box-shadow: 0 40px 80px -40px rgba(0,0,0,.9);
  color: rgba(255,255,255,0.92);
}
.rd-login-brand { display: flex; align-items: center; gap: 12px; margin-bottom: 22px; }
.rd-login-brand img { width: 40px; height: 40px; border-radius: 10px; }
.rd-login-brand h1 { font-size: 17px; font-weight: 700; letter-spacing: -0.01em; line-height: 1.2; }
.rd-login-brand p { font-size: 11px; color: rgba(255,255,255,0.45); }

.rd-login-label {
  display: block; font-size: 11px; font-weight: 500; letter-spacing: .02em;
  color: rgba(255,255,255,0.45); margin-bottom: 6px;
}
.rd-login-input {
  width: 100%; height: 40px; padding: 0 12px;
  border-radius: 8px; font-size: 13px;
  background: var(--gr-input); color: rgba(255,255,255,0.92);
  border: 1px solid var(--gr-line);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.rd-login-input::placeholder { color: rgba(255,255,255,0.28); }
.rd-login-input:focus {
  outline: none; border-color: #6366f1;
  box-shadow: 0 0 0 3px rgba(99,102,241,.22);
}
.rd-login-submit {
  width: 100%; height: 42px; margin-top: 20px;
  border-radius: 8px; font-size: 13px; font-weight: 600;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
}

/* One notice component for all three things this screen has to be able to say:
   no admin exists yet, the licence needs attention, this is a demo. Colour is
   set per instance, so the shapes stay identical and only the accent moves. */
.rd-login-note {
  margin-bottom: 16px; padding: 10px 12px;
  border-radius: 8px; font-size: 11.5px; line-height: 1.5;
  color: rgba(255,255,255,0.72);
}
.rd-login-note strong { color: rgba(255,255,255,0.92); font-weight: 600; }
.rd-login-note button.rd-login-note-action {
  margin-top: 8px; padding: 4px 10px; border-radius: 6px;
  font-size: 11px; font-weight: 600;
}
.rd-login-note button.rd-login-note-action:hover { opacity: .85; }

.rd-login-error {
  margin-top: 14px; padding: 9px 11px; border-radius: 8px;
  font-size: 11.5px; line-height: 1.5; color: #fecdd3;
  background: color-mix(in srgb, #f43f5e 16%, transparent);
  border: 1px solid color-mix(in srgb, #f43f5e 38%, transparent);
}
.rd-login-foot {
  margin-top: 22px; padding-top: 14px;
  border-top: 1px solid var(--gr-line);
  display: flex; align-items: center; justify-content: space-between;
  font-size: 10.5px; color: rgba(255,255,255,0.30);
}

/* Shown for the beat between the page painting and /auth/me answering, so a
   signed-in visitor never sees the login form flash past on the way to the app. */
.rd-boot {
  position: fixed; inset: 0; z-index: 50;
  display: flex; align-items: center; justify-content: center;
  background: var(--gr-canvas);
}
.rd-boot svg { width: 26px; height: 26px; color: rgba(255,255,255,0.35); animation: rd-spin 1s linear infinite; }
@keyframes rd-spin { to { transform: rotate(360deg); } }
