/* ============================================================================
   Help Desk Horizon — "Calm Signal"
   Dark-first, one confident accent, generous spacing. Help desk work is
   long-session work, so the theme is tuned for low fatigue rather than impact.

   Tenant branding overrides only --sp-accent* via an inline nonce'd <style>
   block in the layout. Every other token is fixed, which is why tenant
   branding cannot break the interface.

   Three theme states, in order of precedence:
     1. :root[data-theme="light"|"dark"] — an explicit choice from the toggle,
        rendered server-side from the theme cookie so the first paint is right.
     2. prefers-color-scheme: light    — the OS preference. This is what
        data-theme="system" resolves to: that value matches no rule here, by
        design, so choosing "system" is the absence of an assertion.
     3. :root                          — dark, the default.
   Because every component reads tokens rather than literal colours, a theme is
   a variable swap and nothing below this block is theme-aware.
   ============================================================================ */

:root {
  color-scheme: dark light;

  /* Accent — the only tenant-overridable family. */
  --sp-accent: #4c9aff;
  --sp-accent-hover: #6fb0ff;
  --sp-accent-text: #4c9aff;

  /* Surfaces. Elevation comes from surface colour, not shadow, which keeps
     dark mode clean. */
  --sp-bg: #0e1116;
  --sp-surface: #171b22;
  --sp-surface-raised: #1f242d;
  --sp-surface-hover: #232935;
  --sp-border: #2a313c;
  --sp-border-strong: #3a4250;

  --sp-text: #e8ecf2;
  --sp-text-muted: #9aa5b4;
  --sp-text-faint: #6b7684;

  /* Status colours carry meaning, so they are never tenant-overridable.
     Status is also never communicated by colour alone — every pill has a
     text label. */
  --sp-new: #a78bfa;
  --sp-open: #4c9aff;
  --sp-waiting: #f0a73a;
  --sp-resolved: #3dbe7c;
  --sp-breach: #ff6b61;

  --sp-radius-sm: 6px;
  --sp-radius: 10px;
  --sp-radius-pill: 999px;

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

  --sp-font: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --sp-mono: "JetBrains Mono", ui-monospace, "Cascadia Code", Consolas, monospace;

  --sp-sidebar-width: 232px;
}

/* Light tokens are listed twice on purpose: once for the OS preference and once
   for an explicit choice. A media query cannot be combined into the same rule as
   an attribute selector, and aliasing them through a second layer of variables
   would cost more in legibility than the repetition does. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    color-scheme: light;
    --sp-bg: #ffffff;
    --sp-surface: #f7f9fc;
    --sp-surface-raised: #ffffff;
    --sp-surface-hover: #eef2f8;
    --sp-border: #e2e8f0;
    --sp-border-strong: #cbd4e1;
    --sp-text: #0e1116;
    --sp-text-muted: #5a6472;
    --sp-text-faint: #7d8797;
    --sp-new: #7c4dff;
    --sp-open: #0f6fde;
    --sp-waiting: #b26a00;
    --sp-resolved: #137547;
    --sp-breach: #c0322b;
  }
}

/* An explicit choice must also pin color-scheme, or native scrollbars, date
   pickers and autofill keep following the OS and end up inverted against the
   tokens — the one part of the page CSS variables cannot reach. */
:root[data-theme="dark"] { color-scheme: dark; }

:root[data-theme="light"] {
  color-scheme: light;
  --sp-bg: #ffffff;
  --sp-surface: #f7f9fc;
  --sp-surface-raised: #ffffff;
  --sp-surface-hover: #eef2f8;
  --sp-border: #e2e8f0;
  --sp-border-strong: #cbd4e1;
  --sp-text: #0e1116;
  --sp-text-muted: #5a6472;
  --sp-text-faint: #7d8797;
  --sp-new: #7c4dff;
  --sp-open: #0f6fde;
  --sp-waiting: #b26a00;
  --sp-resolved: #137547;
  --sp-breach: #c0322b;
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  background: var(--sp-bg);
  color: var(--sp-text);
  font: 14px/1.6 var(--sp-font);
  -webkit-font-smoothing: antialiased;
}

/* Portal is read by people who do not live in this tool all day. */
body.sp-portal { font-size: 16px; }

h1, h2, h3, h4 { margin: 0 0 var(--sp-space-3); line-height: 1.25; font-weight: 600; }
h1 { font-size: 24px; letter-spacing: -0.01em; }
h2 { font-size: 20px; }
h3 { font-size: 16px; }
p { margin: 0 0 var(--sp-space-3); }

a { color: var(--sp-accent-text); text-decoration: none; }
a:hover { text-decoration: underline; }

code, .sp-mono { font-family: var(--sp-mono); font-size: 0.92em; }

/* Focus is always visible and always uses the readable accent variant. */
:focus-visible {
  outline: 2px solid var(--sp-accent-text);
  outline-offset: 2px;
  border-radius: var(--sp-radius-sm);
}

/* ---- App shell ---------------------------------------------------------- */

.sp-app { display: grid; grid-template-columns: var(--sp-sidebar-width) 1fr; min-height: 100vh; }

.sp-sidebar {
  background: var(--sp-surface);
  border-right: 1px solid var(--sp-border);
  padding: var(--sp-space-5) var(--sp-space-4);
  display: flex;
  flex-direction: column;
  gap: var(--sp-space-5);
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.sp-sidebar__head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-space-3); }
.sp-sidebar__body { display: flex; flex-direction: column; gap: var(--sp-space-5); flex: 1 1 auto; }

/* The menu button only exists on narrow screens; see "Mobile navigation" below. */
.sp-navtoggle { display: none; }
.sp-navtoggle__close { display: none; }

.sp-brand { display: flex; align-items: center; gap: var(--sp-space-3); min-width: 0; }
.sp-brand__mark {
  width: 30px; height: 30px; flex: 0 0 30px;
  border-radius: 9px;
  background: var(--sp-accent);
  display: grid; place-items: center;
  font-size: 16px; line-height: 1;
}
.sp-brand__name {
  font-weight: 600; font-size: 15px; letter-spacing: -0.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  color: var(--sp-text);
}
.sp-brand__name em { font-style: normal; font-weight: 400; }

.sp-nav { display: flex; flex-direction: column; gap: 2px; }
.sp-nav__label {
  font-size: 11px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--sp-text-faint); padding: var(--sp-space-3) var(--sp-space-2) var(--sp-space-1);
}
.sp-nav__item {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-space-2);
  padding: 7px var(--sp-space-3);
  border-radius: var(--sp-radius-sm);
  color: var(--sp-text-muted);
  font-weight: 500;
}
.sp-nav__item:hover { background: var(--sp-surface-hover); color: var(--sp-text); text-decoration: none; }
.sp-nav__item.is-active { background: var(--sp-surface-hover); color: var(--sp-text); box-shadow: inset 2px 0 0 var(--sp-accent); }
.sp-nav__count {
  font-size: 11px; font-variant-numeric: tabular-nums;
  background: var(--sp-surface-raised); border: 1px solid var(--sp-border);
  border-radius: var(--sp-radius-pill); padding: 1px 7px; color: var(--sp-text-muted);
}

.sp-sidebar__footer { margin-top: auto; border-top: 1px solid var(--sp-border); padding-top: var(--sp-space-4); }
.sp-user { display: flex; align-items: center; gap: var(--sp-space-3); min-width: 0; }
.sp-avatar {
  width: 30px; height: 30px; flex: 0 0 30px; border-radius: 50%;
  background: var(--sp-surface-raised); border: 1px solid var(--sp-border);
  display: grid; place-items: center; font-size: 12px; font-weight: 600; color: var(--sp-text-muted);
}
.sp-user__meta { min-width: 0; }
.sp-user__name { font-weight: 500; font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sp-user__role { font-size: 11px; color: var(--sp-text-faint); }

/* The sidebar profile block links to /profile. */
.sp-user--link {
  color: inherit; text-decoration: none;
  margin: calc(-1 * var(--sp-space-2)); padding: var(--sp-space-2);
  border-radius: var(--sp-radius);
}
.sp-user--link:hover, .sp-user--link.is-active { background: var(--sp-surface-raised); }
.sp-user--link:focus-visible { outline: 2px solid var(--sp-accent, currentColor); outline-offset: 2px; }

/* ---- Profile page ---- */
.sp-profile { display: grid; gap: var(--sp-space-4); max-width: 560px; }
.sp-profile__note { display: block; margin-bottom: var(--sp-space-3); }

.sp-main { min-width: 0; display: flex; flex-direction: column; }

.sp-topbar {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-space-4);
  padding: var(--sp-space-4) var(--sp-space-6);
  border-bottom: 1px solid var(--sp-border);
  background: color-mix(in srgb, var(--sp-bg) 88%, transparent);
  position: sticky; top: 0; z-index: 10; backdrop-filter: blur(8px);
}
.sp-topbar__title { font-size: 16px; font-weight: 600; }
.sp-topbar__meta { font-size: 12px; color: var(--sp-text-faint); }
.sp-topbar__actions { display: flex; align-items: center; gap: var(--sp-space-4); }

/* ---- Theme toggle ------------------------------------------------------- */

/* Three states rather than two: the OS preference is a real answer, and a
   two-way switch would force everyone to pick a side of a decision their
   machine already made. */
.sp-theme {
  display: inline-flex; align-items: center; gap: 2px;
  padding: 2px;
  background: var(--sp-surface);
  border: 1px solid var(--sp-border);
  border-radius: var(--sp-radius-pill);
}
.sp-theme__option {
  display: grid; place-items: center;
  width: 28px; height: 22px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--sp-radius-pill);
  background: transparent;
  color: var(--sp-text-faint);
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.sp-theme__option:hover { background: var(--sp-surface-hover); color: var(--sp-text); }
.sp-theme__option[aria-pressed="true"] {
  background: var(--sp-surface-raised);
  border-color: var(--sp-border-strong);
  color: var(--sp-accent-text);
}
.sp-theme__option svg { width: 14px; height: 14px; display: block; }

.sp-content { padding: var(--sp-space-6); flex: 1; max-width: 1400px; width: 100%; }

/* ---- Cards and stats ---------------------------------------------------- */

.sp-card {
  background: var(--sp-surface);
  border: 1px solid var(--sp-border);
  border-radius: var(--sp-radius);
  padding: var(--sp-space-5);
}
.sp-card__header {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-space-3);
  margin-bottom: var(--sp-space-4);
}
.sp-card__title { font-size: 14px; font-weight: 600; margin: 0; }

.sp-grid { display: grid; gap: var(--sp-space-4); }
.sp-grid--stats { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.sp-grid--split { grid-template-columns: repeat(auto-fit, minmax(min(100%, 380px), 1fr)); }

.sp-stat {
  background: var(--sp-surface);
  border: 1px solid var(--sp-border);
  border-radius: var(--sp-radius);
  padding: var(--sp-space-4);
  display: flex; flex-direction: column; gap: var(--sp-space-1);
}
.sp-stat__value { font-size: 28px; font-weight: 600; line-height: 1.1; font-variant-numeric: tabular-nums; }
.sp-stat__label { font-size: 12px; color: var(--sp-text-muted); }
.sp-stat[data-tone="urgent"] .sp-stat__value { color: var(--sp-breach); }
.sp-stat[data-tone="waiting"] .sp-stat__value { color: var(--sp-waiting); }
.sp-stat[data-tone="good"] .sp-stat__value { color: var(--sp-resolved); }

/* ---- Pills -------------------------------------------------------------- */

.sp-pill {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 9px;
  border-radius: var(--sp-radius-pill);
  font-size: 11px; font-weight: 600; letter-spacing: 0.01em;
  white-space: nowrap;
  border: 1px solid transparent;
}
.sp-pill__dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: 0 0 6px; }

.sp-pill[data-status="New"]               { color: var(--sp-new);      background: color-mix(in srgb, var(--sp-new) 14%, transparent);      border-color: color-mix(in srgb, var(--sp-new) 30%, transparent); }
.sp-pill[data-status="Open"]              { color: var(--sp-open);     background: color-mix(in srgb, var(--sp-open) 14%, transparent);     border-color: color-mix(in srgb, var(--sp-open) 30%, transparent); }
.sp-pill[data-status="Pending"]           { color: var(--sp-text-muted); background: color-mix(in srgb, var(--sp-text-muted) 12%, transparent); border-color: var(--sp-border); }
.sp-pill[data-status="WaitingOnCustomer"] { color: var(--sp-waiting);  background: color-mix(in srgb, var(--sp-waiting) 14%, transparent);  border-color: color-mix(in srgb, var(--sp-waiting) 30%, transparent); }
.sp-pill[data-status="Resolved"]          { color: var(--sp-resolved); background: color-mix(in srgb, var(--sp-resolved) 14%, transparent); border-color: color-mix(in srgb, var(--sp-resolved) 30%, transparent); }
.sp-pill[data-status="Closed"]            { color: var(--sp-text-faint); background: color-mix(in srgb, var(--sp-text-faint) 12%, transparent); border-color: var(--sp-border); }

/* Priority uses colour AND a glyph, so it survives colour-blindness and
   greyscale printing. */
.sp-priority { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 500; }
.sp-priority__glyph { font-family: var(--sp-mono); font-size: 11px; letter-spacing: -1px; }
.sp-priority[data-priority="Urgent"] { color: var(--sp-breach); }
.sp-priority[data-priority="High"]   { color: var(--sp-waiting); }
.sp-priority[data-priority="Normal"] { color: var(--sp-text-muted); }
.sp-priority[data-priority="Low"]    { color: var(--sp-text-faint); }

.sp-queue-tag {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12px; color: var(--sp-text-muted);
}
.sp-queue-tag__swatch { width: 8px; height: 8px; border-radius: 2px; flex: 0 0 8px; }

.sp-key {
  font-family: var(--sp-mono); font-size: 12px; font-weight: 500;
  color: var(--sp-text-muted); white-space: nowrap;
}

/* ---- Tables ------------------------------------------------------------- */

.sp-table-wrap {
  border: 1px solid var(--sp-border);
  border-radius: var(--sp-radius);
  overflow-x: auto;
  background: var(--sp-surface);
}
.sp-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.sp-table th {
  text-align: left; font-size: 11px; font-weight: 600;
  letter-spacing: 0.05em; text-transform: uppercase; color: var(--sp-text-faint);
  padding: var(--sp-space-3) var(--sp-space-4);
  border-bottom: 1px solid var(--sp-border);
  white-space: nowrap;
}
.sp-table td {
  padding: var(--sp-space-3) var(--sp-space-4);
  border-bottom: 1px solid var(--sp-border);
  vertical-align: middle;
}
.sp-table tbody tr:last-child td { border-bottom: none; }
.sp-table tbody tr:hover { background: var(--sp-surface-hover); }
.sp-table__subject { font-weight: 500; color: var(--sp-text); }
.sp-table__subject:hover { color: var(--sp-accent-text); text-decoration: none; }
.sp-table__muted { color: var(--sp-text-muted); }
.sp-table__num { font-variant-numeric: tabular-nums; text-align: right; }

/* ---- Forms and buttons -------------------------------------------------- */

.sp-field { display: flex; flex-direction: column; gap: 6px; margin-bottom: var(--sp-space-4); }
.sp-label { font-size: 12px; font-weight: 600; color: var(--sp-text-muted); }
.sp-hint { font-size: 12px; color: var(--sp-text-faint); }

/* A field label with a help affordance beside it, kept on one line. */
.sp-field__labelrow { display: flex; align-items: center; }

.sp-input, .sp-select, .sp-textarea {
  width: 100%;
  padding: 9px var(--sp-space-3);
  background: var(--sp-bg);
  border: 1px solid var(--sp-border-strong);
  border-radius: var(--sp-radius-sm);
  color: var(--sp-text);
  font: inherit;
  transition: border-color 120ms ease;
}
.sp-input:hover, .sp-select:hover, .sp-textarea:hover { border-color: var(--sp-accent); }
.sp-input:focus, .sp-select:focus, .sp-textarea:focus { border-color: var(--sp-accent); outline-offset: 1px; }
.sp-textarea { resize: vertical; min-height: 110px; line-height: 1.6; }
.sp-select { appearance: none; padding-right: var(--sp-space-6); background-image: none; }

.sp-check { display: flex; align-items: center; gap: var(--sp-space-2); font-size: 13px; }
.sp-check input { accent-color: var(--sp-accent); width: 15px; height: 15px; }

.sp-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: 8px var(--sp-space-4);
  border-radius: var(--sp-radius-sm);
  border: 1px solid var(--sp-border-strong);
  background: var(--sp-surface-raised);
  color: var(--sp-text);
  font: inherit; font-weight: 500;
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease;
  white-space: nowrap;
}
.sp-btn:hover { background: var(--sp-surface-hover); border-color: var(--sp-accent); text-decoration: none; }

/* Accent fill uses the raw tenant colour; the label is forced to a tone that
   reads against it regardless of what they picked. */
.sp-btn--primary {
  background: var(--sp-accent);
  border-color: var(--sp-accent);
  color: #06090d;
  font-weight: 600;
}
.sp-btn--primary:hover { background: var(--sp-accent-hover); border-color: var(--sp-accent-hover); }
.sp-btn--ghost { background: transparent; border-color: transparent; color: var(--sp-text-muted); }
.sp-btn--ghost:hover { background: var(--sp-surface-hover); color: var(--sp-text); }
.sp-btn--sm { padding: 5px var(--sp-space-3); font-size: 12px; }
.sp-btn--danger { color: var(--sp-breach); border-color: color-mix(in srgb, var(--sp-breach) 40%, transparent); }

.sp-toolbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-space-3);
  margin-bottom: var(--sp-space-5);
}
.sp-toolbar__grow { flex: 1 1 220px; min-width: 0; }
.sp-toolbar__spacer { margin-left: auto; }

/* ---- Collapsible filter panel ------------------------------------------- */

/* A <details> rather than script: collapsed state costs no JS, survives a
   filter submit reloading the page, and keeps the toggle keyboard-operable.
   The primary action sits outside the panel so it stays reachable when closed. */
.sp-filterbar {
  display: flex; align-items: flex-start; gap: var(--sp-space-3);
  margin-bottom: var(--sp-space-5);
}
.sp-filters { flex: 1 1 auto; min-width: 0; }

/* Styled as a button, because that is what it behaves like. */
.sp-filters__toggle {
  display: inline-flex; align-items: center; gap: var(--sp-space-2);
  padding: 8px var(--sp-space-4);
  border: 1px solid var(--sp-border-strong);
  border-radius: var(--sp-radius-sm);
  background: var(--sp-surface-raised);
  color: var(--sp-text);
  font-weight: 500;
  cursor: pointer;
  user-select: none;
  list-style: none;
  transition: background 120ms ease, border-color 120ms ease;
}
.sp-filters__toggle::-webkit-details-marker { display: none; }
.sp-filters__toggle:hover { background: var(--sp-surface-hover); border-color: var(--sp-accent); }

.sp-filters__chevron {
  width: 6px; height: 6px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg);
  transition: transform 120ms ease;
}
.sp-filters[open] .sp-filters__chevron { transform: rotate(45deg); }

/* Count only, not a list of names: the panel is one click away, and a long
   summary line would defeat the point of collapsing it. */
.sp-filters__count {
  font-size: 11px; font-weight: 600;
  padding: 1px 7px;
  border-radius: var(--sp-radius-pill);
  background: color-mix(in srgb, var(--sp-accent) 22%, transparent);
  color: var(--sp-accent-text);
}

.sp-filters__form { margin-top: var(--sp-space-3); margin-bottom: 0; }

.sp-validation { color: var(--sp-breach); font-size: 12px; }
.sp-alert {
  padding: var(--sp-space-3) var(--sp-space-4);
  border-radius: var(--sp-radius-sm);
  border: 1px solid var(--sp-border);
  background: var(--sp-surface);
  margin-bottom: var(--sp-space-4);
  font-size: 13px;
}
.sp-alert--error { border-color: color-mix(in srgb, var(--sp-breach) 40%, transparent); color: var(--sp-breach); }
.sp-alert--ok { border-color: color-mix(in srgb, var(--sp-resolved) 40%, transparent); color: var(--sp-resolved); }
.sp-alert--warn { border-color: color-mix(in srgb, var(--sp-waiting) 40%, transparent); color: var(--sp-waiting); }

/* ---- Conversation thread ------------------------------------------------ */

.sp-thread { display: flex; flex-direction: column; gap: var(--sp-space-4); }
.sp-message {
  border: 1px solid var(--sp-border);
  border-radius: var(--sp-radius);
  background: var(--sp-surface);
  overflow: hidden;
}
/* Internal notes are visually unmistakable. An agent must never mistake one
   for a customer-visible reply. */
.sp-message--internal {
  background: color-mix(in srgb, var(--sp-waiting) 7%, var(--sp-surface));
  border-color: color-mix(in srgb, var(--sp-waiting) 35%, transparent);
}
.sp-message__header {
  display: flex; align-items: center; gap: var(--sp-space-3);
  padding: var(--sp-space-3) var(--sp-space-4);
  border-bottom: 1px solid var(--sp-border);
  font-size: 12px;
}
.sp-message__author { font-weight: 600; font-size: 13px; }
.sp-message__time { color: var(--sp-text-faint); margin-left: auto; }
.sp-message__body { padding: var(--sp-space-4); }
.sp-message__body > :last-child { margin-bottom: 0; }
.sp-message__body a { text-decoration: underline; }
.sp-message__body pre {
  background: var(--sp-bg); border: 1px solid var(--sp-border);
  border-radius: var(--sp-radius-sm); padding: var(--sp-space-3);
  overflow-x: auto;
}
.sp-message__body table { border-collapse: collapse; width: 100%; }
.sp-message__body td, .sp-message__body th { border: 1px solid var(--sp-border); padding: 6px 8px; }

.sp-badge-internal {
  font-size: 10px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--sp-waiting);
  border: 1px solid color-mix(in srgb, var(--sp-waiting) 45%, transparent);
  border-radius: var(--sp-radius-pill); padding: 1px 7px;
}

.sp-timeline { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--sp-space-3); }
.sp-timeline li { display: flex; gap: var(--sp-space-3); font-size: 12px; color: var(--sp-text-muted); }
.sp-timeline time { color: var(--sp-text-faint); margin-left: auto; white-space: nowrap; }

/* ---- Detail layout ----------------------------------------------------- */

.sp-detail { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: var(--sp-space-5); align-items: start; }
.sp-aside { display: flex; flex-direction: column; gap: var(--sp-space-4); position: sticky; top: 84px; }
.sp-props { display: flex; flex-direction: column; gap: var(--sp-space-3); }
.sp-prop { display: flex; flex-direction: column; gap: 3px; }
.sp-prop__label { font-size: 11px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--sp-text-faint); }
.sp-prop__value { font-size: 13px; }

/* ---- Auth screens ------------------------------------------------------ */

.sp-auth { min-height: 100vh; display: grid; place-items: center; padding: var(--sp-space-5); }
.sp-auth__card {
  width: 100%; max-width: 380px;
  background: var(--sp-surface);
  border: 1px solid var(--sp-border);
  border-radius: 14px;
  padding: var(--sp-space-6);
}
.sp-auth__brand { display: flex; align-items: center; gap: var(--sp-space-3); margin-bottom: var(--sp-space-5); }
/* Reachable before sign-in: someone on a bright screen should not have to
   authenticate in the dark first. */
.sp-auth__brand .sp-theme { margin-left: auto; flex: none; }
.sp-auth__tagline { color: var(--sp-text-muted); font-size: 13px; margin-bottom: var(--sp-space-5); }
.sp-auth__divider {
  display: flex; align-items: center; gap: var(--sp-space-3);
  margin: var(--sp-space-5) 0; color: var(--sp-text-faint); font-size: 12px;
}
.sp-auth__divider::before, .sp-auth__divider::after {
  content: ""; height: 1px; background: var(--sp-border); flex: 1;
}

/* ---- Empty states ------------------------------------------------------ */

.sp-empty { text-align: center; padding: var(--sp-space-7) var(--sp-space-5); color: var(--sp-text-muted); }
.sp-empty__icon { font-size: 28px; margin-bottom: var(--sp-space-3); opacity: 0.8; }
.sp-empty__title { font-weight: 600; color: var(--sp-text); margin-bottom: var(--sp-space-1); }

/* ---- Pagination -------------------------------------------------------- */

.sp-pager { display: flex; align-items: center; gap: var(--sp-space-3); margin-top: var(--sp-space-4); font-size: 13px; }
.sp-pager__info { color: var(--sp-text-muted); margin-right: auto; font-variant-numeric: tabular-nums; }

/* ---- Impersonation banner ---------------------------------------------- */

/* Persistent and loud by design. Impersonation must never be ambiguous. */
.sp-impersonation {
  background: var(--sp-breach); color: #0b0b0d;
  padding: 6px var(--sp-space-5);
  font-size: 12px; font-weight: 600; text-align: center;
}

/* ---- Responsive -------------------------------------------------------- */

@media (max-width: 1080px) {
  .sp-detail { grid-template-columns: minmax(0, 1fr); }
  .sp-aside { position: static; }
}

/* ---- Mobile navigation --------------------------------------------------
   The sidebar becomes a slim sticky bar (brand + menu button). The menu button opens the full
   navigation — section labels, profile and sign out included — as a panel filling the screen below
   the bar, with large tap targets. nav.js toggles .is-open. */
@media (max-width: 860px) {
  /* minmax(0, …), not 1fr: a bare 1fr column grows to fit its widest content, so a wide table
     made the whole page wider than the phone and pushed the menu button off screen. The table
     scrolls inside .sp-table-wrap instead. */
  .sp-app { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto 1fr; }

  .sp-sidebar {
    --sp-mobilebar: 56px;
    position: sticky; top: 0; z-index: 30;
    height: var(--sp-mobilebar);
    padding: 0 var(--sp-space-2) 0 var(--sp-space-4);
    border-right: 0; border-bottom: 1px solid var(--sp-border);
    overflow: visible;
    gap: 0;
  }
  .sp-sidebar__head { height: 100%; }

  .sp-navtoggle {
    display: inline-grid; place-items: center;
    width: 44px; height: 44px;
    border: 0; border-radius: var(--sp-radius-sm);
    background: transparent; color: var(--sp-text);
    cursor: pointer;
  }
  .sp-navtoggle:hover { background: var(--sp-surface-hover); }
  .sp-sidebar.is-open .sp-navtoggle__open { display: none; }
  .sp-sidebar.is-open .sp-navtoggle__close { display: block; }

  .sp-sidebar__body {
    display: none;
    position: fixed; left: 0; right: 0; bottom: 0;
    top: var(--sp-drawer-top, var(--sp-mobilebar));
    padding: var(--sp-space-3) var(--sp-space-4) calc(var(--sp-space-5) + env(safe-area-inset-bottom));
    background: var(--sp-surface);
    overflow-y: auto; overscroll-behavior: contain;
  }
  .sp-sidebar.is-open .sp-sidebar__body { display: flex; }

  .sp-nav__item { min-height: 44px; padding: 10px var(--sp-space-3); font-size: 15px; }
  .sp-sidebar__footer {
    margin-top: var(--sp-space-3);
    display: flex; align-items: center; justify-content: space-between; gap: var(--sp-space-3);
  }
  .sp-sidebar__footer .sp-user--link { flex: 1 1 auto; margin: 0; }

  /* The page title bar scrolls away rather than stacking under the sticky menu bar. */
  .sp-topbar { position: static; backdrop-filter: none; }
  .sp-content, .sp-topbar { padding-left: var(--sp-space-4); padding-right: var(--sp-space-4); }
}

@media (max-width: 560px) {
  .sp-topbar__host { display: none; }
}

html.sp-nav-open, html.sp-nav-open body { overflow: hidden; }

/* ---- Ticket list on phones ----------------------------------------------
   Each row of the ticket table becomes a card, in three lines:
     subject, with key and requester under it
     status · priority · queue
     client · assignee                                   time
   The subject link is stretched over the whole card, so the card is one big tap target. The table
   markup is unchanged, so desktop is untouched. */
@media (max-width: 720px) {
  .sp-ticketlist-wrap { overflow: visible; }
  .sp-ticketlist, .sp-ticketlist tbody { display: block; }
  .sp-ticketlist thead { display: none; }

  .sp-ticketlist tr {
    position: relative;
    display: flex; flex-wrap: wrap; align-items: center;
    gap: var(--sp-space-2) var(--sp-space-3);
    padding: var(--sp-space-3) var(--sp-space-4);
    border-bottom: 1px solid var(--sp-border);
  }
  .sp-ticketlist tbody tr:last-child { border-bottom: none; }
  .sp-ticketlist tr:active { background: var(--sp-surface-hover); }

  .sp-ticketlist td { display: block; padding: 0; border: 0; min-width: 0; }

  .sp-ticketlist .sp-tl__main { order: 1; flex: 1 0 100%; }
  .sp-ticketlist .sp-table__subject { font-size: 15px; line-height: 1.35; }
  .sp-ticketlist .sp-table__subject::after { content: ""; position: absolute; inset: 0; }
  .sp-ticketlist .sp-key { margin-top: 2px; white-space: normal; }

  .sp-ticketlist .sp-tl__status   { order: 2; }
  .sp-ticketlist .sp-tl__priority { order: 3; }
  .sp-ticketlist .sp-tl__queue    { order: 4; }

  /* A zero-height, full-width item: forces client/assignee/time onto their own line. */
  .sp-ticketlist tr::after { content: ""; order: 5; flex: 0 0 100%; height: 0; margin-top: calc(-1 * var(--sp-space-2)); }

  .sp-ticketlist .sp-tl__client,
  .sp-ticketlist .sp-tl__assignee,
  .sp-ticketlist .sp-tl__time { font-size: 12px; }
  .sp-ticketlist .sp-tl__client   { order: 6; }
  .sp-ticketlist .sp-tl__assignee { order: 7; margin-left: calc(4px - var(--sp-space-3)); }
  .sp-ticketlist .sp-tl__assignee::before { content: "· "; color: var(--sp-text-faint); }
  .sp-ticketlist .sp-tl__time     { order: 8; margin-left: auto; white-space: nowrap; }

  /* Filters: the fields stack full width, and an open panel takes the whole row so the fields
     are not squeezed beside the New ticket button. */
  .sp-filterbar { flex-wrap: wrap; }
  .sp-filters[open] { flex-basis: 100%; }
  .sp-filters__form > * { flex: 1 1 100%; }
  .sp-filters__form .sp-btn { width: 100%; }

  .sp-pager { flex-wrap: wrap; }
  .sp-pager__info { flex: 1 0 100%; }
  .sp-pager .sp-btn { flex: 1 1 0; justify-content: center; text-align: center; padding-top: 10px; padding-bottom: 10px; }
}

/* ---- Client list on phones ----------------------------------------------
   Each client becomes a card:
     name (and "us"/"MSP" badge)                         status
     MSP name (platform view only)
     prefix · 3 open tickets · 5 users
   On an MSP's own host the name link is stretched over the card, so the whole card opens the
   client and the separate Manage button is not needed. The counts take their units from
   data-unit, because the column headers are hidden. */
@media (max-width: 720px) {
  .sp-clientlist-wrap { overflow: visible; }
  .sp-clientlist, .sp-clientlist tbody { display: block; }
  .sp-clientlist thead { display: none; }

  .sp-clientlist tr {
    position: relative;
    display: flex; flex-wrap: wrap; align-items: center;
    gap: var(--sp-space-1) var(--sp-space-2);
    padding: var(--sp-space-3) var(--sp-space-4);
    border-bottom: 1px solid var(--sp-border);
  }
  .sp-clientlist tbody tr:last-child { border-bottom: none; }
  .sp-clientlist tr:active { background: var(--sp-surface-hover); }

  .sp-clientlist td { display: block; padding: 0; border: 0; min-width: 0; text-align: left; }

  .sp-clientlist .sp-cl__name { order: 1; flex: 1 1 auto; }
  .sp-clientlist .sp-table__subject { font-size: 15px; }
  .sp-clientlist a.sp-table__subject::after { content: ""; position: absolute; inset: 0; }
  .sp-clientlist .sp-cl__status { order: 2; margin-left: auto; font-size: 12px; }

  .sp-clientlist tr::after { content: ""; order: 3; flex: 0 0 100%; height: 0; }

  .sp-clientlist .sp-cl__msp { order: 4; flex: 0 0 100%; font-size: 12px; }
  /* An MSP's own row: the MSP line would only repeat the name above it. */
  .sp-clientlist .sp-cl__msp--self { display: none; }

  .sp-clientlist .sp-cl__code  { order: 5; }
  .sp-clientlist .sp-cl__open  { order: 6; font-size: 12px; color: var(--sp-text-muted); }
  .sp-clientlist .sp-cl__users { order: 7; font-size: 12px; }
  .sp-clientlist .sp-cl__open::before,
  .sp-clientlist .sp-cl__users::before { content: "· "; color: var(--sp-text-faint); }
  .sp-clientlist .sp-cl__open,
  .sp-clientlist .sp-cl__users { margin-left: calc(4px - var(--sp-space-2)); }
  .sp-clientlist .sp-cl__open::after,
  .sp-clientlist .sp-cl__users::after { content: " " attr(data-unit); }

  .sp-clientlist .sp-cl__manage { display: none; }
}

/* ---- Card lists on phones -----------------------------------------------
   A general version of the two lists above, for tables whose rows hold controls (so the card
   cannot be one big link). Used by the Users pages. Mark the table .sp-cardlist and each cell:
     .sp-cc__title    first line, left          .sp-cc__badge    first line, right (status)
     .sp-cc__sub      second line, full width   .sp-cc__meta     small items on one wrapping line;
     .sp-cc__control  a form/control row                          data-label="…" prefixes the value
     .sp-cc__actions  buttons, right-aligned    .sp-cc__wide-only  hidden on the card
   .sp-cardlist--sortable keeps the header row as "Sort by" links instead of hiding it. */
@media (max-width: 720px) {
  .sp-cardlist-wrap { overflow: visible; }
  .sp-cardlist, .sp-cardlist tbody { display: block; }
  .sp-cardlist thead { display: none; }

  .sp-cardlist tbody tr {
    display: flex; flex-wrap: wrap; align-items: center;
    gap: var(--sp-space-1) var(--sp-space-3);
    padding: var(--sp-space-3) var(--sp-space-4);
    border-bottom: 1px solid var(--sp-border);
  }
  .sp-cardlist tbody tr:last-child { border-bottom: none; }
  .sp-cardlist tbody tr:hover { background: transparent; }
  .sp-cardlist td { display: block; padding: 0; border: 0; min-width: 0; text-align: left; }

  .sp-cardlist .sp-cc__title { order: 1; flex: 1 1 auto; font-size: 15px; }
  /* With no status beside it, the title has its line to itself, so details start below it. */
  .sp-cardlist tr:not(:has(.sp-cc__badge)) .sp-cc__title { flex-basis: 100%; overflow-wrap: anywhere; }
  .sp-cardlist .sp-cc__badge { order: 2; margin-left: auto; }
  .sp-cardlist .sp-cc__sub   { order: 3; flex: 0 0 100%; font-size: 13px; overflow-wrap: anywhere; }
  .sp-cardlist .sp-cc__meta  { order: 4; font-size: 12px; }
  .sp-cardlist [data-label]::before { content: attr(data-label) " "; color: var(--sp-text-faint); }
  /* A value that is missing (no IP recorded, say) would otherwise leave its label standing alone. */
  .sp-cardlist .sp-cc__meta:empty { display: none; }

  /* Ends the meta line, so controls and actions start on a line of their own. */
  .sp-cardlist tbody tr::after { content: ""; order: 5; flex: 0 0 100%; height: var(--sp-space-1); }
  .sp-cardlist tbody tr:not(:has(.sp-cc__control, .sp-cc__actions))::after { display: none; }

  /* Audit log: the time is the right-hand badge, kept on one line. */
  .sp-auditlist .sp-cc__badge { font-size: 12px; white-space: nowrap; }
  .sp-auditlist .sp-cc__title .sp-key { font-size: 13px; white-space: normal; overflow-wrap: anywhere; }

  .sp-cardlist .sp-cc__control {
    order: 6; flex: 1 1 auto;
    display: flex; align-items: center; gap: var(--sp-space-2);
    font-size: 13px;
  }
  .sp-cardlist .sp-cc__control .sp-users__role { flex: 1 1 auto; }
  .sp-cardlist .sp-cc__control .sp-select { flex: 1 1 auto; min-width: 0; padding-top: 8px; padding-bottom: 8px; font-size: 13px; }
  .sp-cardlist .sp-cc__actions { order: 7; margin-left: auto; }
  .sp-cardlist .sp-cc__actions:empty { display: none; }
  .sp-cardlist .sp-btn--sm { padding: 8px var(--sp-space-3); }

  .sp-cardlist .sp-cc__wide-only { display: none; }

  /* Sortable lists keep their headings, as a wrapping row of links above the cards. */
  .sp-cardlist--sortable thead { display: block; border-bottom: 1px solid var(--sp-border); }
  .sp-cardlist--sortable thead tr {
    display: flex; flex-wrap: wrap; align-items: center;
    gap: var(--sp-space-2) var(--sp-space-3);
    padding: var(--sp-space-3) var(--sp-space-4);
  }
  .sp-cardlist--sortable thead tr::before {
    content: "Sort by"; font-size: 11px; font-weight: 600; letter-spacing: 0.05em;
    text-transform: uppercase; color: var(--sp-text-faint);
  }
  .sp-cardlist--sortable th { display: block; padding: 0; border: 0; }
  .sp-cardlist--sortable th:has(.sp-sr-only):not(:has(a)) { display: none; }
  .sp-cardlist--sortable .sp-sort {
    padding: 4px 10px; border: 1px solid var(--sp-border); border-radius: var(--sp-radius-pill);
    text-transform: none; letter-spacing: 0; font-size: 12px;
  }
  .sp-cardlist--sortable .sp-sort.is-active { border-color: var(--sp-accent); }

  .sp-users__filter { max-width: none; flex: 1 1 100%; }
}

@media print {
  .sp-sidebar, .sp-topbar, .sp-btn, .sp-theme { display: none; }
  body { background: #fff; color: #000; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}

/* ---- Branding editor ---------------------------------------------------- */

/* Classes rather than style="" attributes: the CSP carries no unsafe-inline, so
   inline style attributes are dropped by the browser and the layout silently
   collapses. Everything visual on that page lives here instead. */

.sp-brandform { max-width: 620px; }
.sp-brandform__switch { margin-bottom: var(--sp-space-4); }
.sp-brandform__switchrow { display: flex; gap: var(--sp-space-3); align-items: center; }
.sp-brandform__hint { display: block; margin-top: var(--sp-space-3); }
.sp-brandform__note { margin-top: var(--sp-space-5); }
.sp-brandform__notetext { font-size: 13px; margin-bottom: 0; }

.sp-brandform__colour { display: flex; gap: var(--sp-space-3); align-items: center; }
.sp-brandform__hex { max-width: 140px; }
.sp-brandform__picker {
  width: 44px; height: 38px;
  border: 1px solid var(--sp-border-strong);
  border-radius: var(--sp-radius-sm);
  background: var(--sp-bg);
  padding: 2px;
}
.sp-brandform__swatch {
  width: 38px; height: 38px;
  border-radius: var(--sp-radius-sm);
  border: 1px solid var(--sp-border);
}

.sp-brandform__pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-space-4);
}

@media (max-width: 560px) {
  .sp-brandform__pair { grid-template-columns: 1fr; }
  .sp-brandform__switchrow { flex-wrap: wrap; }
}

/* Visually hidden but read by assistive tech — for a column header whose cells
   hold only buttons. */
.sp-sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Sign-in link documentation on the branding page. */
.sp-brandform__doc { font-size: 13px; color: var(--sp-text-muted); }
.sp-brandform__doc:last-child { margin-bottom: 0; }
.sp-brandform__docmuted { color: var(--sp-text-faint); }

.sp-brandform__link {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-space-2);
  margin-bottom: var(--sp-space-4);
}
/* The URL is meant to be read and copied, so it gets room and does not wrap mid-token. */
.sp-brandform__url {
  flex: 1 1 260px;
  min-width: 0;
  padding: 7px var(--sp-space-3);
  background: var(--sp-bg);
  border: 1px solid var(--sp-border-strong);
  border-radius: var(--sp-radius-sm);
  color: var(--sp-text);
  overflow-x: auto;
  white-space: nowrap;
}

.sp-signout { margin-top: var(--sp-space-3); }

/* ---- Rich text composer -------------------------------------------------- */

.sp-editor {
  border: 1px solid var(--sp-border-strong);
  border-radius: var(--sp-radius-sm);
  background: var(--sp-bg);
  overflow: hidden;
}

.sp-editor__toolbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 2px;
  padding: var(--sp-space-2);
  border-bottom: 1px solid var(--sp-border);
  background: var(--sp-surface);
}
.sp-editor__tool {
  min-width: 30px; height: 28px;
  padding: 0 var(--sp-space-2);
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid transparent;
  border-radius: var(--sp-radius-sm);
  background: transparent;
  color: var(--sp-text-muted);
  font: inherit; font-size: 13px;
  cursor: pointer;
}
.sp-editor__tool:hover { background: var(--sp-surface-hover); color: var(--sp-text); }
.sp-editor__divider { width: 1px; height: 18px; background: var(--sp-border); margin: 0 var(--sp-space-2); }

/* The file input is the label's own control, hidden but still focusable by keyboard. */
.sp-editor__attach { position: relative; overflow: hidden; }
.sp-editor__attach input[type="file"] {
  position: absolute; inset: 0;
  opacity: 0; cursor: pointer; width: 100%;
}

.sp-editor__surface {
  min-height: 130px;
  padding: var(--sp-space-3);
  color: var(--sp-text);
  line-height: 1.6;
  overflow-y: auto;
  max-height: 420px;
}
.sp-editor__surface:focus { outline: none; }
.sp-editor__surface.is-dropping { background: color-mix(in srgb, var(--sp-accent) 10%, transparent); }

/* Placeholder for a contenteditable, which gets none of its own. */
.sp-editor__surface:empty::before {
  content: attr(data-placeholder);
  color: var(--sp-text-faint);
  pointer-events: none;
}

.sp-editor__surface img { max-width: 100%; height: auto; border-radius: var(--sp-radius-sm); }
.sp-editor__surface blockquote {
  margin: 0 0 var(--sp-space-3);
  padding-left: var(--sp-space-3);
  border-left: 2px solid var(--sp-border-strong);
  color: var(--sp-text-muted);
}

.sp-editor__files { list-style: none; margin: 0; padding: 0; }
.sp-editor__file {
  display: flex; align-items: center; gap: var(--sp-space-2);
  padding: var(--sp-space-2) var(--sp-space-3);
  border-top: 1px solid var(--sp-border);
  font-size: 13px;
}
.sp-editor__file small { color: var(--sp-text-faint); margin-right: auto; }
.sp-editor__file.is-pending { color: var(--sp-text-muted); }
.sp-editor__file.is-failed { color: var(--sp-breach); }

.sp-editor__hint {
  margin: 0;
  padding: var(--sp-space-2) var(--sp-space-3);
  border-top: 1px solid var(--sp-border);
  background: var(--sp-surface);
  font-size: 12px; color: var(--sp-text-faint);
}

/* Images inside a posted message. The class is applied by the sanitizer, so it is present on every
   stored image and cannot be spoofed into meaning something else. */
.sp-message__image {
  max-width: 100%; height: auto;
  border: 1px solid var(--sp-border);
  border-radius: var(--sp-radius-sm);
  margin: var(--sp-space-2) 0;
}

.sp-message__files {
  display: flex; flex-wrap: wrap; gap: var(--sp-space-3);
  padding: var(--sp-space-3) var(--sp-space-4);
  border-top: 1px solid var(--sp-border);
  font-size: 13px;
}
.sp-message__file { display: inline-flex; align-items: center; gap: 6px; }
.sp-message__file small { color: var(--sp-text-faint); }

.sp-reply { margin-top: var(--sp-space-5); }
.sp-reply__title { margin-bottom: var(--sp-space-3); }
.sp-reply__internal { margin-bottom: var(--sp-space-4); }

/* ---- Clickable dashboard stats ------------------------------------------ */

.sp-stats { margin-bottom: var(--sp-space-5); }

/* The tiles are anchors, so they inherit link colour and underline unless told
   otherwise. Text tone comes from the tokens, exactly as it did when they were
   divs, and the affordance is the hover lift plus the arrow below. */
a.sp-stat {
  color: inherit;
  text-decoration: none;
  transition: border-color 120ms ease, background 120ms ease;
}
a.sp-stat:hover {
  background: var(--sp-surface-hover);
  border-color: var(--sp-border-strong);
  text-decoration: none;
}
a.sp-stat:hover .sp-stat__label { color: var(--sp-text); }

/* A quiet cue that the tile goes somewhere, rather than relying on hover alone —
   hover does not exist on a touch screen. */
.sp-stat__label::after {
  content: " →";
  color: var(--sp-text-faint);
  opacity: 0;
  transition: opacity 120ms ease;
}
a.sp-stat:hover .sp-stat__label::after,
a.sp-stat:focus-visible .sp-stat__label::after { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .sp-stat__label::after { transition: none; }
}

/* ---- Settings tabs and forms -------------------------------------------- */

.sp-tabs {
  display: flex; gap: var(--sp-space-1);
  border-bottom: 1px solid var(--sp-border);
  margin-bottom: var(--sp-space-5);
}
.sp-tabs__tab {
  padding: var(--sp-space-3) var(--sp-space-4);
  color: var(--sp-text-muted);
  font-weight: 500;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.sp-tabs__tab:hover { color: var(--sp-text); text-decoration: none; }
.sp-tabs__tab.is-active {
  color: var(--sp-text);
  border-bottom-color: var(--sp-accent);
}

.sp-settings { max-width: 660px; }
.sp-settings__empty { max-width: 660px; }
.sp-settings__switch { margin-bottom: var(--sp-space-4); }
.sp-settings__switchrow { display: flex; gap: var(--sp-space-3); align-items: center; }
.sp-settings__hint { display: block; margin-top: var(--sp-space-3); }
.sp-settings__test { margin-top: var(--sp-space-4); }
.sp-settings__last { font-size: 13px; }
.sp-settings__enabled { margin-bottom: var(--sp-space-4); }
.sp-settings__note { display: block; margin-bottom: var(--sp-space-4); }

.sp-settings__group {
  border: 1px solid var(--sp-border);
  border-radius: var(--sp-radius-sm);
  padding: var(--sp-space-4);
  margin: 0 0 var(--sp-space-4);
}
.sp-settings__group legend {
  font-size: 11px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--sp-text-faint);
  padding: 0 var(--sp-space-2);
}

.sp-settings__pair {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-space-4);
}

@media (max-width: 560px) {
  .sp-settings__pair { grid-template-columns: 1fr; }
  .sp-settings__switchrow { flex-wrap: wrap; }
}

/* ---- Client detail ------------------------------------------------------- */

.sp-client { display: flex; flex-direction: column; gap: var(--sp-space-4); }
.sp-client__stats { margin-bottom: var(--sp-space-4); }

/* The settings form is a form, so it takes the same reading width as the other
   ones rather than stretching to the full content column. The panels below it
   are summaries and do stretch, which is why the cap is not on .sp-client. */
.sp-client > .sp-card:first-child { max-width: 660px; }

.sp-client__readonly { margin-top: var(--sp-space-2); }
.sp-client__check { margin-bottom: var(--sp-space-2); }
.sp-client__checkhint { display: block; margin-bottom: var(--sp-space-5); }

/* Card, summary, then one action at the bottom — so a row of panels lines its
   buttons up however much the summaries above them differ in height. */
.sp-client__panel { display: flex; flex-direction: column; align-items: flex-start; }
.sp-client__summary { margin-bottom: var(--sp-space-4); }
.sp-client__panel > .sp-btn { margin-top: auto; }

.sp-client__colour { display: flex; align-items: center; gap: var(--sp-space-2); }
.sp-client__swatch {
  width: 16px; height: 16px;
  border-radius: var(--sp-radius-sm);
  border: 1px solid var(--sp-border);
  flex: 0 0 16px;
}

/* ---- Users, roles, and invitations --------------------------------------- */

.sp-users__filter { display: flex; gap: var(--sp-space-3); align-items: center; max-width: 420px; }
.sp-users__you { margin-left: var(--sp-space-2); font-weight: 400; }
.sp-users__note { display: block; margin-top: var(--sp-space-4); max-width: 70ch; }
.sp-users__notetext { font-size: 13px; }
.sp-users__invites { margin-top: var(--sp-space-5); }
.sp-users__form { max-width: 620px; display: flex; flex-direction: column; gap: var(--sp-space-4); }

/* Role menu and its button sit on one line so the row does not grow a second one. */
.sp-users__role { display: flex; gap: var(--sp-space-2); align-items: center; }
.sp-users__inviteactions { display: flex; gap: var(--sp-space-2); justify-content: flex-end; }

.sp-select--sm { padding: 4px var(--sp-space-2); font-size: 12px; min-width: 130px; }

/* Sortable column headings. The heading keeps its own colour and weight so the row
   still reads as a header rather than a row of links; only the active one lifts. */
.sp-sort {
  display: inline-flex; align-items: center; gap: 4px;
  color: inherit; font: inherit; letter-spacing: inherit; text-transform: inherit;
}
.sp-sort:hover { color: var(--sp-text); text-decoration: none; }
.sp-sort.is-active { color: var(--sp-text); }
.sp-sort__arrow { font-size: 9px; line-height: 1; }

/* Account state. Muted for the ordinary cases and coloured only for the two that
   mean somebody cannot get in — the same rule as ticket pills, which never carry
   meaning in colour alone: the label is always spelled out. */
.sp-userstate { font-size: 12px; color: var(--sp-text-muted); }
.sp-userstate[data-state="Invited"] { color: var(--sp-waiting); }
.sp-userstate[data-state="Disabled"],
.sp-userstate[data-state="Expired"] { color: var(--sp-breach); }

/* ---- Accepting an invitation --------------------------------------------- */

.sp-invite__title { font-size: 18px; }
.sp-invite__lead { color: var(--sp-text-muted); font-size: 13px; }
.sp-invite__submit { width: 100%; }
.sp-invite__email {
  font-family: var(--sp-mono); font-size: 13px;
  padding: var(--sp-space-2) 0;
  color: var(--sp-text);
}

/* ---- Setup guidance on the settings page --------------------------------- */

.sp-guide {
  border: 1px solid var(--sp-border);
  border-left: 3px solid var(--sp-accent);
  border-radius: var(--sp-radius-sm);
  background: var(--sp-surface);
  padding: var(--sp-space-4);
  margin-bottom: var(--sp-space-4);
  font-size: 13px;
  color: var(--sp-text-muted);
}
.sp-guide__lead { color: var(--sp-text); }
.sp-guide p:last-child { margin-bottom: 0; }

/* The two things people actually get wrong: Delegated instead of Application,
   and leaving the org-wide grant in place so the scope does nothing. */
.sp-guide__warn {
  border-left: 2px solid var(--sp-waiting);
  padding-left: var(--sp-space-3);
  color: var(--sp-waiting);
}
.sp-guide__legacy { color: var(--sp-text-faint); }

.sp-guide__steps { margin: 0 0 var(--sp-space-3); padding-left: var(--sp-space-5); }
.sp-guide__steps li { margin-bottom: var(--sp-space-2); }
.sp-guide__steps strong, .sp-guide__lead strong { color: var(--sp-text); }

/* Collapsed by default: the mailbox scoping is important but long, and it would
   otherwise bury the four fields this page is actually asking for. */
.sp-guide__more > summary {
  cursor: pointer;
  color: var(--sp-accent-text);
  font-weight: 500;
  margin-bottom: var(--sp-space-3);
}
.sp-guide__more[open] > summary { margin-bottom: var(--sp-space-3); }

.sp-guide__code {
  background: var(--sp-bg);
  border: 1px solid var(--sp-border);
  border-radius: var(--sp-radius-sm);
  padding: var(--sp-space-3);
  overflow-x: auto;
  font-size: 12px;
  line-height: 1.6;
  color: var(--sp-text);
}

/* ---- Reports ------------------------------------------------------------ */

/* The catalogue. auto-fit rather than a fixed count so six reports lay out as
   three-by-two on a laptop and one column on a phone with no breakpoints. */
.sp-reports {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: var(--sp-space-4);
  margin-bottom: var(--sp-space-6);
}

.sp-report {
  display: flex; flex-direction: column; gap: var(--sp-space-3);
  background: var(--sp-surface);
  border: 1px solid var(--sp-border);
  border-radius: var(--sp-radius);
  padding: var(--sp-space-5);
}
.sp-report__head { display: flex; align-items: center; gap: var(--sp-space-3); }
.sp-report__icon { font-size: 20px; line-height: 1; }
.sp-report__title { font-size: 14px; font-weight: 600; margin: 0; }

/* Pushes the actions to the bottom so every card's buttons line up across a row
   however long the summaries are. */
.sp-report__summary { font-size: 13px; color: var(--sp-text-muted); margin: 0; flex: 1 1 auto; }

.sp-report__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-space-2); }
.sp-report__note { font-size: 11px; color: var(--sp-text-faint); }

.sp-reports__schedules { margin-bottom: var(--sp-space-5); }
.sp-report__scope { font-size: 12px; margin-top: 2px; }
.sp-report__missing { color: var(--sp-text-faint); font-style: italic; }
.sp-report__detail { font-size: 11px; color: var(--sp-text-faint); margin-top: 2px; }
.sp-report__rowactions { display: inline-flex; gap: var(--sp-space-2); justify-content: flex-end; }
.sp-report__footnote { margin-top: var(--sp-space-4); }

/* Outcome is never colour alone — the word is always there, and the colour only
   makes it findable in a long list. */
.sp-report__outcome { font-weight: 600; margin-right: var(--sp-space-2); }
.sp-report__outcome[data-outcome="Succeeded"] { color: var(--sp-resolved); }
.sp-report__outcome[data-outcome="PartiallyDelivered"] { color: var(--sp-waiting); }
.sp-report__outcome[data-outcome="Failed"] { color: var(--sp-breach); }
.sp-report__outcome[data-outcome="None"] { color: var(--sp-text-faint); }

/* Filter bar. The fields size to their content and the actions take the rest,
   so a two-control bar does not stretch a select across the whole page. */
.sp-reportbar {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--sp-space-4);
  margin-bottom: var(--sp-space-3);
}
.sp-reportbar__field { flex: 0 1 220px; margin-bottom: 0; }
.sp-reportbar__actions { display: flex; gap: var(--sp-space-2); }

.sp-reportbar__secondary {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-space-3);
  margin-bottom: var(--sp-space-5);
}
.sp-reportbar__email { display: inline; }
.sp-reportbar__scope { margin-left: auto; font-size: 12px; }

.sp-scheduleform { max-width: 720px; }
.sp-scheduleform__delete {
  max-width: 720px;
  margin-top: var(--sp-space-5);
  display: flex; align-items: center; gap: var(--sp-space-3);
}

/* ---- Help and documentation ---------------------------------------------- */

/* The contents grid on help home. */
.sp-help__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--sp-space-4); }
.sp-help__card {
  display: flex; flex-direction: column; gap: var(--sp-space-2);
  background: var(--sp-surface);
  border: 1px solid var(--sp-border);
  border-radius: var(--sp-radius);
  padding: var(--sp-space-4);
}
.sp-help__card:hover { border-color: var(--sp-accent); text-decoration: none; }
.sp-help__cardicon { font-size: 22px; line-height: 1; }
.sp-help__cardtitle { font-weight: 600; color: var(--sp-text); }
.sp-help__cardtext { font-size: 13px; color: var(--sp-text-muted); }

/* Contents, repeated beside every topic. */
.sp-help__nav { padding: var(--sp-space-4); }
.sp-help__navlist { list-style: none; margin: 0 0 var(--sp-space-3); padding: 0; display: flex; flex-direction: column; gap: 2px; }
.sp-help__navitem {
  display: flex; align-items: center; gap: var(--sp-space-2);
  padding: 6px var(--sp-space-2);
  border-radius: var(--sp-radius-sm);
  font-size: 13px; color: var(--sp-text-muted);
}
.sp-help__navitem:hover { background: var(--sp-surface-hover); color: var(--sp-text); text-decoration: none; }
.sp-help__navitem.is-active { background: var(--sp-surface-hover); color: var(--sp-text); font-weight: 500; }
.sp-help__navicon { font-size: 14px; }
.sp-help__navback { width: 100%; justify-content: center; }

/* The small "?" that opens a help page from beside a form field. Sized to sit on the
   label line without pushing it around. */
.sp-help__hint {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; margin-left: var(--sp-space-2);
  border: 1px solid var(--sp-border-strong);
  border-radius: var(--sp-radius-pill);
  font-size: 11px; font-weight: 600; line-height: 1;
  color: var(--sp-text-muted);
  vertical-align: middle;
}
.sp-help__hint:hover { border-color: var(--sp-accent); color: var(--sp-accent); text-decoration: none; }

/* Prose. Documentation is the one place in this app with running text, so the
   reading measure is capped here rather than left to the content column. */
.sp-doc { max-width: 76ch; }
.sp-doc h2 { font-size: 16px; margin-top: var(--sp-space-6); }
.sp-doc h2:first-child { margin-top: 0; }
.sp-doc h3 { font-size: 14px; margin-top: var(--sp-space-5); }
.sp-doc p, .sp-doc li { font-size: 13px; line-height: 1.65; color: var(--sp-text-muted); }
.sp-doc strong { color: var(--sp-text); font-weight: 600; }
.sp-doc ul, .sp-doc ol { margin: 0 0 var(--sp-space-3); padding-left: var(--sp-space-5); }
.sp-doc li { margin-bottom: var(--sp-space-2); }
.sp-doc code { background: var(--sp-surface); padding: 1px 5px; border-radius: var(--sp-radius-sm); }
.sp-doc .sp-table { margin-bottom: var(--sp-space-4); }
.sp-doc__lead { font-size: 14px; color: var(--sp-text); }

/* A callout for the thing on a page most likely to be got wrong. */
.sp-doc__note {
  border: 1px solid var(--sp-border);
  border-left: 3px solid var(--sp-accent);
  border-radius: var(--sp-radius-sm);
  background: var(--sp-surface);
  padding: var(--sp-space-3) var(--sp-space-4);
  margin: 0 0 var(--sp-space-4);
}
.sp-doc__note p:last-child { margin-bottom: 0; }

/* One role and the permissions it carries. */
.sp-help__role { border-top: 1px solid var(--sp-border); padding: var(--sp-space-4) 0; }
.sp-help__role:first-of-type { border-top: 0; padding-top: var(--sp-space-2); }
.sp-help__rolehead { display: flex; align-items: baseline; gap: var(--sp-space-3); flex-wrap: wrap; }
.sp-help__rolename { font-family: var(--sp-mono); font-size: 13px; font-weight: 600; color: var(--sp-text); }
.sp-help__rolesummary { font-size: 13px; color: var(--sp-text-muted); margin: var(--sp-space-2) 0; line-height: 1.6; }
.sp-help__roleuse { font-size: 12px; color: var(--sp-text-faint); margin: 0 0 var(--sp-space-3); line-height: 1.6; }

.sp-help__perms { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--sp-space-2); }
.sp-help__perm { font-size: 12px; color: var(--sp-text-muted); line-height: 1.55; }
.sp-help__permtitle { color: var(--sp-text); font-weight: 500; }
.sp-help__permkey { font-family: var(--sp-mono); font-size: 11px; color: var(--sp-text-faint); }

/* Marks a role the reader could actually hand out. Shown only when they can grant
   at least one, so it never reads as a permission they are missing. */
.sp-help__grant {
  font-size: 11px; font-weight: 600;
  color: var(--sp-resolved);
  border: 1px solid currentColor;
  border-radius: var(--sp-radius-pill);
  padding: 1px 8px;
}

@media (max-width: 900px) {
  .sp-help__nav { position: static; }
}

/* ---- Audit log ----------------------------------------------------------- */

.sp-audit__intro { display: block; margin-bottom: var(--sp-space-4); max-width: 76ch; }
.sp-audit__truncated { margin-bottom: var(--sp-space-4); }
.sp-audit__source { font-size: 12px; }

/* Two rows rather than one: six controls wrapping mid-line read as a pile
   rather than a form. */
.sp-audit__filters { display: flex; flex-direction: column; gap: var(--sp-space-3); }
.sp-audit__row { display: flex; gap: var(--sp-space-3); align-items: center; flex-wrap: wrap; }
.sp-audit__date { display: flex; align-items: center; gap: var(--sp-space-2); }
.sp-audit__date .sp-input { width: auto; }
.sp-audit__check { margin: 0; }
.sp-audit__zone { display: block; }

@media (max-width: 720px) {
  .sp-audit__row { align-items: stretch; flex-direction: column; }
  /* Stacked, a flex-basis is a height: the search box's 220px basis left a gap under it. */
  .sp-audit__filters > *, .sp-audit__row > * { flex: 0 0 auto; }
  .sp-audit__date .sp-input { width: 100%; }
  .sp-audit__date .sp-label { flex: 0 0 40px; }
}

/* ---- Collapsible integration section (Settings → Integrations) ---------- */

/* A <details> styled as a card whose header is the toggle. The cards inside
   keep their spacing but lose their own border, so it reads as one panel. */
.sp-integration { padding: 0; }
.sp-integration__summary {
  display: flex; align-items: center; gap: var(--sp-space-3);
  padding: var(--sp-space-4) var(--sp-space-5);
  cursor: pointer;
  user-select: none;
  list-style: none;
  border-radius: var(--sp-radius);
}
.sp-integration__summary::-webkit-details-marker { display: none; }
.sp-integration__summary:hover { background: var(--sp-surface-hover); }
.sp-integration__summary:focus-visible { outline: 2px solid var(--sp-accent-text); outline-offset: -2px; }
.sp-integration[open] > .sp-integration__summary { border-bottom: 1px solid var(--sp-border); border-radius: var(--sp-radius) var(--sp-radius) 0 0; }

.sp-integration__chevron {
  width: 7px; height: 7px; flex: none;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg);
  transition: transform 120ms ease;
}
.sp-integration[open] .sp-integration__chevron { transform: rotate(45deg); }

.sp-integration__status {
  font-size: 11px; font-weight: 600;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid currentColor;
}
.sp-integration__status--ok { color: var(--sp-resolved); }
.sp-integration__status--warn { color: var(--sp-waiting); }
.sp-integration__status--error { color: var(--sp-breach); }
.sp-integration__status--muted { color: var(--sp-text-muted); }
.sp-integration__account { font-size: 13px; margin-left: auto; }

.sp-integration__body { padding: var(--sp-space-2) var(--sp-space-5) var(--sp-space-5); }
.sp-integration__body > .sp-card,
.sp-integration__body > form.sp-card {
  border: none; border-radius: 0; padding: var(--sp-space-4) 0 0; background: transparent;
}
.sp-integration__body > .sp-card + .sp-card,
.sp-integration__body > .sp-card + form.sp-card,
.sp-integration__body > form.sp-card + .sp-card {
  border-top: 1px solid var(--sp-border); margin-top: var(--sp-space-4);
}
.sp-integration__body > .sp-alert { margin-top: var(--sp-space-4); }

@media (max-width: 600px) {
  .sp-integration__summary { flex-wrap: wrap; }
  .sp-integration__account { margin-left: 0; flex-basis: 100%; }
}

/* Stacked integration sections, and the NinjaOne import's progress list. */
.sp-integration + .sp-integration { margin-top: var(--sp-space-4); }
.sp-integration__progress {
  list-style: none; margin: 0 0 var(--sp-space-3); padding: 0;
  display: flex; flex-wrap: wrap; gap: var(--sp-space-2) var(--sp-space-5);
  font-size: 13px; color: var(--sp-text-muted);
}
.sp-integration__progress strong { color: var(--sp-text); font-variant-numeric: tabular-nums; }
