/* ==========================================================================
   RemSup design system
   One accent colour, a neutral ramp, and a 4px spacing scale. Everything
   derives from the tokens below, so rebranding is a single value change.
   ========================================================================== */

:root {
  --accent: #4f7cff;
  --accent-fg: #ffffff;

  --radius-sm: 6px;
  --radius: 10px;
  --radius-lg: 16px;

  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 24px;
  --sp-6: 32px;
  --sp-7: 48px;

  --font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Inter, Roboto,
    "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --shadow-1: 0 1px 2px rgb(0 0 0 / 0.06), 0 1px 3px rgb(0 0 0 / 0.08);
  --shadow-2: 0 4px 12px rgb(0 0 0 / 0.10), 0 2px 4px rgb(0 0 0 / 0.06);
  --shadow-3: 0 24px 48px -12px rgb(0 0 0 / 0.30);

  --ease: cubic-bezier(0.4, 0, 0.2, 1);
}

/* Light ------------------------------------------------------------------ */
:root,
:root[data-theme="light"] {
  /* Tell the browser which scheme to use for anything it draws itself --
     scrollbars, date pickers, the file button. Without this it follows the
     operating system and clashes with the app's own theme. */
  color-scheme: light;
  --bg: #f6f7f9;
  --surface: #ffffff;
  --surface-2: #f1f3f6;
  --surface-3: #e8ebef;
  --border: #e2e5ea;
  --border-strong: #cfd4dc;
  --text: #10131a;
  --text-2: #4a5261;
  --text-3: #7b8494;
  --ok: #14864a;
  --ok-bg: #e6f5ec;
  --warn: #9a6100;
  --warn-bg: #fdf3e2;
  --danger: #c02626;
  --danger-bg: #fdeceb;
  --accent-soft: color-mix(in srgb, var(--accent) 10%, transparent);
}

/* Dark ------------------------------------------------------------------- */
@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;
    --bg: #0c0e13;
    --surface: #14171e;
    --surface-2: #1a1e27;
    --surface-3: #232833;
    --border: #262b36;
    --border-strong: #363d4b;
    --text: #eef1f6;
    --text-2: #a7b0c0;
    --text-3: #6f7889;
    --ok: #45d483;
    --ok-bg: #10281c;
    --warn: #e8b357;
    --warn-bg: #2a2114;
    --danger: #ff6b6b;
    --danger-bg: #2c1618;
    --shadow-3: 0 24px 48px -12px rgb(0 0 0 / 0.65);
  }
}
/* An explicit choice must beat the OS preference in both directions. */
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0c0e13;
  --surface: #14171e;
  --surface-2: #1a1e27;
  --surface-3: #232833;
  --border: #262b36;
  --border-strong: #363d4b;
  --text: #eef1f6;
  --text-2: #a7b0c0;
  --text-3: #6f7889;
  --ok: #45d483;
  --ok-bg: #10281c;
  --warn: #e8b357;
  --warn-bg: #2a2114;
  --danger: #ff6b6b;
  --danger-bg: #2c1618;
  --shadow-3: 0 24px 48px -12px rgb(0 0 0 / 0.65);
}

/* Reset ------------------------------------------------------------------ */
*,
*::before,
*::after { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.5;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 { margin: 0; font-weight: 650; letter-spacing: -0.011em; }
p { margin: 0; }
button, input, select, textarea { font: inherit; color: inherit; }
svg.ico {
  width: 16px; height: 16px;
  fill: none; stroke: currentColor;
  stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round;
  flex: none;
}

[hidden] { display: none !important; }

::selection { background: color-mix(in srgb, var(--accent) 30%, transparent); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* Boot ------------------------------------------------------------------- */
.boot {
  position: fixed; inset: 0;
  display: grid; place-items: center;
  background: var(--bg);
}
.spinner {
  width: 28px; height: 28px;
  border: 2.5px solid var(--border-strong);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* Login ------------------------------------------------------------------ */
.login {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: var(--sp-5);
  background:
    radial-gradient(1200px 600px at 50% -10%, var(--accent-soft), transparent 70%),
    var(--bg);
}
.login-card {
  width: min(100%, 400px);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--sp-6);
  box-shadow: var(--shadow-3);
  display: grid;
  gap: var(--sp-4);
  animation: rise 0.35s var(--ease) both;
}
@keyframes rise {
  from { opacity: 0; transform: translateY(10px); }
}
.login-brand {
  display: grid;
  gap: var(--sp-3);
  justify-items: center;
  text-align: center;
  margin-bottom: var(--sp-2);
}
.login-title { font-size: 20px; }
.login-sub { color: var(--text-2); font-size: 13.5px; }
.login-foot {
  text-align: center;
  color: var(--text-3);
  font-size: 12px;
  margin-top: var(--sp-1);
}

.brand-mark {
  width: 44px; height: 44px;
  border-radius: 12px;
  background: linear-gradient(140deg, var(--accent), color-mix(in srgb, var(--accent) 55%, #000));
  color: var(--accent-fg);
  display: grid; place-items: center;
  font-weight: 700; font-size: 17px;
  letter-spacing: -0.02em;
  box-shadow: var(--shadow-1);
  overflow: hidden;
  flex: none;
}
.brand-mark img { width: 100%; height: 100%; object-fit: contain; }

/* Fields ----------------------------------------------------------------- */
.field { display: grid; gap: 6px; }
.field-label {
  font-size: 12.5px;
  font-weight: 550;
  color: var(--text-2);
}
.field-hint { font-size: 12px; color: var(--text-3); }

/* Match every text-like field, however it is declared.
   Enumerating input[type=...] silently missed every <input> written without a
   type attribute -- and an unstyled input follows the operating system's
   colour scheme, not the page's, which is why some fields rendered dark on the
   light theme and light on the dark one. */
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="range"]):not([type="submit"]):not([type="button"]),
select,
textarea {
  width: 100%;
  padding: 9px 11px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease), background 0.15s var(--ease);
}
input:not([type="checkbox"]):not([type="radio"]):hover,
select:hover, textarea:hover { border-color: var(--border-strong); }
input:not([type="checkbox"]):not([type="radio"]):focus,
select:focus, textarea:focus {
  outline: none;
  background: var(--surface);
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
textarea { resize: vertical; min-height: 72px; }
input[type="color"] { padding: 4px; height: 38px; cursor: pointer; }

/* Dropdowns.
   The open list is drawn by the operating system, not the page, so it cannot
   be styled the way the rest of the app is. Setting the colours on the options
   themselves is what most platforms honour, and color-scheme (declared on
   :root) is what tells macOS to draw a dark menu rather than a white one. */
select {
  appearance: none;
  -webkit-appearance: none;
  /* Room for the chevron drawn below. */
  padding-right: 32px;
  background-image:
    linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position:
    calc(100% - 17px) calc(50% + 1px),
    calc(100% - 12px) calc(50% + 1px);
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  cursor: pointer;
}
select option {
  background-color: var(--surface);
  color: var(--text);
}
select option:disabled { color: var(--text-3); }

/* Chrome paints its own background on fields it considers autofillable -- and
   it picks that colour from the OS theme, not the page. The result was a dark
   field on the light theme and a light field on the dark one, but only on
   Username / Full name / Customer name, which is what made it look random.
   The background cannot be overridden directly; an inset shadow the full size
   of the field is the only thing that covers it. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active,
textarea:-webkit-autofill,
select:-webkit-autofill {
  -webkit-text-fill-color: var(--text) !important;
  -webkit-box-shadow: 0 0 0 100px var(--surface-2) inset !important;
  box-shadow: 0 0 0 100px var(--surface-2) inset !important;
  caret-color: var(--text);
  border-color: var(--border);
  /* Chrome animates its background in; an absurd delay stops it appearing. */
  transition: background-color 600000s 0s, color 600000s 0s;
}
input:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 100px var(--surface) inset, 0 0 0 3px var(--accent-soft) !important;
  box-shadow: 0 0 0 100px var(--surface) inset, 0 0 0 3px var(--accent-soft) !important;
  border-color: var(--accent);
}

/* File picker and checkboxes follow the theme rather than the browser default. */
input[type="file"] { padding: 7px 9px; font-size: 13px; }
input[type="file"]::file-selector-button {
  margin-right: 10px;
  padding: 5px 11px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: 12.5px;
  font-weight: 550;
  cursor: pointer;
}
input[type="file"]::file-selector-button:hover { background: var(--surface-3); }
input[type="checkbox"] { accent-color: var(--accent); }

.form-error {
  background: var(--danger-bg);
  color: var(--danger);
  border: 1px solid color-mix(in srgb, var(--danger) 25%, transparent);
  padding: 9px 11px;
  border-radius: var(--radius);
  font-size: 13px;
}

/* Buttons ---------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 8px 14px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font-weight: 550;
  font-size: 13.5px;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.15s var(--ease), border-color 0.15s var(--ease), transform 0.06s var(--ease);
}
.btn:hover { background: var(--surface-2); border-color: var(--border-strong); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: 0.55; cursor: not-allowed; }

.btn-primary {
  background: var(--accent);
  border-color: transparent;
  color: var(--accent-fg);
}
.btn-primary:hover { background: color-mix(in srgb, var(--accent) 88%, #000); border-color: transparent; }

.btn-danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 30%, transparent); }
.btn-danger:hover { background: var(--danger-bg); }

.btn-ghost { background: transparent; border-color: transparent; color: var(--text-2); }
.btn-ghost:hover { background: var(--surface-2); color: var(--text); }

.btn-block { width: 100%; padding: 10px; }
.btn-sm { padding: 5px 10px; font-size: 12.5px; }

.icon-btn {
  display: grid; place-items: center;
  width: 34px; height: 34px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  background: transparent;
  color: var(--text-2);
  cursor: pointer;
  transition: background 0.15s var(--ease), color 0.15s var(--ease);
}
.icon-btn:hover { background: var(--surface-2); color: var(--text); }

/* App shell -------------------------------------------------------------- */
.app { min-height: 100dvh; display: flex; flex-direction: column; }

.topbar {
  position: sticky; top: 0; z-index: 20;
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  padding: var(--sp-3) var(--sp-5);
  background: color-mix(in srgb, var(--surface) 85%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--border);
}
.topbar-brand { display: flex; align-items: center; gap: var(--sp-3); flex: none; }
.topbar-brand .brand-mark { width: 34px; height: 34px; border-radius: 9px; font-size: 14px; }
.brand-text { display: grid; line-height: 1.25; }
.brand-text strong { font-size: 14px; letter-spacing: -0.01em; }
.brand-text span { font-size: 11.5px; color: var(--text-3); }

.tabs {
  display: flex;
  gap: 2px;
  padding: 3px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 12px;
}
.tab {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 14px;
  border: none;
  background: transparent;
  color: var(--text-2);
  border-radius: 9px;
  font-weight: 550;
  font-size: 13.5px;
  cursor: pointer;
  transition: background 0.18s var(--ease), color 0.18s var(--ease);
}
.tab:hover { color: var(--text); }
.tab[aria-selected="true"] {
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-1);
}
.tab[aria-selected="true"] .ico { color: var(--accent); }

.topbar-right { margin-left: auto; display: flex; align-items: center; gap: var(--sp-2); }

.user-chip { display: flex; align-items: center; gap: var(--sp-2); padding-left: var(--sp-2); }
.avatar {
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--accent); color: var(--accent-fg);
  display: grid; place-items: center;
  font-weight: 650; font-size: 12.5px;
  text-transform: uppercase;
}
.user-meta { display: grid; line-height: 1.25; }
.user-meta strong { font-size: 13px; }
.user-meta span { font-size: 11px; color: var(--text-3); }

/* Stat bar --------------------------------------------------------------- */
.statbar {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--sp-3);
  padding: var(--sp-5) var(--sp-5) 0;
}
.stat {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--sp-4);
  display: grid;
  gap: 2px;
}
.stat-value { font-size: 24px; font-weight: 660; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.stat-label { font-size: 12px; color: var(--text-3); }
.stat-value .dim { color: var(--text-3); font-weight: 500; font-size: 16px; }

/* Content ---------------------------------------------------------------- */
.content { padding: var(--sp-5); flex: 1; }
.panel { animation: fade 0.22s var(--ease) both; }
@keyframes fade { from { opacity: 0; transform: translateY(4px); } }

.panel-head {
  display: flex;
  align-items: flex-end;
  gap: var(--sp-4);
  margin-bottom: var(--sp-4);
  flex-wrap: wrap;
}
.panel-head h2 { font-size: 17px; }
.panel-head p { color: var(--text-3); font-size: 13px; margin-top: 2px; }
.panel-head .spacer { margin-left: auto; }

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.card + .card { margin-top: var(--sp-4); }
.card-head {
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: var(--sp-3);
}
.card-head h3 { font-size: 14px; }
.card-head p { font-size: 12.5px; color: var(--text-3); }
.card-body { padding: var(--sp-5); }

/* Tables ----------------------------------------------------------------- */
.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; }
th {
  text-align: left;
  font-size: 11.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-3);
  padding: var(--sp-3) var(--sp-5);
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
td {
  padding: var(--sp-3) var(--sp-5);
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
tbody tr:last-child td { border-bottom: none; }
tbody tr { transition: background 0.12s var(--ease); }
tbody tr:hover { background: var(--surface-2); }
td.actions { text-align: right; white-space: nowrap; }
td.actions .btn + .btn { margin-left: var(--sp-2); }

.cell-primary { display: flex; align-items: center; gap: var(--sp-3); }
.cell-primary strong { font-weight: 600; }
.cell-sub { font-size: 12px; color: var(--text-3); }

/* Pills ------------------------------------------------------------------ */
.pill {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2.5px 9px;
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 550;
  background: var(--surface-3);
  color: var(--text-2);
  white-space: nowrap;
}
.pill-accent { background: var(--accent-soft); color: var(--accent); }
.pill-ok { background: var(--ok-bg); color: var(--ok); }
.pill-warn { background: var(--warn-bg); color: var(--warn); }
.pill-danger { background: var(--danger-bg); color: var(--danger); }
.pill-row { display: flex; flex-wrap: wrap; gap: 5px; }

.dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none; }

/* Empty state ------------------------------------------------------------ */
.empty {
  padding: var(--sp-7) var(--sp-5);
  text-align: center;
  color: var(--text-3);
  display: grid;
  gap: var(--sp-2);
  justify-items: center;
}
.empty strong { color: var(--text-2); font-size: 14px; font-weight: 600; }
.empty p { font-size: 13px; max-width: 42ch; }

/* Modal ------------------------------------------------------------------ */
.modal-backdrop {
  position: fixed; inset: 0; z-index: 100;
  background: rgb(0 0 0 / 0.45);
  backdrop-filter: blur(3px);
  display: grid;
  place-items: center;
  padding: var(--sp-5);
  animation: fade 0.16s var(--ease) both;
}
.modal {
  width: min(100%, 520px);
  max-height: 88dvh;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-3);
  animation: rise 0.22s var(--ease) both;
}
.modal-head {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--border);
}
.modal-head h2 { font-size: 15px; flex: 1; }
.modal-body { padding: var(--sp-5); overflow-y: auto; display: grid; gap: var(--sp-4); }
.modal-foot {
  padding: var(--sp-4) var(--sp-5);
  border-top: 1px solid var(--border);
  display: flex; justify-content: flex-end; gap: var(--sp-2);
}

/* Checkbox grid ---------------------------------------------------------- */
.check-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: var(--sp-2);
}
.check {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-2);
  cursor: pointer;
  font-size: 13px;
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease);
}
.check:hover { border-color: var(--border-strong); }
.check:has(input:checked) {
  border-color: var(--accent);
  background: var(--accent-soft);
}
.check input { accent-color: var(--accent); width: 15px; height: 15px; flex: none; }

/* Themed dropdown ----------------------------------------------------------
   Replaces <select> where the open menu has to match the app. A native select
   popup is drawn by the operating system and cannot be styled; this one is
   ours end to end. */
.dd { position: relative; }

.dd-toggle {
  width: 100%;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 9px 11px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease), background 0.15s var(--ease);
}
.dd-toggle:hover { border-color: var(--border-strong); }
.dd.is-open .dd-toggle,
.dd-toggle:focus-visible {
  outline: none;
  background: var(--surface);
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.dd-value { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dd-value.is-empty { color: var(--text-3); }
.dd-chev {
  width: 15px; height: 15px; flex: none;
  fill: none; stroke: var(--text-3);
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
  transition: transform 0.18s var(--ease);
}
.dd.is-open .dd-chev { transform: rotate(180deg); stroke: var(--accent); }

.dd-menu {
  position: fixed;
  z-index: 400;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-3);
  animation: dd-in 0.14s var(--ease) both;
}
@keyframes dd-in { from { opacity: 0; transform: translateY(-4px); } }

.dd-search { padding: 8px; border-bottom: 1px solid var(--border); flex: none; }
.dd-search input { padding: 7px 10px; font-size: 13px; }

.dd-list { overflow-y: auto; padding: 5px; }

.dd-option {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 8px 9px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  min-width: 0;
}
.dd-option:hover,
.dd-option.is-active { background: var(--surface-3); }
.dd-option.is-selected { background: var(--accent-soft); }
.dd-option.is-selected .dd-label { color: var(--accent); font-weight: 600; }

.dd-text { display: grid; gap: 1px; min-width: 0; flex: 1; }
.dd-label { font-size: 13.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dd-meta {
  font-size: 11.5px; color: var(--text-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dd-tag {
  font-size: 11px;
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--surface-3);
  color: var(--text-3);
  white-space: nowrap;
  flex: none;
}
.dd-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; background: var(--text-3); }
.dd-dot.on { background: var(--ok); }

.dd-empty { padding: 14px; text-align: center; color: var(--text-3); font-size: 12.5px; }

/* Copy field ------------------------------------------------------------- */
.copy-field { display: flex; gap: var(--sp-2); align-items: stretch; }
.copy-field code {
  flex: 1;
  font-family: var(--mono);
  font-size: 11.5px;
  padding: 9px 11px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  word-break: break-all;
  max-height: 110px;
  overflow-y: auto;
  line-height: 1.45;
}

/* Housekeeping notice ------------------------------------------------------ */
.notice {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  margin-bottom: var(--sp-4);
  background: var(--warn-bg);
  border: 1px solid color-mix(in srgb, var(--warn) 30%, transparent);
  border-radius: var(--radius);
  font-size: 13.5px;
}
.notice > div { flex: 1; min-width: 0; }
.notice strong { color: var(--warn); }
.notice .cell-sub { margin-top: 2px; }

/* Compact list rows --------------------------------------------------------
   Dense rather than card-like: several facts per row without the row becoming
   tall. The primary cell stacks name over its supporting detail; every other
   cell stays on one line. */
.table-compact th { padding: 9px var(--sp-4); font-size: 11px; }
.table-compact td { padding: 9px var(--sp-4); vertical-align: top; }
.table-compact td.actions { vertical-align: middle; }

.cell-stack { display: grid; gap: 1px; min-width: 0; }
.cell-stack .lead { font-weight: 600; font-size: 13.5px; line-height: 1.35; }
.cell-stack .meta {
  font-size: 11.5px;
  color: var(--text-3);
  line-height: 1.4;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 34ch;              /* keeps a long note out of the next column */
}
.cell-stack .meta.wrap { white-space: normal; }

.status-dot {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  font-weight: 550;
  white-space: nowrap;
}
.status-dot i {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--text-3);
  flex: none;
  position: relative;
}
.status-dot.on { color: var(--ok); }
.status-dot.on i { background: var(--ok); }
.status-dot.on i::after {
  content: '';
  position: absolute; inset: -3px;
  border-radius: 50%;
  border: 1.5px solid var(--ok);
  opacity: 0.4;
  animation: ping 2s var(--ease) infinite;
}
.status-dot.off { color: var(--text-3); }
@keyframes ping {
  0% { transform: scale(0.7); opacity: 0.5; }
  100% { transform: scale(1.3); opacity: 0; }
}

/* Expanded sub-row (the customers a technician can reach) */
.sub-row td { background: var(--surface-2); padding-top: 0; }
.sub-row:hover td { background: var(--surface-2); }
.sub-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 4px 0 10px;
}
.chev {
  color: var(--text-3);
  font-size: 10px;
  width: 11px;
  flex: none;
  transition: color 0.15s var(--ease), transform 0.15s var(--ease);
}
.expandable { cursor: pointer; }
.expandable:hover .chev { color: var(--accent); }
.expandable.open .chev { transform: rotate(90deg); color: var(--accent); }

.empty-inline {
  padding: var(--sp-3) var(--sp-4);
  text-align: center;
  color: var(--text-3);
  font-size: 12.5px;
}

/* Big install code -------------------------------------------------------- */
.bigcode {
  font-size: 34px;
  font-weight: 680;
  letter-spacing: 0.1em;
  font-family: var(--mono);
  text-align: center;
  padding: 20px;
  border-radius: var(--radius);
  background: var(--accent-soft);
  color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
  cursor: pointer;
  user-select: all;
  transition: background 0.15s var(--ease);
}
.bigcode:hover { background: color-mix(in srgb, var(--accent) 16%, transparent); }
/* While the code is being reserved: hold the same footprint so the dialog does
   not jump when the value arrives. */
.bigcode.is-loading {
  color: var(--text-3);
  cursor: default;
  animation: pulse-soft 1.3s ease-in-out infinite;
}
@keyframes pulse-soft { 50% { opacity: 0.5; } }
#m-codeblock { display: grid; gap: var(--sp-3); margin-bottom: var(--sp-2); }

/* Embedded remote desktop viewer ------------------------------------------ */
.viewer {
  position: fixed;
  inset: 0;
  z-index: 150;
  display: flex;
  flex-direction: column;
  background: #0a0c10;           /* always dark: a bright frame around a remote
                                    screen is fatiguing and distorts colour */
  animation: fade 0.18s var(--ease) both;
}

/* Floating control bar.
   Small and centred at the top, and fully opaque -- a translucent bar over a
   bright remote desktop (a Windows taskbar, a white document) blended into the
   background and became unreadable. It hides itself when the pointer is idle
   and slides back the moment the mouse moves. */
.viewer-bar {
  position: absolute;
  top: 16px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 4;

  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 9px;
  max-width: min(94vw, 900px);

  border-radius: 14px;
  border: 1px solid rgb(255 255 255 / 0.09);
  background: #171a21;                      /* solid: always readable */
  box-shadow: 0 12px 36px rgb(0 0 0 / 0.55), inset 0 1px 0 rgb(255 255 255 / 0.05);
  color: #eef1f6;

  opacity: 1;
  /* Slow, soft easing. The bar sits over someone's live desktop, so it should
     drift rather than snap -- a fast linear slide reads as a glitch.
     Appearing is quicker than disappearing: when you reach for the controls
     you want them now, but going away should be unobtrusive. */
  will-change: transform, opacity;
  transition:
    opacity 0.35s cubic-bezier(0.22, 0.61, 0.36, 1),
    transform 0.42s cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* Auto-hide: eases up out of the way. pointer-events off so a hidden bar can
   never swallow a click meant for the remote screen. */
.viewer-bar.is-hidden {
  opacity: 0;
  transform: translateX(-50%) translateY(calc(-100% - 26px));
  pointer-events: none;
  transition:
    opacity 0.5s cubic-bezier(0.4, 0, 0.2, 1),
    transform 0.55s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Anything wrong, or the user reaching for the bar, keeps it on screen. */
.viewer-bar:hover,
.viewer-bar:focus-within,
.viewer.is-bad .viewer-bar {
  opacity: 1;
  transform: translateX(-50%);
  pointer-events: auto;
}

.viewer-name {
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 22ch;
  padding-right: 2px;
}
.viewer-sep {
  width: 1px;
  align-self: stretch;
  margin: 2px 4px;
  background: rgb(255 255 255 / 0.12);
}
.vico {
  width: 14px; height: 14px;
  fill: none; stroke: currentColor;
  stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round;
  flex: none;
}

.viewer-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: #e8b357;
  flex: none;
  animation: blink 1.2s ease-in-out infinite;
}
.viewer-dot.ok { background: #45d483; animation: none; }
.viewer-dot.bad { background: #ff6b6b; animation: none; }
@keyframes blink { 50% { opacity: 0.35; } }

.viewer-btn, .viewer-select {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 11px;
  border-radius: 9px;
  border: 1px solid transparent;
  background: rgb(255 255 255 / 0.07);
  color: #dde2ea;
  font: inherit;
  font-size: 12.5px;
  font-weight: 550;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.14s var(--ease), color 0.14s var(--ease);
}
.viewer-btn:hover, .viewer-select:hover { background: rgb(255 255 255 / 0.16); color: #fff; }
.viewer-btn:active { transform: translateY(1px); }
.viewer-btn.active { background: var(--accent); color: #fff; }
.viewer-btn.danger { color: #ff9c9c; }
.viewer-btn.danger:hover { background: rgb(220 60 60 / 0.28); color: #fff; }
.viewer-select { padding-right: 8px; }

.viewer-stage {
  flex: 1;
  position: relative;
  display: grid;
  place-items: center;
  overflow: auto;
  padding: var(--sp-3);
  background:
    repeating-conic-gradient(#101319 0% 25%, #0c0f14 0% 50%) 50% / 22px 22px;
}
.viewer-canvas {
  display: block;
  background: #000;
  box-shadow: 0 8px 40px rgb(0 0 0 / 0.6);
  border-radius: 3px;
  /* Smooth, not pixelated: the canvas is scaled by arbitrary fractions to fit
     the stage, and nearest-neighbour at those ratios looks far worse than
     bilinear -- especially on text. */
  image-rendering: auto;
  /* The module sets an inline cursor of its own once connected; the remote
     pointer is painted into the frame, so the local one stays a plain arrow. */
  cursor: default;
}

.viewer-overlay {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  align-content: center;
  gap: var(--sp-4);
  background: rgb(10 12 16 / 0.86);
  backdrop-filter: blur(2px);
  color: #a7b0c0;
  font-size: 14px;
  text-align: center;
  padding: var(--sp-5);
  z-index: 2;
}
.viewer-spinner {
  width: 30px; height: 30px;
  border: 2.5px solid #2a3140;
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}

.viewer.is-full .viewer-stage { padding: 0; }
.viewer.is-full .viewer-bar { top: 22px; }

@media (max-width: 720px) {
  .viewer-bar { top: 10px; gap: 4px; padding: 6px 7px; }
  .viewer-btn, .viewer-select { font-size: 11.5px; padding: 5px 8px; }
  .viewer-name { max-width: 12ch; }
  .viewer-btn .vico { display: none; }
}

/* Toasts ----------------------------------------------------------------- */
.toasts {
  position: fixed; z-index: 200;
  bottom: var(--sp-5); right: var(--sp-5);
  display: grid; gap: var(--sp-2);
  pointer-events: none;
}
.toast {
  pointer-events: auto;
  padding: 10px 14px;
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-2);
  font-size: 13px;
  display: flex; align-items: center; gap: var(--sp-2);
  animation: rise 0.22s var(--ease) both;
  max-width: 360px;
}
.toast-ok { border-left: 3px solid var(--ok); }
.toast-err { border-left: 3px solid var(--danger); }

/* Designer preview ------------------------------------------------------- */
.designer-grid {
  display: grid;
  grid-template-columns: minmax(300px, 1fr) minmax(280px, 380px);
  gap: var(--sp-4);
  align-items: start;
}
.preview {
  position: sticky;
  top: 84px;
}
.preview-frame {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface-2);
}
.preview-chrome {
  display: flex; align-items: center; gap: 6px;
  padding: 8px 11px;
  background: var(--surface-3);
  border-bottom: 1px solid var(--border);
}
.preview-chrome i { width: 9px; height: 9px; border-radius: 50%; background: var(--border-strong); }
.preview-chrome span {
  margin-left: var(--sp-2);
  font-size: 11px; color: var(--text-3);
  font-family: var(--mono);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.preview-body { padding: var(--sp-5); display: grid; gap: var(--sp-3); justify-items: center; text-align: center; }
.preview-body h4 { font-size: 15px; }
.preview-body p { font-size: 12.5px; color: var(--text-2); }

/* Responsive ------------------------------------------------------------- */
@media (max-width: 1000px) {
  .designer-grid { grid-template-columns: 1fr; }
  .preview { position: static; }
}
@media (max-width: 820px) {
  .topbar { flex-wrap: wrap; gap: var(--sp-3); padding: var(--sp-3) var(--sp-4); }
  .tabs { order: 3; width: 100%; }
  .tab { flex: 1; justify-content: center; }
  .topbar-right { margin-left: auto; }
  .user-meta { display: none; }
  .content, .statbar { padding-left: var(--sp-4); padding-right: var(--sp-4); }
  th, td { padding-left: var(--sp-4); padding-right: var(--sp-4); }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}
