/* ==========================================================================
   Obala Customer Portal — design system.
   Reuses the marketing site's visual language (obala.cloud): charcoal canvas,
   orange accent, Outfit 600/400, 16px cards / 10px controls, thin orange rules.
   No inline scripts/styles anywhere — the CSP stays script-src 'self'.
   ========================================================================== */

:root {
  --charcoal:    #111317;
  --orange:      #FF6A00;
  --orange-hi:   #ff8226;   /* hover */
  --orange-lo:   #ef6400;   /* active */
  --off-white:   #F6F6F4;
  --warm-grey:   #E2DED9;
  --muted:       #8D95A3;
  --surface:     #1a1e24;   /* raised panels / cards */
  --line:        #2a303b;   /* hairline borders */
  --line-hi:     #3a4250;   /* hover borders */
  --sidebar-bg:  #14171c;   /* app sidebar / bars */

  --danger:      #ff5a52;   /* destructive-action tint (kept off the brand core) */

  --radius-card: 16px;
  --radius-ctrl: 10px;
  --radius-pill: 999px;

  --sidebar-w:   248px;
  --content-max: 1100px;

  --focus: 2px solid var(--orange);

  --shadow-pop: 0 18px 44px rgba(0, 0, 0, 0.5);

  --font: "Outfit", Arial, Helvetica, sans-serif;

  /* Visual layer scale — the single source of truth for stacking. Components
     reference these tokens; no ad-hoc escalating z-index values anywhere.
     base < sticky topbar < mobile scrim < sidebar < action menu < toast < skip-link. */
  --z-base:     1;
  --z-topbar:   40;
  --z-scrim:    55;
  --z-sidebar:  60;
  --z-menu:     80;
  --z-toast:    120;
  --z-skiplink: 200;

  /* Spacing scale — the single source of truth for layout rhythm. Semantic
     tokens below reference it so peer surfaces never rely on accidental
     adjacent-sibling margins. */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --stack-gap: var(--space-5);   /* 24px vertical rhythm between top-level surfaces */

  /* Control geometry — the single source of truth for anything that shares a row.
     Every full-height control resolves to --ctrl-h, so a select, a text input and a
     button on the same line are the same height by construction rather than by luck. */
  --ctrl-h:      2.5rem;    /* 40px at the 16px root */
  --ctrl-h-touch: 2.75rem;  /* 44px — the WCAG 2.2 AA target floor, used below 768px */
  --ctrl-pad-y:  0.5rem;
  --ctrl-pad-x:  0.9rem;

  /* A filter cell is a one-line label above a control. --label-block is the exact
     height that label row occupies (line box + gap), which is what lets a cell with no
     label — an action group, a checkbox — offset itself by the same amount and still
     land on the shared control row. It is a derived token, never a guessed nudge. */
  --label-size:  0.85rem;
  --label-lh:    1.4;
  --label-gap:   var(--space-1);
  --label-block: calc(var(--label-size) * var(--label-lh) + var(--label-gap));

  --flt-basis:   11rem;     /* preferred filter-cell width before wrapping */
  --flt-basis-lookup: 16rem;/* a combobox cell carries more text, so it starts wider */
}

/* Self-hosted Outfit variable font (latin subset; 400 + 600 axis) */
@font-face {
  font-family: "Outfit";
  src: url("/portal/static/fonts/outfit-latin-variable.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

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

/* The `hidden` attribute must always win. A component class that sets its own `display`
   — `.btn` is `inline-flex` — has higher specificity than the user-agent
   `[hidden] { display: none }` rule, so a hidden button stayed visible. That defect
   showed an enabled "Clear" control on every bounded lookup with nothing selected. */
[hidden] { display: none !important; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--charcoal);
  color: var(--off-white);
  font-family: var(--font);
  font-weight: 400;
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 { font-weight: 600; letter-spacing: -0.01em; color: var(--off-white); }
h1 { font-size: 1.7rem; line-height: 1.15; margin: 0 0 0.5rem; }
h2 { font-size: 1.2rem; margin: 0 0 0.9rem; }
h3 { font-size: 1.02rem; margin: 0 0 0.5rem; }
p { margin: 0 0 0.8rem; }

a { color: var(--orange); text-decoration: none; }
/* Links embedded in running/muted text must not rely on colour alone (WCAG 1.4.1):
   underline them so they're distinguishable from the surrounding copy. */
.auth-foot a, .muted a, p a { text-decoration: underline; text-underline-offset: 2px; }
a:hover { text-decoration: underline; }

:focus-visible { outline: var(--focus); outline-offset: 3px; border-radius: 4px; }

.muted { color: var(--muted); }
.warm  { color: var(--warm-grey); }
.nowrap { white-space: nowrap; }
.mono  { font-variant-numeric: tabular-nums; }

/* Layout utilities (keeps templates free of inline styles) */
.narrow { max-width: 560px; }
.measure { max-width: 640px; }
.mt-0 { margin-top: 0; }
.mt-2 { margin-top: 1.25rem; }
.cap { text-transform: capitalize; }
.tac { text-align: center; }

/* Inside a dense filter bar the bounded lookup's STATIC help sentence is moved to the
   accessibility layer only. It remains in the DOM, remains the input's `aria-describedby`
   target and is still announced; what it stops doing is repeating the same fixed sentence
   beside every combobox in a bar that can hold thirteen filters. The equivalent guidance
   reaches a sighted operator from the live status line at the moment it applies ("Type at
   least 2 characters", "Showing the first 20 matches"), which is more useful than
   permanent boilerplate. Outside a filter bar — on a form, where vertical space is not
   contested — the sentence stays visible. */
.sr-only,
.filters .lookup-help {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Skip link ---------------------------------------------------------------- */
.skip-link {
  position: fixed;
  top: 10px; left: 10px;
  z-index: var(--z-skiplink);
  transform: translateY(-160%);
  padding: 0.6rem 1rem;
  background: var(--orange);
  color: var(--charcoal);
  font-weight: 600;
  border-radius: var(--radius-ctrl);
  transition: transform 0.18s ease;
}
.skip-link:focus { transform: none; text-decoration: none; }

/* ==========================================================================
   Kicker / section rhythm
   ========================================================================== */
.kicker {
  margin: 0 0 0.6rem;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--orange);
}

.lead { color: var(--warm-grey); font-size: 1rem; }

/* Thin orange rule echoing the brand composition */
.rule {
  width: 56px; height: 2px;
  background: var(--orange);
  border: 0;
  margin: 1rem 0 1.25rem;
}

/* ==========================================================================
   Buttons
   ========================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  font-family: inherit;
  font-weight: 600;
  font-size: 0.92rem;
  letter-spacing: 0.01em;
  line-height: 1;
  padding: 0.78rem 1.3rem;
  min-height: 42px;
  border: 0;
  border-radius: var(--radius-ctrl);
  background: none;
  color: var(--off-white);
  text-decoration: none;
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease, transform 0.05s ease;
}
.btn:hover { text-decoration: none; }
.btn:active { transform: translateY(1px); }

.btn-primary { background: var(--orange); color: var(--charcoal); }
.btn-primary:hover { background: var(--orange-hi); }
.btn-primary:active { background: var(--orange-lo); }

.btn-ghost {
  padding: calc(0.78rem - 1px) calc(1.3rem - 1px);
  border: 1px solid rgba(141, 149, 163, 0.45);
  color: var(--warm-grey);
}
.btn-ghost:hover { color: var(--off-white); border-color: var(--muted); }

.btn-danger {
  padding: calc(0.78rem - 1px) calc(1.3rem - 1px);
  border: 1px solid rgba(255, 90, 82, 0.5);
  color: var(--danger);
}
.btn-danger:hover { color: #fff; background: rgba(255, 90, 82, 0.14); border-color: var(--danger); }

.btn-sm { padding: 0.5rem 0.85rem; min-height: 36px; font-size: 0.82rem; }
.btn-block { width: 100%; }

.btn .icon { width: 18px; height: 18px; }

/* ==========================================================================
   App shell — sidebar + topbar + content
   ========================================================================== */
.app { min-height: 100vh; }

.sidebar {
  position: fixed;
  inset: 0 auto 0 0;
  width: var(--sidebar-w);
  display: flex;
  flex-direction: column;
  background: var(--sidebar-bg);
  border-right: 1px solid var(--line);
  z-index: var(--z-sidebar);
}

.sidebar-head {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 1.15rem 1.25rem;
  min-height: 64px;
  border-bottom: 1px solid var(--line);
}
.sidebar-head .mark { width: 30px; height: 30px; display: block; flex: none; }
.sidebar-head .wordmark {
  font-weight: 600; font-size: 1.25rem; letter-spacing: 0.01em; color: var(--off-white);
}

.sidebar-scroll {
  flex: 1;
  overflow-y: auto;
  padding: 0.9rem 0.75rem 1.25rem;
}

/* Nav grouping */
.nav-group-label {
  margin: 1.1rem 0 0.4rem;
  padding: 0 0.85rem;
  font-size: 0.65rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
}

.nav { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }

.nav-link {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.6rem 0.85rem;
  min-height: 42px;
  border-radius: var(--radius-ctrl);
  color: var(--warm-grey);
  font-size: 0.92rem;
  font-weight: 400;
  transition: background 0.15s ease, color 0.15s ease;
}
.nav-link:hover { background: rgba(255, 255, 255, 0.04); color: var(--off-white); text-decoration: none; }
.nav-link .icon { width: 19px; height: 19px; flex: none; color: var(--muted); transition: color 0.15s ease; }
.nav-link:hover .icon { color: var(--warm-grey); }
.nav-link .label { flex: 1; min-width: 0; }

/* Active item: orange left marker + tint */
.nav-link.is-active {
  background: rgba(255, 106, 0, 0.12);
  color: var(--off-white);
  font-weight: 600;
  box-shadow: inset 3px 0 0 var(--orange);
}
.nav-link.is-active .icon { color: var(--orange); }

/* "Soon" pill on locked features */
.soon {
  flex: none;
  padding: 0.12rem 0.5rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}
.nav-link:hover .soon { border-color: rgba(255, 106, 0, 0.5); color: var(--warm-grey); }

/* Expandable Console group */
.nav-parent {
  width: 100%;
  background: none;
  border: 0;
  cursor: pointer;
  font-family: inherit;
  text-align: left;
}
.nav-parent .chev {
  width: 16px; height: 16px; flex: none; color: var(--muted);
  transition: transform 0.2s ease;
}
.nav-parent[aria-expanded="true"] .chev { transform: rotate(90deg); }

.nav-sub {
  list-style: none;
  margin: 2px 0 2px;
  padding: 0 0 0 0.5rem;
  display: none;
  flex-direction: column;
  gap: 1px;
  border-left: 1px solid var(--line);
  margin-left: 1.35rem;
}
.nav-parent[aria-expanded="true"] + .nav-sub { display: flex; }

.nav-sub .nav-link { padding: 0.5rem 0.75rem; min-height: 38px; font-size: 0.86rem; }
.nav-sub .nav-link .dot {
  width: 5px; height: 5px; border-radius: 50%; background: var(--line); flex: none;
}
.nav-sub .nav-link:hover .dot,
.nav-sub .nav-link.is-active .dot { background: var(--orange); }

/* No-JS fallback: expose submenu so links are always reachable */
.no-js .nav-parent + .nav-sub { display: flex; }
.no-js .nav-parent .chev { display: none; }

/* Main column ------------------------------------------------------------- */
.main {
  margin-left: var(--sidebar-w);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.topbar {
  position: sticky;
  top: 0;
  z-index: var(--z-topbar);
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0 clamp(1.25rem, 3vw, 2.5rem);
  min-height: 64px;
  background: rgba(17, 19, 23, 0.85);
  border-bottom: 1px solid var(--line);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
/* the heading can hold arbitrary user content (a long name); truncate in the
   fixed-height bar instead of forcing the top bar (and the page) wider */
.topbar-title { margin: 0; font-size: 1.05rem; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.topbar-spacer { flex: 1; }

/* Hamburger (mobile only) */
.nav-toggle {
  display: none;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 44px; height: 44px;
  margin-left: -0.5rem;
  padding: 0;
  border: 0;
  border-radius: var(--radius-ctrl);
  background: transparent;
  color: var(--off-white);
  cursor: pointer;
}
.nav-toggle:hover { background: rgba(255, 255, 255, 0.06); }
.nav-toggle .icon { width: 22px; height: 22px; }

/* Profile menu ------------------------------------------------------------ */
.profile { position: relative; flex: none; }
.profile-btn {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.35rem 0.6rem 0.35rem 0.4rem;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--off-white);
  font-family: inherit;
  font-size: 0.88rem;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.profile-btn:hover { background: rgba(255, 255, 255, 0.05); border-color: var(--line); }

.avatar {
  flex: none;
  display: grid;
  place-items: center;
  width: 34px; height: 34px;
  border-radius: 50%;
  background: rgba(255, 106, 0, 0.16);
  color: var(--orange);
  border: 1px solid rgba(255, 106, 0, 0.4);
  font-weight: 600;
  font-size: 0.8rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.profile-meta { display: flex; flex-direction: column; align-items: flex-start; line-height: 1.15; }
.profile-name { font-weight: 600; }
.profile-btn .chev { width: 14px; height: 14px; color: var(--muted); }

.role-badge {
  display: inline-block;
  padding: 0.05rem 0.5rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
}
.role-badge.is-staff { color: var(--orange); border-color: rgba(255, 106, 0, 0.45); }

/* Dropdown */
.menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 220px;
  padding: 0.4rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow-pop);
  display: none;
  z-index: var(--z-menu);
}
.profile.open .menu { display: block; }
/* No-JS fallback: reveal on keyboard focus within */
.no-js .profile:focus-within .menu { display: block; }

.menu-head {
  padding: 0.55rem 0.7rem 0.7rem;
  border-bottom: 1px solid var(--line);
  margin-bottom: 0.35rem;
}
.menu-head .n { font-weight: 600; }
.menu-head .e { font-size: 0.8rem; color: var(--muted); word-break: break-all; }

.menu-item {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  width: 100%;
  padding: 0.6rem 0.7rem;
  border: 0;
  border-radius: var(--radius-ctrl);
  background: none;
  color: var(--warm-grey);
  font-family: inherit;
  font-size: 0.9rem;
  text-align: left;
  cursor: pointer;
}
.menu-item:hover { background: rgba(255, 255, 255, 0.05); color: var(--off-white); text-decoration: none; }
.menu-item .icon { width: 17px; height: 17px; color: var(--muted); }
.menu form { margin: 0; }
.menu-sep { height: 1px; background: var(--line); margin: 0.35rem 0; border: 0; }

/* Content ----------------------------------------------------------------- */
.content {
  flex: 1;
  padding: clamp(1.5rem, 3vw, 2.5rem) clamp(1.25rem, 3vw, 2.5rem) 3rem;
}
/* The content column is a controlled vertical stack: EVERY top-level surface
   (page-head, cards, grids, table wraps, alerts) is separated by one consistent
   gap, regardless of element type — so peer surfaces never touch just because
   they aren't two adjacent .card siblings. */
.content-inner {
  max-width: var(--content-max);
  margin: 0 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--stack-gap);
}
/* Neutralise legacy per-surface margins on direct children so the stack gap is
   the single source of vertical rhythm (no doubling with the flex gap). */
.content-inner > .page-head,
.content-inner > .flash-stack,
.content-inner > .stat-grid { margin-bottom: 0; }
.content-inner > .card + .card { margin-top: 0; }

.page-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
  margin-bottom: 1.5rem;
}
.page-head .titles { min-width: 0; }
.page-head h1 { margin: 0; }
.page-head .sub { margin: 0.25rem 0 0; color: var(--muted); }
.page-actions { display: flex; gap: 0.6rem; flex-wrap: wrap; }

/* ==========================================================================
   Cards
   ========================================================================== */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  padding: clamp(1.25rem, 2.5vw, 1.75rem);
}
.card + .card { margin-top: 1.25rem; }
.card-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-bottom: 1rem; }
.card-head h2 { margin: 0; }
.card-rule::before {
  content: ""; display: block; width: 40px; height: 2px;
  background: var(--orange); margin-bottom: 1.1rem;
}

.grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.25rem; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.25rem; }
/* long values must never force a grid column wider than its track */
.grid-2 > *, .grid-3 > * { min-width: 0; }

/* ==========================================================================
   Forms
   ========================================================================== */
.field { margin: 0 0 1.1rem; }
.field:last-child { margin-bottom: 0; }
.field > label,
.field-label {
  display: block;
  margin-bottom: 0.4rem;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--warm-grey);
}
.field .req { color: var(--orange); margin-left: 0.15em; }

.field input,
.field select,
.field textarea,
input[type="text"], input[type="email"], input[type="password"],
input[type="tel"], input[type="search"], input[type="date"], select, textarea {
  width: 100%;
  padding: 0.72rem 0.9rem;
  background: var(--charcoal);
  border: 1px solid var(--line);
  border-radius: var(--radius-ctrl);
  font-family: inherit;
  font-size: 0.95rem;
  font-weight: 400;
  color: var(--off-white);
  transition: border-color 0.18s ease, box-shadow 0.18s ease;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--orange);
  box-shadow: 0 0 0 3px rgba(255, 106, 0, 0.18);
}
input::placeholder, textarea::placeholder { color: var(--muted); opacity: 1; }
textarea { resize: vertical; min-height: 120px; line-height: 1.55; }

/* Native select gets a brand chevron */
select {
  padding-right: 2.6rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%238D95A3' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.9rem center;
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
}

/* Native date control -------------------------------------------------------------------
   The shared rule above now gives it the Obala surface, border, radius, padding, font and
   colour. What the shared rule cannot reach is the part the user agent draws for itself: the
   calendar indicator glyph and the drop-down picker. Those are rendered from the element's
   COLOUR SCHEME, not from its background, so a dark field still received a dark-on-light glyph
   and a light picker.

   `color-scheme: dark` is the standards-based fix and is declared at the narrowest scope that
   works — on the control itself, never on :root, so nothing else on the page changes its
   rendering. No image, no external icon, no JavaScript picker, and no filter on the indicator:
   a filter would need per-engine evidence to justify, and this does not.

   Certified in Microsoft Edge, Chromium, Firefox and WebKit; see
   DATE-CONTROL-VISUAL-SEMANTICS-AFTER.json. Under forced colours the system override takes
   over, which is correct and is verified separately rather than fought. */
input[type="date"] {
  color-scheme: dark;
}

input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"] {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px rgba(255, 90, 82, 0.16);
}

fieldset {
  margin: 0 0 1.1rem;
  padding: 1rem 1.1rem 0.3rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-ctrl);
}
fieldset legend {
  padding: 0 0.4rem;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--warm-grey);
}

/* Inline checkbox */
.check {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  cursor: pointer;
  font-size: 0.9rem;
  color: var(--warm-grey);
}
/* A checkbox is never a full-width control. `flex: none` and the explicit box keep it
   18px regardless of any width or min-width rule that applies to inputs generally — the
   defect this replaces rendered these as 150px squares inside filter bars, because a
   later `.filters input` rule of equal specificity won the cascade. Selecting the type
   directly means no ancestor rule can stretch it again. */
.check input[type="checkbox"],
.check input[type="radio"],
.checkline input[type="checkbox"],
.checkline input[type="radio"] {
  flex: none;
  width: 18px;
  min-width: 18px;
  max-width: 18px;
  height: 18px;
  margin: 0;
  padding: 0;
  accent-color: var(--orange);
}

.field-note { margin: 0.4rem 0 0; font-size: 0.8rem; color: var(--muted); }
.field-hint { margin: 0.4rem 0 0; font-size: 0.8rem; color: var(--danger); }
.field-row { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0 1rem; }
.form-error {
  margin: 0 0 0.9rem;
  padding: 0.55rem 0.75rem;
  font-size: 0.82rem;
  color: var(--danger);
  border: 1px solid rgba(255,90,82,0.5);
  border-radius: var(--radius-ctrl);
  background: rgba(255,90,82,0.08);
}
.classify-status { margin: 0.2rem 0 0; font-size: 0.8rem; }

/* Audit Trails */
/* `.filters-wrap` removed: `.filters` now wraps with an explicit row gap for every
   filter region, so the per-page override had nothing left to add. */
.json-block {
  margin: 0.6rem 0 0;
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-ctrl);
  background: rgba(0,0,0,0.25);
  font-size: 0.78rem;
  line-height: 1.5;
  overflow-x: auto;
  white-space: pre-wrap;
  word-break: break-word;
}
.inline-h2 { display: inline; font-size: 1rem; }
details > summary { cursor: pointer; }

/* --- Interaction-state components (Release 4) --------------------------- */
/* Busy submit button: truthful spinner, no fake percentage. */
.btn.is-busy { position: relative; opacity: 0.85; }
.btn.is-busy::before {
  content: "";
  display: inline-block;
  width: 0.85em; height: 0.85em;
  margin-right: 0.5em;
  vertical-align: -0.1em;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: obala-spin 0.7s linear infinite;
}
@keyframes obala-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  /* No spin under reduced motion — show a static "working" glyph instead. */
  .btn.is-busy::before { animation: none; border-top-color: currentColor; border-radius: 2px; }
}
/* Page/section state notices — text-led; icon + border reinforce, never colour alone. */
.state-notice {
  display: flex; gap: 0.6rem; align-items: flex-start;
  padding: 0.75rem 0.9rem; margin: 0 0 1rem;
  border: 1px solid var(--line); border-left-width: 3px; border-radius: var(--radius-ctrl);
  background: rgba(255,255,255,0.02);
}
.state-notice .icon { flex: none; width: 18px; height: 18px; margin-top: 0.1rem; }
.state-notice strong { display: block; }
.state-error       { border-left-color: var(--danger); }
.state-conflict    { border-left-color: var(--orange); }
.state-rate_limited{ border-left-color: var(--orange); }
.state-unavailable { border-left-color: var(--orange); }
.state-warning     { border-left-color: var(--warm-grey); }

.form-actions { display: flex; gap: 0.7rem; flex-wrap: wrap; margin-top: 1.25rem; align-items: center; }

/* Pagination + bounded lookup (Administrative Scalability v1) ---------------- */
/* Text carries every meaning here: the range, the total, the result count and the
   disabled state are all readable without relying on colour, and the whole control set
   is plain links, inputs and buttons so it works with JavaScript unavailable. */
.list-foot {
  display: flex; flex-wrap: wrap; gap: 0.9rem 1.4rem;
  align-items: center; justify-content: space-between;
  margin-top: var(--stack-gap);
}
.pager { display: flex; flex-wrap: wrap; gap: 0.5rem 1rem; align-items: center; }
.pager-range { margin: 0; }
.pager-controls { display: flex; gap: 0.4rem; list-style: none; margin: 0; padding: 0; flex-wrap: wrap; }
/* A disabled control is announced via aria-disabled and dimmed; it is not a link, so it
   is skipped by keyboard navigation rather than focusable-but-inert. */
.btn.is-disabled { opacity: 0.5; cursor: default; }
.page-size { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; }
.page-size label { margin: 0; white-space: nowrap; }
/* A two- or three-digit row count needs a control sized for a two- or three-digit row
   count. The generic `select { width: 100% }` rule left this stretching to fill the
   footer row, which read as a broken, oversized box beside a short label. */
.page-size select { width: auto; min-width: 5rem; min-height: var(--ctrl-h); }
/* The label text may wrap on a narrow phone; only the box-and-text pair is kept together.
   `nowrap` here previously pushed "Protected / system only" past the filter bar's edge. */
.checkline { display: inline-flex; gap: 0.45rem; align-items: center; }

/* Bounded lookup ------------------------------------------------------------------
   The control is a stack: label, the combobox itself, the authoritative id, the help
   line, the current selection and one live status line. Only the LABEL and the SEARCH
   BOX participate in the filter row's shared alignment; everything below hangs beneath
   the row, which is why the stack no longer sets the row's height. */
.lookup {
  display: flex; flex-direction: column; gap: var(--label-gap);
  flex: 1 1 var(--flt-basis-lookup);
  /* Capped so the cell cannot absorb all the spare room on a wide row: an 800px-wide
     search box for a person's name is disproportionate, and it also forced the result
     panel to be narrower than its own field. */
  max-width: 26rem;
  min-width: 0;
}
.lookup > label { margin: 0; }
/* The popup anchors to THIS element — the search box — not to the whole stack. Anchoring
   it to `.lookup` made it open 152px lower than the field it belongs to, level with the
   help text, which read as a detached panel floating over the next control. */
.lookup-combo { position: relative; display: block; }
.lookup-combo .lookup-search { width: 100%; }
/* The id field carries the authoritative value, so it is labelled and visible rather than
   hidden. Its label is set smaller than the field label because it is secondary
   information — but it stays a real, visible label: an unnamed focusable input was a
   critical axe `label` violation in the first cut of this control. */
.lookup-meta {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--space-1) var(--space-2);
  font-size: 0.82rem;
}
.lookup-idlabel { margin: 0; color: var(--muted); white-space: nowrap; }
/* `input.` rather than `.` — the generic `input[type="text"] { width: 100% }` rule is an
   attribute selector and therefore outranked a bare class, so the id field rendered at
   the full cell width and pushed Clear onto a line of its own. */
input.lookup-value {
  flex: none;
  width: 5.5rem;
  min-width: 0;
  max-width: 100%;
  min-height: 2rem;
  padding: 0.3rem 0.55rem;
  font-variant-numeric: tabular-nums;
}
.lookup-meta .btn { min-height: 2rem; padding: 0.2rem 0.6rem; }
.lookup-help, .lookup-current, .lookup-status { margin: 0; font-size: 0.82rem; }
/* The persistent selection statement and the transient live status share one line: only
   one of them is ever the thing the operator is reading, and giving each its own line
   made the composite cell tower over the plain controls beside it. */
.lookup-foot {
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: 0 var(--space-2);
  /* Reserved height, so a result count appearing does not shift the layout under the
     pointer or the caret. */
  min-height: 1.25em;
}
/* Long organisation and person names wrap inside the cell rather than widening it. */
.lookup-current { min-width: 0; overflow-wrap: break-word; }
.lookup-list {
  position: absolute; z-index: var(--z-menu);
  top: calc(100% + 0.25rem); left: 0;
  /* At least as wide as the field, never narrower, and never wider than the viewport.
     The cap matches the cell's own max-width, so the panel and the field it belongs to
     are always the same width — a panel narrower than its field reads as a mispositioned
     overlay rather than as part of the control. */
  width: max(100%, 14rem);
  max-width: min(26rem, calc(100vw - 2 * var(--space-4)));
  margin: 0; padding: 0.25rem; list-style: none;
  max-height: 17rem; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-ctrl);
  box-shadow: var(--shadow-pop);
}
/* A long label or e-mail wraps inside the option instead of forcing the panel wider. */
.lookup-option-label, .lookup-option-detail { overflow-wrap: break-word; min-width: 0; }
.lookup-option {
  display: flex; flex-direction: column; gap: 0.1rem;
  padding: 0.45rem 0.6rem; border-radius: 4px; cursor: pointer;
}
.lookup-option-detail { font-size: 0.82rem; }
/* The active option is marked by background AND a left border, so it remains visible in
   forced-colours mode where background may be overridden. */
.lookup-option.is-active,
.lookup-option[aria-selected="true"] {
  background: var(--surface-2, rgba(255, 255, 255, 0.06));
  box-shadow: inset 3px 0 0 var(--orange);
}
@media (forced-colors: active) {
  .lookup-option.is-active,
  .lookup-option[aria-selected="true"] { forced-color-adjust: none; outline: 2px solid Highlight; }
  .btn.is-disabled { opacity: 1; color: GrayText; }
}

/* Inline alert inside a form/card */
.alert {
  display: flex;
  gap: 0.6rem;
  padding: 0.8rem 1rem;
  border-radius: var(--radius-ctrl);
  font-size: 0.9rem;
  margin-bottom: 1.1rem;
  border: 1px solid;
}
.alert .icon { flex: none; width: 18px; height: 18px; margin-top: 1px; }
.alert-error { color: #ffd7cd; background: rgba(255, 90, 82, 0.1); border-color: rgba(255, 90, 82, 0.5); }
.alert-info  { color: var(--warm-grey); background: rgba(255, 106, 0, 0.08); border-color: rgba(255, 106, 0, 0.4); }

/* ==========================================================================
   Flash messages (top of content)
   ========================================================================== */
.flash-stack { display: flex; flex-direction: column; gap: 0.7rem; margin-bottom: 1.4rem; }
.flash-stack-auth { max-width: 440px; width: 100%; margin: 0 auto 1.4rem; }
.flash {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  padding: 0.85rem 1rem;
  background: var(--surface);
  border: 1px solid rgba(255, 106, 0, 0.45);
  border-left: 3px solid var(--orange);
  border-radius: var(--radius-ctrl);
  color: var(--off-white);
}
.flash .icon { flex: none; width: 19px; height: 19px; color: var(--orange); margin-top: 1px; }
.flash p { margin: 0; word-break: break-word; }
.flash-dismiss {
  margin-left: auto;
  flex: none;
  border: 0; background: none; color: var(--muted);
  cursor: pointer; padding: 0.15rem; border-radius: 6px;
}
.flash-dismiss:hover { color: var(--off-white); }
.flash-dismiss .icon { width: 15px; height: 15px; color: currentColor; margin: 0; }

/* ==========================================================================
   Chips (status / severity / generic)
   ========================================================================== */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.22rem 0.65rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: var(--warm-grey);
  text-transform: capitalize;
  white-space: nowrap;
}
.chip .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--muted); flex: none; }

/* Status */
.st-open            { border-color: rgba(255,106,0,0.5); color: #ffd3b0; }
.st-open .dot       { background: var(--orange); }
.st-in_progress     { border-color: rgba(226,222,217,0.4); color: var(--warm-grey); }
.st-in_progress .dot{ background: var(--warm-grey); }
.st-waiting_customer{ border-color: rgba(255,106,0,0.35); color: var(--warm-grey); }
.st-waiting_customer .dot { background: #b9752f; }
.st-resolved        { color: var(--muted); }
.st-resolved .dot   { background: #6f9a6a; }
.st-closed          { color: var(--muted); opacity: 0.85; }
.st-closed .dot     { background: var(--muted); }

/* Severity — escalating orange intensity, brand-consistent */
.sev-low      { color: var(--muted); }
.sev-low .dot { background: var(--muted); }
.sev-medium      { color: var(--warm-grey); border-color: rgba(226,222,217,0.4); }
.sev-medium .dot { background: var(--warm-grey); }
.sev-high      { color: #ffb27a; border-color: rgba(255,106,0,0.55); }
.sev-high .dot { background: var(--orange); }
.sev-critical  { background: var(--orange); color: var(--charcoal); border-color: var(--orange); }
.sev-critical .dot { background: var(--charcoal); }

/* Org status */
.os-pending   { border-color: rgba(255,106,0,0.5); color: #ffd3b0; }
.os-pending .dot { background: var(--orange); }
.os-approved  { color: #a9d3a2; border-color: rgba(111,154,106,0.5); }
.os-approved .dot { background: #6f9a6a; }
.os-suspended { color: var(--danger); border-color: rgba(255,90,82,0.5); }
.os-suspended .dot { background: var(--danger); }
.os-declined { color: var(--muted); border-style: dashed; }
.os-declined .dot { background: var(--muted); }

/* User status */
.us-active { color: #a9d3a2; border-color: rgba(111,154,106,0.5); }
.us-active .dot { background: #6f9a6a; }
.us-disabled { color: var(--muted); }
.us-disabled .dot { background: var(--muted); }
.us-deleted { color: var(--muted); border-style: dashed; text-decoration: line-through; }
.us-deleted .dot { background: var(--danger); }

/* Forced-colours (Windows High Contrast): map text to system colours so the
   design-system's custom greys/accents never fight the forced palette — text
   then keeps guaranteed system contrast (Canvas/CanvasText, LinkText, Highlight)
   across the shared chrome and every page. Colour-only; mode-gated; no normal-
   mode or layout impact. Destructive/alert affordances get an explicit border
   so they stay perceivable when the accent fill is neutralised. */
@media (forced-colors: active) {
  /* Universal reset to the forced system palette: every element gets Canvas
     background + CanvasText foreground + CanvasText borders, so text always has
     guaranteed system contrast regardless of the author colours it uses in
     normal mode. Interactive elements stay distinguishable via LinkText and
     borders. This is the intended High-Contrast presentation. */
  body *, body *::before, body *::after {
    background-color: Canvas !important;
    color: CanvasText !important;
    border-color: CanvasText !important;
  }
  a, a *, .nav-link, .nav-link * { color: LinkText !important; }
  .nav-link.is-active, .nav-link.is-active * { color: Highlight !important; }
  .btn, .badge, .chip, .role-badge, .alert, .card, .field input,
  .field select, .field textarea { border: 1px solid CanvasText !important; }
}

/* ==========================================================================
   Operational classification badges (severity + priority)
   Text-led: the word/number is always the primary signal — colour only
   reinforces it. Distinguishable without colour, contained at 320px and 200%
   zoom, and readable under forced-colours.
   ========================================================================== */
.badge {
  display: inline-flex;
  align-items: baseline;
  gap: 0.35rem;
  padding: 0.2rem 0.6rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--warm-grey);
  white-space: nowrap;
  max-width: 100%;
}
.badge .badge-k {
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}
/* Unclassified — deliberately muted + dashed so it never reads as a real level */
.opsev-unclassified, .pri-unclassified { color: var(--muted); border-style: dashed; }
/* Severity — escalating orange intensity (mirrors .sev-* chips) */
.opsev-informational { color: var(--muted); }
.opsev-low     { color: var(--warm-grey); }
.opsev-medium  { color: var(--warm-grey); border-color: rgba(226,222,217,0.4); }
.opsev-high    { color: #ffb27a; border-color: rgba(255,106,0,0.55); }
.opsev-critical{ background: var(--orange); color: var(--charcoal); border-color: var(--orange); }
.opsev-critical .badge-k { color: var(--charcoal); }
/* Priority — escalating urgency */
.pri-p4 { color: var(--muted); }
.pri-p3 { color: var(--warm-grey); }
.pri-p2 { color: #ffb27a; border-color: rgba(255,106,0,0.55); }
.pri-p1 { background: var(--orange); color: var(--charcoal); border-color: var(--orange); }
.pri-p1 .badge-k { color: var(--charcoal); }
@media (forced-colors: active) {
  .badge { border: 1px solid ButtonBorder; color: ButtonText; }
  .badge .badge-k { color: ButtonText; }
}

/* ==========================================================================
   Tables / data grids
   ========================================================================== */
.table-wrap {
  /* position: relative makes this the containing block for its absolutely
     positioned descendants. Without it a visually-hidden .sr-only span inside a
     wide table escaped the wrapper's clip (an absolute box is not clipped by a
     static ancestor), landed on the initial containing block, and pushed the whole
     PAGE into horizontal scroll — 1133px of it at 360px wide on the audit trail. */
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  /* overflow-x: auto, never hidden. With `overflow: hidden` a table a few pixels
     wider than its container lost its last column silently — no scrollbar, no hint,
     78px of the organisations table simply unreachable. Vertical overflow stays
     hidden so the rounded corners still clip. The scroll shadows remain exclusive
     to .responsive-data-region. */
  overflow-x: auto;
  overflow-y: hidden;
  background: var(--surface);
}
.grid { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
.grid thead th {
  text-align: left;
  padding: 0.85rem 1.1rem;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  background: rgba(255, 255, 255, 0.02);
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.grid tbody td { padding: 0.85rem 1.1rem; border-bottom: 1px solid var(--line); vertical-align: middle; }
.grid tbody tr:last-child td { border-bottom: 0; }
.grid tbody tr { transition: background 0.12s ease; }
.grid tbody tr:hover { background: rgba(255, 255, 255, 0.025); }
.grid td.actions { text-align: right; white-space: nowrap; }
.grid .actions form { display: inline; margin: 0; }
.grid .actions form + form,
.grid .actions .btn + .btn,
.grid .actions form + .btn { margin-left: 0.4rem; }
.grid a { color: var(--off-white); font-weight: 600; }
.grid a:hover { color: var(--orange); }
.cell-ref { font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: 0.02em; }
.cell-sub { display: block; font-size: 0.78rem; color: var(--muted); }

.inline-form { display: inline-flex; align-items: center; gap: 0.4rem; margin: 0; }
.inline-form select { width: auto; padding-top: 0.45rem; padding-bottom: 0.45rem; min-height: 36px; font-size: 0.82rem; }

/* ==========================================================================
   Empty states
   ========================================================================== */
.empty {
  text-align: center;
  padding: 3rem 1.5rem;
  color: var(--muted);
}
.empty .empty-mark {
  display: grid; place-items: center;
  width: 56px; height: 56px; margin: 0 auto 1rem;
  border-radius: 50%;
  background: rgba(255, 106, 0, 0.1);
  border: 1px solid rgba(255, 106, 0, 0.35);
}
.empty .empty-mark .icon { width: 26px; height: 26px; color: var(--orange); }
/* Empty-state headings are <h2> so the document outline never skips a level
   (h1 -> h3 was an axe heading-order violation on every empty list). The h3 size
   is kept deliberately — the semantic level changed, the design did not. */
.empty h2, .empty h3 { color: var(--off-white); font-size: 1.02rem; margin: 0 0 0.35rem; }
.empty p { margin: 0 auto 1.2rem; max-width: 42ch; }

/* ==========================================================================
   Dashboard — stat tiles + queue
   ========================================================================== */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 1rem;
  margin-bottom: 1.5rem;
}
.section-label {
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  margin: 0 0 0.75rem;
}
.stat {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  padding: 1.15rem 1.25rem 1.25rem;
  transition: border-color 0.18s ease, transform 0.18s ease;
}
a.stat:hover { border-color: var(--line-hi); transform: translateY(-2px); text-decoration: none; }
.stat::before {
  content: ""; display: block; width: 22px; height: 2px; background: var(--orange); margin-bottom: 0.85rem;
}
.stat.is-quiet::before { background: var(--line); }
.stat-value { font-size: 2rem; font-weight: 600; line-height: 1; color: var(--off-white); font-variant-numeric: tabular-nums; }
.stat-label { margin: 0.45rem 0 0; font-size: 0.82rem; color: var(--muted); }

.dash-cols { display: grid; grid-template-columns: 1.6fr 1fr; gap: 1.25rem; align-items: start; }
/* a wide table/long value inside a column must never force the grid track wider
   than its track (would push the neighbouring column off-screen) */
.dash-cols > * { min-width: 0; }

/* Responsive data region: a wide table becomes a FOCUSABLE horizontal-scroll
   region — no column is ever clipped silently (overflow-x:auto, never hidden).
   The right/left scroll-shadows are a pure-CSS hint that appear only when more
   content exists that way and fade out at each end. Scoped class — the global
   .table-wrap is unchanged. */
.responsive-data-region {
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-inline: contain;
  background:
    linear-gradient(90deg, var(--surface), rgba(26, 30, 36, 0)) 0 0 / 28px 100% no-repeat,
    linear-gradient(90deg, rgba(26, 30, 36, 0), var(--surface)) 100% 0 / 28px 100% no-repeat,
    radial-gradient(farthest-side at 0 50%, rgba(0, 0, 0, 0.45), rgba(0, 0, 0, 0)) 0 0 / 14px 100% no-repeat,
    radial-gradient(farthest-side at 100% 50%, rgba(0, 0, 0, 0.45), rgba(0, 0, 0, 0)) 100% 0 / 14px 100% no-repeat;
  background-attachment: local, local, scroll, scroll;
}
.responsive-data-region:focus-visible { outline: var(--focus); outline-offset: -2px; }

/* Phone (<=480): the same recent cases as labelled summary cards; the scroll
   region is hidden so nothing is duplicated to assistive tech at once. */
.recent-case-cards { list-style: none; margin: 0; padding: 0; display: none; }
.recent-case-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-ctrl); padding: 0.85rem 0.95rem; margin-bottom: 0.75rem;
}
.recent-case-card:last-child { margin-bottom: 0; }
.rc-head { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; }
.rc-ref { font-weight: 600; font-variant-numeric: tabular-nums; }
.rc-title { margin: 0.45rem 0 0.55rem; color: var(--warm-grey); overflow-wrap: anywhere; }
.rc-row { display: flex; align-items: baseline; gap: 0.5rem; margin-top: 0.3rem; font-size: 0.85rem; }
.rc-k { flex: none; min-width: 70px; color: var(--muted); font-size: 0.78rem; }
.rc-v { min-width: 0; overflow-wrap: anywhere; }

/* ==========================================================================
   Ticket detail — meta panel + thread
   ========================================================================== */
.ticket-layout { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 1.5rem; align-items: start; }
.ticket-main { min-width: 0; }
.ticket-side { display: flex; flex-direction: column; gap: 1.25rem; position: sticky; top: 84px; }

.meta-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.8rem; }
.meta-list li { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.meta-list .k { font-size: 0.8rem; color: var(--muted); }
.meta-list .v { font-size: 0.88rem; color: var(--off-white); text-align: right; }

.thread { display: flex; flex-direction: column; gap: 1rem; margin: 0 0 1.5rem; }
.msg {
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--surface);
  padding: 1rem 1.15rem;
}
.msg-head {
  display: flex; align-items: center; gap: 0.6rem;
  margin-bottom: 0.55rem; flex-wrap: wrap;
}
.msg-avatar {
  width: 30px; height: 30px; border-radius: 50%;
  display: grid; place-items: center; flex: none;
  background: rgba(141, 149, 163, 0.16); color: var(--warm-grey);
  border: 1px solid var(--line);
  font-size: 0.72rem; font-weight: 600; text-transform: uppercase;
}
.msg-author { font-weight: 600; font-size: 0.9rem; }
.msg-role { font-size: 0.62rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted);
  border: 1px solid var(--line); border-radius: var(--radius-pill); padding: 0.05rem 0.45rem; }
.msg-time { margin-left: auto; font-size: 0.75rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.msg-body { margin: 0; white-space: pre-wrap; word-break: break-word; line-height: 1.6; color: var(--warm-grey); }

/* staff-authored bubble tint */
.msg.from-staff { border-color: rgba(255,106,0,0.28); }
.msg.from-staff .msg-avatar { background: rgba(255,106,0,0.16); color: var(--orange); border-color: rgba(255,106,0,0.4); }

/* internal note — visually distinct, staff-only (server-gated) */
.msg.internal {
  border-color: rgba(255, 106, 0, 0.5);
  border-style: dashed;
  background: rgba(255, 106, 0, 0.06);
}
.msg.internal .internal-tag {
  display: inline-flex; align-items: center; gap: 0.3rem;
  font-size: 0.62rem; letter-spacing: 0.08em; text-transform: uppercase; font-weight: 600;
  color: var(--orange);
  border: 1px solid rgba(255,106,0,0.5); border-radius: var(--radius-pill);
  padding: 0.05rem 0.5rem;
}

/* attachments on a message */
.att-list { list-style: none; margin: 0.8rem 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.5rem; }
.att {
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0.45rem 0.75rem;
  background: var(--charcoal);
  border: 1px solid var(--line);
  border-radius: var(--radius-ctrl);
  font-size: 0.82rem;
  color: var(--warm-grey);
}
.att:hover { border-color: var(--line-hi); color: var(--off-white); text-decoration: none; }
.att .icon { width: 16px; height: 16px; color: var(--muted); flex: none; }
.att .sz { color: var(--muted); font-size: 0.74rem; }

/* ==========================================================================
   File input (drag-drop-ish)
   ========================================================================== */
.file-drop {
  display: block;
  position: relative;
  border: 1.5px dashed var(--line);
  border-radius: var(--radius-ctrl);
  background: var(--charcoal);
  padding: 1.4rem 1rem;
  text-align: center;
  cursor: pointer;
  transition: border-color 0.18s ease, background 0.18s ease;
}
.file-drop:hover { border-color: rgba(255,106,0,0.5); }
.file-drop.is-drag { border-color: var(--orange); background: rgba(255,106,0,0.06); }
.file-drop input[type="file"] {
  position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer;
}
.file-drop .icon { width: 22px; height: 22px; color: var(--orange); margin-bottom: 0.35rem; }
.file-drop .fd-main { font-weight: 600; font-size: 0.9rem; }
.file-drop .fd-main u { color: var(--orange); text-decoration: none; }
.file-drop .fd-sub { font-size: 0.76rem; color: var(--muted); margin-top: 0.2rem; }
.file-list { list-style: none; margin: 0.7rem 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.file-list li {
  display: flex; align-items: center; gap: 0.5rem;
  font-size: 0.82rem; color: var(--warm-grey);
  padding: 0.4rem 0.6rem; background: var(--charcoal);
  border: 1px solid var(--line); border-radius: 8px;
}
.file-list li .icon { width: 15px; height: 15px; color: var(--muted); flex: none; }
.file-list li .sz { margin-left: auto; color: var(--muted); font-size: 0.74rem; }
.file-list li.too-big { border-color: rgba(255,90,82,0.5); color: var(--danger); }

/* ==========================================================================
   Reply / composer
   ========================================================================== */
.composer .field:last-of-type { margin-bottom: 0; }

/* Segmented staff toggle: public reply vs internal note */
.seg {
  display: inline-flex;
  padding: 3px;
  gap: 3px;
  background: var(--charcoal);
  border: 1px solid var(--line);
  border-radius: var(--radius-ctrl);
  margin-bottom: 1rem;
}
.seg button {
  border: 0; background: none; cursor: pointer;
  font-family: inherit; font-size: 0.82rem; font-weight: 600;
  color: var(--muted);
  padding: 0.45rem 0.9rem; border-radius: 8px;
}
.seg button[aria-selected="true"] { background: var(--surface); color: var(--off-white); box-shadow: inset 0 0 0 1px var(--line); }
.seg button.note-tab[aria-selected="true"] { color: var(--orange); }
.no-js .seg { display: none; }

/* ==========================================================================
   Filter regions
   --------------------------------------------------------------------------
   One structure for every filter bar in the portal: a wrapping row of CELLS, where a
   cell is a one-line label above one control. Because every cell has the same shape,
   the labels line up, the controls line up, and a cell that is intrinsically taller —
   a combobox carrying a selection statement — extends DOWNWARD without dragging its
   neighbours off the row.

   The previous rule set centred children of mixed heights (`align-items: center`) and
   applied `min-width: 150px` to every input including checkboxes. A 200px-tall combobox
   therefore set the row height and every 40px select floated at its vertical middle,
   which is the malformed-filter defect users reported: labels detached from their
   fields, checkboxes rendered as large empty squares, and controls apparently escaping
   the box. Both causes are removed here rather than offset.
   ========================================================================== */
.filters {
  display: flex;
  flex-wrap: wrap;
  align-items: start;             /* cells share their TOP edge, so labels align */
  gap: var(--space-4) var(--space-3);
  margin-bottom: var(--stack-gap);
  padding: var(--space-4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
}
/* No child may force the bar wider than the page. */
.filters > * { min-width: 0; }

/* A filter cell. */
.flt {
  display: flex; flex-direction: column; gap: var(--label-gap);
  flex: 1 1 var(--flt-basis);
  min-width: 0;
}
.flt-label {
  margin: 0;
  font-size: var(--label-size);
  line-height: var(--label-lh);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--warm-grey);
}
/* Wide cells: a free-text search earns more room than a fixed-option select. */
.flt-wide { flex: 3 1 18rem; }

/* Row-height membership is decided STRUCTURALLY: a control shares the row's height only
   if it is the control of a cell. Listing the members explicitly avoids the alternative,
   which is a broad `.filters input` rule plus a growing tail of `:not()` exclusions for
   every part that is deliberately smaller — that approach is what let a 150px min-width
   reach a checkbox in the first place. */
.flt > select,
.flt > input,
.filters > select,
.filters > input,
.lookup-combo > .lookup-search,
.flt-check > .checkline,
.filter-actions > .btn {
  min-height: var(--ctrl-h);
}
.flt > select,
.flt > input,
.lookup-combo > .lookup-search {
  width: 100%;
  min-width: 0;
  max-width: 100%;
  padding-top: var(--ctrl-pad-y);
  padding-bottom: var(--ctrl-pad-y);
}
/* The checkbox pair is one target: the label fills the control row so the tappable area
   matches every other control. At 23px it was below the WCAG 2.2 AA 24x24 minimum. */
.flt-check > .checkline { display: inline-flex; align-items: center; }

/* Cells with no label of their own — a checkbox pair, an action group — drop by exactly
   the label row's height so they land on the shared control row. The offset is the
   derived --label-block token, not a measured pixel value. */
.flt-check,
.filter-actions {
  flex: 0 0 auto;
  margin-top: var(--label-block);
  min-height: var(--ctrl-h);
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.flt-check { max-width: 100%; }
/* Actions sit at the end of the row on a real filter bar; when the bar wraps to a single
   column they become full width instead, so Apply and Clear are never off-screen. */
.filter-actions { margin-left: auto; flex-wrap: wrap; }
.filter-actions .btn { flex: 0 0 auto; }

/* ==========================================================================
   Auth / public layout
   ========================================================================== */
.public {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
.public-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.1rem clamp(1.25rem, 5vw, 3rem);
}
.public-bar .logo { height: 34px; width: auto; display: block; }
.public-main {
  flex: 1;
  display: grid;
  place-items: center;
  padding: 1.5rem;
}
.auth-card {
  width: 100%;
  max-width: 440px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  padding: clamp(1.75rem, 4vw, 2.5rem);
}
.auth-card .kicker { text-align: left; }
.auth-foot { margin: 1.4rem 0 0; font-size: 0.9rem; color: var(--muted); text-align: center; }
.public-foot {
  padding: 1.25rem clamp(1.25rem, 5vw, 3rem);
  border-top: 1px solid var(--line);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  color: var(--muted);
  text-align: center;
}

/* Awaiting-approval hero */
.awaiting {
  max-width: 560px;
  text-align: center;
}
.awaiting .awaiting-mark {
  width: 64px; height: 64px; margin: 0 auto 1.5rem; display: block;
}
.awaiting .steps {
  list-style: none; margin: 1.75rem 0 0; padding: 0;
  display: flex; flex-direction: column; gap: 0.9rem; text-align: left;
}
.awaiting .steps li { display: flex; gap: 0.75rem; align-items: flex-start; color: var(--warm-grey); font-size: 0.92rem; }
.awaiting .steps .num {
  flex: none; width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(255,106,0,0.14); border: 1px solid rgba(255,106,0,0.4);
  color: var(--orange); font-weight: 600; font-size: 0.75rem;
}

/* ==========================================================================
   Coming soon
   ========================================================================== */
.cs-hero { text-align: center; max-width: 640px; margin: 2rem auto; }
.cs-hero .cs-badge {
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0.35rem 0.85rem; margin-bottom: 1.25rem;
  border-radius: var(--radius-pill);
  border: 1px solid rgba(255,106,0,0.45);
  background: rgba(255,106,0,0.08);
  color: var(--orange);
  font-size: 0.72rem; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase;
}
.cs-hero h1 { font-size: clamp(1.8rem, 4vw, 2.6rem); }
.cs-hero p { color: var(--warm-grey); font-size: 1.02rem; max-width: 52ch; margin: 0.75rem auto 0; }

/* Conversations premium chat mockup */
.chat-mock {
  max-width: 720px;
  margin: 2rem auto 0;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  overflow: hidden;
}
.chat-head {
  display: flex; align-items: center; gap: 0.75rem;
  padding: 1rem 1.25rem; border-bottom: 1px solid var(--line);
  background: var(--sidebar-bg);
}
.chat-head .bot-avatar {
  width: 38px; height: 38px; border-radius: 50%;
  display: grid; place-items: center; flex: none;
  background: rgba(255,106,0,0.14); border: 1px solid rgba(255,106,0,0.4);
}
.chat-head .bot-avatar .mark { width: 22px; height: 22px; }
.chat-head .who { line-height: 1.2; }
.chat-head .who .n { font-weight: 600; }
.chat-head .who .s { font-size: 0.75rem; color: var(--muted); display: flex; align-items: center; gap: 0.35rem; }
.chat-head .who .s .live { width: 7px; height: 7px; border-radius: 50%; background: #6f9a6a; }
.chat-body { padding: 1.5rem 1.25rem; display: flex; flex-direction: column; gap: 1rem; background:
  radial-gradient(120% 80% at 50% 0%, rgba(255,106,0,0.05), rgba(255,106,0,0) 60%); }
.bubble { max-width: 78%; padding: 0.75rem 1rem; border-radius: 16px; font-size: 0.92rem; line-height: 1.5; }
.bubble.from-bot {
  align-self: flex-start;
  background: var(--charcoal);
  border: 1px solid var(--line);
  border-bottom-left-radius: 5px;
  color: var(--warm-grey);
}
.bubble.from-user {
  align-self: flex-end;
  background: var(--orange);
  color: var(--charcoal);
  border-bottom-right-radius: 5px;
  font-weight: 500;
}
.bubble .b-meta { display: block; margin-top: 0.35rem; font-size: 0.68rem; opacity: 0.7; }
/* Charcoal-on-orange at full opacity = 7:1; 0.7 dropped it to 4.06:1 (WCAG 1.4.3). */
.bubble.from-user .b-meta { opacity: 1; }
.typing { display: inline-flex; gap: 4px; align-items: center; }
.typing span { width: 6px; height: 6px; border-radius: 50%; background: var(--muted); animation: blink 1.2s infinite ease-in-out; }
.typing span:nth-child(2) { animation-delay: 0.2s; }
.typing span:nth-child(3) { animation-delay: 0.4s; }
@keyframes blink { 0%, 80%, 100% { opacity: 0.3; } 40% { opacity: 1; } }

.chat-composer {
  position: relative;
  display: flex; align-items: center; gap: 0.75rem;
  padding: 0.9rem 1.25rem; border-top: 1px solid var(--line);
}
.chat-composer input {
  flex: 1; background: var(--charcoal); cursor: not-allowed;
}
.chat-composer input:disabled { color: var(--muted); }
.chat-ribbon {
  position: absolute; top: -13px; right: 1.25rem;
  padding: 0.2rem 0.7rem; border-radius: var(--radius-pill);
  background: var(--orange); color: var(--charcoal);
  font-size: 0.66rem; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
}
.chat-composer .send-stub {
  width: 40px; height: 40px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  background: rgba(255,106,0,0.2); color: var(--orange); border: 1px solid rgba(255,106,0,0.4);
}
.chat-composer .send-stub .icon { width: 18px; height: 18px; }

.cs-features { list-style: none; margin: 2rem auto 0; padding: 0; max-width: 720px;
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
.cs-features li {
  background: var(--surface); border: 1px solid var(--line); border-radius: 14px;
  padding: 1.1rem 1.15rem; font-size: 0.86rem; color: var(--warm-grey);
}
.cs-features li::before { content: ""; display: block; width: 24px; height: 2px; background: rgba(255,106,0,0.65); margin-bottom: 0.7rem; }
.cs-features li strong { display: block; color: var(--off-white); margin-bottom: 0.2rem; font-size: 0.95rem; }

/* ==========================================================================
   Error pages
   ========================================================================== */
.error-hero { text-align: center; max-width: 520px; }
.error-code {
  font-size: clamp(3.5rem, 12vw, 6rem);
  font-weight: 600; line-height: 1;
  color: var(--orange);
  font-variant-numeric: tabular-nums;
}
.error-hero h1 { margin: 0.5rem 0 0.75rem; }
.error-hero p { color: var(--warm-grey); }
.error-hero .actions { margin-top: 1.5rem; display: flex; gap: 0.7rem; justify-content: center; flex-wrap: wrap; }

/* ==========================================================================
   Drawer backdrop (mobile, JS)
   ========================================================================== */
.scrim {
  position: fixed; inset: 0;
  background: rgba(17, 19, 23, 0.6);
  z-index: var(--z-scrim);
  opacity: 0; visibility: hidden;
  transition: opacity 0.22s ease, visibility 0s linear 0.22s;
}
body.drawer-open .scrim { opacity: 1; visibility: visible; transition: opacity 0.22s ease; }

/* ==========================================================================
   Responsive
   ========================================================================== */
@media (max-width: 1000px) {
  .ticket-layout { grid-template-columns: 1fr; }
  .ticket-side { position: static; order: -1; }
  .dash-cols { grid-template-columns: 1fr; }
  .grid-2, .grid-3 { grid-template-columns: 1fr; }
  .cs-features { grid-template-columns: 1fr; }
}

@media (max-width: 880px) {
  /* Sidebar becomes an off-canvas drawer (only when JS is present) */
  .js .sidebar {
    transform: translateX(-100%);
    transition: transform 0.25s ease;
    box-shadow: var(--shadow-pop);
    width: min(84vw, 300px);
  }
  .js body.drawer-open .sidebar { transform: none; }

  .main { margin-left: 0; }
  .nav-toggle { display: inline-flex; }

  /* No-JS: sidebar stacks above content, full width, static */
  .no-js .sidebar { position: static; width: 100%; border-right: 0; border-bottom: 1px solid var(--line); }
  .no-js .main { margin-left: 0; }
  .no-js .nav-toggle { display: none; }

  .profile-meta { display: none; }
  .topbar { padding: 0 1rem; }
  .field-row { grid-template-columns: 1fr; }

  /* Comfortable touch targets on mobile. Raising the TOKEN lifts every control that
     resolves its height from it — filter controls, the combobox search box, the checkbox
     row and the action buttons — instead of restating a min-height per component and
     risking one being missed. */
  :root { --ctrl-h: var(--ctrl-h-touch); }
  .btn, .nav-link, .menu-item, .profile-btn { min-height: var(--ctrl-h-touch); }
  .inline-form select { min-height: var(--ctrl-h-touch); }
  /* With JavaScript unavailable the id field is the ONLY way to set a bounded lookup's
     value, so on a touch screen it is a primary control and takes the full touch height
     rather than its compact desktop height. */
  input.lookup-value, .lookup-meta .btn { min-height: var(--ctrl-h-touch); }
  .lookup { max-width: 100%; }

  /* One consistent stacking order for every filter region: each cell takes the full
     width in source order, and the actions become full-width buttons at the end so
     Apply and Clear are always reachable without horizontal scrolling. */
  .filters { padding: var(--space-3); }
  .flt, .lookup { flex: 1 1 100%; }
  .flt-wide { flex: 1 1 100%; }
  .flt-check, .filter-actions { flex: 1 1 100%; margin-top: 0; margin-left: 0; }
  .filter-actions .btn { flex: 1 1 auto; justify-content: center; }

  /* Tables: let them scroll horizontally rather than crush */
  .table-wrap { overflow-x: auto; }
  .grid { min-width: 560px; }
}

/* Long emails / identifiers wrap instead of widening the page ------------- */
.break { overflow-wrap: anywhere; }

/* Action groups (user detail, recovery) ----------------------------------- */
.action-row { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: center; }
.action-row form { margin: 0; }

/* Users: responsive card list — replaces the wide table on small phones so
   there is no page-level horizontal scroll at 320/390px. */
.users-cards { list-style: none; margin: 1.25rem 0 0; padding: 0; display: none; }
.user-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-card); padding: 1rem 1.1rem; margin-bottom: 0.8rem;
}
.uc-head { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; }
/* the name must shrink/wrap so the status chip stays inside the card at 320px */
.uc-name { font-weight: 600; min-width: 0; overflow-wrap: anywhere; }
.uc-email { margin: 0.35rem 0 0; font-size: 0.9rem; }
.uc-meta { margin: 0.55rem 0 0; display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; }
.uc-login { margin: 0.4rem 0 0.85rem; font-size: 0.82rem; }
.uc-actions .btn { width: 100%; }
.uc-actions form { margin: 0; }

@media (max-width: 480px) {
  .users-table { display: none; }
  .users-cards { display: block; }
  /* Recent-cases summary → labelled cards on phones (6-column table is too
     dense to read here even when scrollable). */
  .recent-cases .responsive-data-region { display: none; }
  .recent-cases .recent-case-cards { display: block; }
}

@media (max-width: 560px) {
  .page-head { flex-direction: column; align-items: stretch; }
  .page-actions .btn { flex: 1; }
  .stat-value { font-size: 1.6rem; }
  .bubble { max-width: 90%; }
  /* paired form fields stack on phones so neither field is cramped */
  .field-row { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Motion preferences
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

/* Icon default sizing */
.svg-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.icon { display: inline-block; width: 20px; height: 20px; vertical-align: middle; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }

/* ==========================================================================
   5-role extension — role badges, new chips, dashboards, banner, auth panel,
   rich-text editor, marketplace. (Appended; reuses the tokens above.)
   ========================================================================== */

/* --- Role badges (all 5 roles) ------------------------------------------- */
.role-superadmin    { color: var(--orange);      border-color: rgba(255,106,0,0.5); }
.role-support_agent { color: #ffb27a;            border-color: rgba(255,106,0,0.4); }
.role-sales         { color: #a9d3a2;            border-color: rgba(111,154,106,0.55); }
.role-security      { color: #b7c0d0;            border-color: rgba(141,149,163,0.55); }
.role-customer      { color: var(--muted);       border-color: var(--line); }

/* --- Lead / case chips (extend .chip) ------------------------------------ */
.kind-demo             { border-color: rgba(255,106,0,0.5); color: #ffd3b0; }
.kind-demo .dot        { background: var(--orange); }
.kind-queue            { border-color: rgba(141,149,163,0.5); color: var(--warm-grey); }
.kind-queue .dot       { background: #b7c0d0; }

.chip.spam             { border-color: rgba(255,90,82,0.5); color: var(--danger); text-transform: none; }
.chip.spam .icon       { width: 13px; height: 13px; color: currentColor; }

.ls-new                { border-color: rgba(255,106,0,0.5); color: #ffd3b0; }
.ls-new .dot           { background: var(--orange); }
.ls-contacted          { color: var(--warm-grey); border-color: rgba(226,222,217,0.4); }
.ls-contacted .dot     { background: var(--warm-grey); }
.ls-qualified          { color: #ffb27a; border-color: rgba(255,106,0,0.45); }
.ls-qualified .dot     { background: var(--orange); }
.ls-won                { color: #a9d3a2; border-color: rgba(111,154,106,0.6); }
.ls-won .dot           { background: #6f9a6a; }
.ls-lost               { color: var(--danger); border-color: rgba(255,90,82,0.45); }
.ls-lost .dot          { background: var(--danger); }
.ls-archived           { color: var(--muted); opacity: 0.85; }
.ls-archived .dot      { background: var(--muted); }

.cs-open               { border-color: rgba(255,106,0,0.5); color: #ffd3b0; }
.cs-open .dot          { background: var(--orange); }
.cs-in_progress        { color: var(--warm-grey); border-color: rgba(226,222,217,0.4); }
.cs-in_progress .dot   { background: var(--warm-grey); }
.cs-on_hold            { color: #ffb27a; border-color: rgba(255,106,0,0.35); }
.cs-on_hold .dot       { background: #b9752f; }
.cs-closed             { color: var(--muted); opacity: 0.85; }
.cs-closed .dot        { background: var(--muted); }

.ct-fraud          { color: #ffb27a; border-color: rgba(255,106,0,0.45); }
.ct-research       { color: var(--warm-grey); }
.ct-analysis       { color: #a9d3a2; border-color: rgba(111,154,106,0.45); }
.ct-investigation  { color: #b7c0d0; border-color: rgba(141,149,163,0.5); }
.ct-review         { color: var(--muted); }

/* --- Dashboard banner ---------------------------------------------------- */
.dash-banner {
  position: relative;
  display: flex;
  align-items: center;
  gap: 1.25rem;
  overflow: hidden;
  margin-bottom: 1.6rem;
  padding: clamp(1.15rem, 3vw, 1.8rem) clamp(1.4rem, 4vw, 2.4rem);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: linear-gradient(120deg, #14171c 0%, #1a1e24 55%, #20252d 100%);
}
.db-glow {
  position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(58% 130% at 88% 15%, rgba(255,106,0,0.22), rgba(255,106,0,0) 60%);
}
.db-body { position: relative; display: flex; align-items: center; gap: 1rem; flex: 1; min-width: 0; }
.db-mark { width: 44px; height: 44px; flex: none; }
.db-copy { min-width: 0; }
.db-hi { margin: 0; font-size: clamp(1.3rem, 3vw, 1.7rem); font-weight: 600; letter-spacing: -0.01em; color: var(--off-white); }
.db-sub { margin: 0.4rem 0 0; display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; color: var(--muted); font-size: 0.92rem; }
.db-sub span { color: var(--warm-grey); }
.db-bot {
  position: relative; flex: none; align-self: flex-end;
  width: clamp(96px, 13vw, 138px); height: auto;
  margin: -0.9rem -0.4rem -1.8rem 0;
  filter: drop-shadow(0 12px 26px rgba(0,0,0,0.55));
}

/* --- Activity feed (superadmin) ------------------------------------------ */
.feed { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.feed-item { display: flex; align-items: flex-start; gap: 0.85rem; padding: 0.85rem 0; border-bottom: 1px solid var(--line); }
.feed-item:first-child { padding-top: 0; }
.feed-item:last-child { border-bottom: 0; padding-bottom: 0; }
.feed-mark {
  flex: none; width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center;
  background: rgba(255,106,0,0.12); border: 1px solid rgba(255,106,0,0.35);
}
.feed-mark .icon { width: 16px; height: 16px; color: var(--orange); }
.feed-body { flex: 1; min-width: 0; }
.feed-line { margin: 0; word-break: break-word; }
.feed-line .mono { font-size: 0.82rem; color: var(--warm-grey); }
.feed-detail { margin: 0.15rem 0 0; font-size: 0.82rem; word-break: break-word; }
.feed-time { flex: none; font-size: 0.75rem; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; margin-left: 0.5rem; }

/* --- By-type list (security) --------------------------------------------- */
.type-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.type-list a {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 0.6rem 0.85rem; border: 1px solid var(--line); border-radius: var(--radius-ctrl);
  color: var(--warm-grey); font-weight: 600; font-size: 0.9rem;
}
.type-list a:hover { border-color: var(--line-hi); color: var(--off-white); background: rgba(255,255,255,0.02); text-decoration: none; }
.type-count { font-variant-numeric: tabular-nums; color: var(--orange); }

/* --- Auth split (login / register brand panel) --------------------------- */
.auth-split {
  width: 100%;
  max-width: 900px;
  display: grid;
  grid-template-columns: 1.02fr 0.98fr;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  overflow: hidden;
  box-shadow: var(--shadow-pop);
}
.auth-brand {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem;
  padding: clamp(1.75rem, 4vw, 2.75rem);
  border-right: 1px solid var(--line);
  background: linear-gradient(160deg, #14171c 0%, #1a1e24 58%, #23272f 100%);
}
.auth-glow {
  position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(70% 55% at 50% 22%, rgba(255,106,0,0.24), rgba(255,106,0,0) 62%);
}
.auth-brand-top { position: relative; display: flex; align-items: center; gap: 0.6rem; align-self: flex-start; }
.auth-brand-top .mark { width: 34px; height: 34px; }
.auth-brand-top .wordmark { font-weight: 600; font-size: 1.3rem; letter-spacing: 0.01em; color: var(--off-white); }
.auth-bot { position: relative; width: min(78%, 300px); height: auto; filter: drop-shadow(0 16px 34px rgba(0,0,0,0.55)); }
.auth-tag {
  position: relative; margin: 0; text-align: center;
  font-weight: 600; font-size: 1.15rem; line-height: 1.25; letter-spacing: -0.01em;
  color: var(--off-white);
}
.auth-form { padding: clamp(1.75rem, 4vw, 2.75rem); align-self: center; width: 100%; }
.auth-form .kicker { text-align: left; }

/* --- Rich-text editor + rendered rich content ---------------------------- */
.rte {
  border: 1px solid var(--line);
  border-radius: var(--radius-ctrl);
  background: var(--charcoal);
  overflow: hidden;
  margin-bottom: 1.1rem;
}
.rte:focus-within { border-color: var(--orange); box-shadow: 0 0 0 3px rgba(255,106,0,0.18); }
.rte-toolbar {
  display: none;
  flex-wrap: wrap; align-items: center; gap: 2px;
  padding: 0.4rem; border-bottom: 1px solid var(--line); background: var(--surface);
}
.js .rte-toolbar { display: flex; }
.rte-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; padding: 0;
  border: 0; border-radius: 8px; background: none; color: var(--warm-grey);
  cursor: pointer; transition: background 0.15s ease, color 0.15s ease;
}
.rte-btn:hover { background: rgba(255,255,255,0.06); color: var(--off-white); }
.rte-btn[aria-pressed="true"] { background: rgba(255,106,0,0.16); color: var(--orange); }
.rte-btn .icon { width: 18px; height: 18px; }
.rte-sep { width: 1px; align-self: stretch; margin: 0.25rem 0.3rem; background: var(--line); }
.rte-area {
  display: none;
  min-height: 150px; max-height: 460px; overflow-y: auto;
  padding: 0.85rem 0.95rem; color: var(--off-white); line-height: 1.65; outline: none;
}
.js .rte-area { display: block; }
.rte-area:empty::before { content: attr(data-placeholder); color: var(--muted); pointer-events: none; }
.js .rte-fallback { display: none; }

.rich { color: var(--warm-grey); line-height: 1.65; word-break: break-word; }
.rich > :first-child, .rte-area > :first-child { margin-top: 0; }
.rich > :last-child, .rte-area > :last-child { margin-bottom: 0; }
.rich p, .rte-area p { margin: 0 0 0.7rem; }
.rich h3, .rte-area h3 { font-size: 1.05rem; margin: 1rem 0 0.5rem; color: var(--off-white); }
.rich h4, .rte-area h4 { font-size: 0.95rem; margin: 0.9rem 0 0.4rem; color: var(--off-white); }
.rich ul, .rich ol, .rte-area ul, .rte-area ol { margin: 0 0 0.7rem; padding-left: 1.4rem; }
.rich li, .rte-area li { margin: 0.2rem 0; }
.rich blockquote, .rte-area blockquote {
  margin: 0 0 0.7rem; padding: 0.35rem 0 0.35rem 0.9rem;
  border-left: 3px solid rgba(255,106,0,0.5); color: var(--warm-grey);
}
.rich code, .rte-area code {
  font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 0.88em;
  background: var(--charcoal); border: 1px solid var(--line); border-radius: 5px; padding: 0.05rem 0.35rem;
}
.rich pre, .rte-area pre {
  margin: 0 0 0.7rem; padding: 0.85rem 1rem; overflow-x: auto;
  background: var(--charcoal); border: 1px solid var(--line); border-radius: var(--radius-ctrl);
}
.rich pre code, .rte-area pre code { background: none; border: 0; padding: 0; }
.rich a { color: var(--orange); text-decoration: underline; text-underline-offset: 2px; }

/* --- Marketplace --------------------------------------------------------- */
.mk-section { margin-top: 2.25rem; }
.mk-head { margin-bottom: 1rem; }
.mk-head h2 { margin: 0; }
.mk-head p { margin: 0.2rem 0 0; }
.mk-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(258px, 1fr)); gap: 1rem; }
.mk-card {
  display: flex; flex-direction: column; align-items: flex-start; gap: 0.85rem;
  padding: 1.3rem; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-card);
}
.mk-icon {
  flex: none; width: 42px; height: 42px; border-radius: 10px; display: grid; place-items: center;
  background: rgba(255,106,0,0.12); border: 1px solid rgba(255,106,0,0.35);
}
.mk-icon .icon { width: 21px; height: 21px; color: var(--orange); }
.mk-body { flex: 1; }
.mk-body h3 { margin: 0 0 0.3rem; font-size: 1rem; }
.mk-body p { margin: 0; font-size: 0.85rem; color: var(--muted); line-height: 1.55; }
.mk-pill {
  margin-top: auto;
  padding: 0.18rem 0.6rem; border-radius: var(--radius-pill);
  border: 1px solid rgba(255,106,0,0.4); background: rgba(255,106,0,0.08); color: var(--orange);
  font-size: 0.62rem; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase;
}

/* --- Responsive additions ------------------------------------------------ */
@media (max-width: 880px) {
  .rte-btn { width: 44px; height: 44px; }
}
@media (max-width: 720px) {
  .auth-brand { display: none; }
  .auth-split { grid-template-columns: 1fr; max-width: 440px; box-shadow: none; }
}
@media (max-width: 560px) {
  .db-bot { display: none; }
  .dash-banner { padding: 1.1rem 1.25rem; }
  .feed-time { display: none; }
}

/* ==========================================================================
   Site monitoring (superadmin) — visits chart, top-N ranks, recent table
   ========================================================================== */
.viz { margin: 0; }
.viz-chart { display: block; width: 100%; height: auto; overflow: visible; }
.viz-bar { fill: var(--orange); transition: fill 0.12s ease; }
.viz-bar:hover { fill: var(--orange-hi); }
.viz-base { stroke: var(--line); stroke-width: 1; }
.viz-lab { fill: var(--muted); font-family: var(--font); font-size: 10px; font-variant-numeric: tabular-nums; }
.viz-cap { margin: 0.75rem 0 0; font-size: 0.78rem; }

.rank-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.7rem; }
.rank-row { display: grid; grid-template-columns: 1fr auto; gap: 0.2rem 0.8rem; align-items: baseline; }
.rank-label {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--warm-grey); font-size: 0.85rem; font-weight: 600;
}
.rank-flag { font-weight: 400; }
.rank-count { font-variant-numeric: tabular-nums; color: var(--muted); font-size: 0.8rem; white-space: nowrap; }
.rank-meter { grid-column: 1 / -1; display: block; width: 100%; height: 4px; border-radius: 2px; overflow: hidden; }
.rm-track { fill: var(--line); }
.rm-fill { fill: var(--orange); }

/* Bot filter: link-based (works without JS, unlike the .seg tab control). */
.bot-toggle {
  display: inline-flex; padding: 3px; gap: 3px;
  background: var(--charcoal); border: 1px solid var(--line); border-radius: var(--radius-ctrl);
}
.bt-btn {
  font-size: 0.8rem; font-weight: 600; color: var(--muted);
  padding: 0.35rem 0.8rem; border-radius: 8px;
}
.bt-btn:hover { color: var(--off-white); text-decoration: none; }
.bt-btn.is-on { background: var(--surface); color: var(--off-white); box-shadow: inset 0 0 0 1px var(--line); }

.path-cell { display: inline-block; max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; color: var(--warm-grey); }
.ua-cell { max-width: 280px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.82rem; }
.bot-tag {
  font-size: 0.62rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--muted); border: 1px solid var(--line); border-radius: var(--radius-pill); padding: 0.05rem 0.4rem;
}

/* ==========================================================================
   Organisation integrity — staged registration + organisation lifecycle
   ========================================================================== */
/* Honeypot: off-screen (not display:none, which some bots detect), removed from
   the accessibility tree by aria-hidden and from the tab order by tabindex=-1. */
.hp-field {
  position: absolute !important;
  left: -9999px; top: auto; width: 1px; height: 1px;
  overflow: hidden; opacity: 0; pointer-events: none;
}
.reg-steps {
  list-style: none; padding: 0; margin: 0 0 var(--space-4);
  display: flex; flex-direction: column; gap: 0.3rem;
  font-size: 0.85rem; color: var(--warm-grey);
}
.reg-steps li { padding-left: 0.9rem; position: relative; }
.reg-steps li::before {
  content: ""; position: absolute; left: 0; top: 0.55em;
  width: 5px; height: 5px; border-radius: 50%; background: var(--orange);
}
.org-admin-links { font-size: 0.85rem; margin: 0 0 var(--space-4); }
.org-admin-links .icon { vertical-align: -0.15em; }
.alert-info {
  display: flex; gap: var(--space-2); align-items: flex-start;
  background: rgba(59,130,246,0.1); border: 1px solid rgba(59,130,246,0.35);
  color: var(--off-white); border-radius: var(--radius-ctrl);
  padding: var(--space-3); margin-bottom: var(--space-4);
}
.alert-info .icon { flex: none; color: #93c5fd; }
.chip.os-deleted .dot { background: var(--danger); }

/* ==========================================================================
   Obala Designer — visual data-flow editor
   ========================================================================== */
.sr-only {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Status chips (reuse .chip base) */
.chip.ds-draft .dot { background: var(--muted); }
.chip.ds-submitted .dot { background: #3b82f6; }
.chip.ds-in_review .dot { background: #f59e0b; }
.chip.ds-changes_requested .dot { background: var(--orange); }
.chip.ds-reviewed .dot { background: #22c55e; }
.chip.ds-archived .dot { background: #64748b; }
.chip.ds-deleted .dot { background: var(--danger); }

/* Landing filters */
/* The Designer filter bar was a second, divergent implementation: `align-items:
   flex-end` and a 150px min-width on a `.field` wrapper, which produced the same
   detached-popup and uneven-height defects in a different way. It now uses the one
   filter system above, so `.ds-filters` only carries what is genuinely specific to
   this surface — it is not a panel, so it has no card background. */
.ds-filters { padding: 0; background: none; border: 0; border-radius: 0; }
.ds-deleted-toggle { margin: 0 0 var(--space-4); font-size: 0.85rem; }
.ds-pager { display: flex; align-items: center; gap: var(--space-3); margin-top: var(--space-4); flex-wrap: wrap; }

/* Editor shell */
.ds-editor { display: flex; flex-direction: column; gap: var(--space-3); min-width: 0; }
.ds-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2);
  background: var(--sidebar-bg); border: 1px solid var(--line); border-radius: var(--radius-ctrl);
  padding: var(--space-2) var(--space-3); position: sticky; top: 0; z-index: var(--z-topbar);
}
.ds-bar-title { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; min-width: 0; }
.ds-bar-title strong { color: var(--off-white); }
.ds-bar-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-left: auto; }
.ds-inline { display: inline; }
.ds-dirty { color: var(--orange); font-size: 0.78rem; font-weight: 600; }
.ds-guidance {
  display: flex; align-items: center; gap: var(--space-2); font-size: 0.82rem; color: var(--warm-grey);
  background: rgba(255,106,0,0.08); border: 1px solid rgba(255,106,0,0.3);
  border-radius: var(--radius-ctrl); padding: var(--space-2) var(--space-3); margin: 0;
}
.ds-guidance .icon { color: var(--orange); flex: none; }

/* Dropdown menus (native <details>) */
.ds-menu { position: relative; }
.ds-menu > summary { list-style: none; cursor: pointer; }
.ds-menu > summary::-webkit-details-marker { display: none; }
.ds-menu-panel {
  position: absolute; right: 0; top: calc(100% + 4px); min-width: 190px; z-index: var(--z-menu);
  background: var(--surface); border: 1px solid var(--line-hi); border-radius: var(--radius-ctrl);
  box-shadow: var(--shadow-pop); padding: var(--space-1); display: flex; flex-direction: column;
}
.ds-menu-panel a, .ds-menu-panel button {
  display: block; width: 100%; text-align: left; background: none; border: 0; color: var(--warm-grey);
  padding: 0.5rem 0.7rem; border-radius: 8px; font: inherit; cursor: pointer;
}
.ds-menu-panel a:hover, .ds-menu-panel button:hover { background: var(--sidebar-bg); color: var(--off-white); text-decoration: none; }
.ds-menu-panel form { margin: 0; }
.ds-menu-panel .ds-danger { color: var(--danger); }

/* Workspace grid */
.ds-workspace {
  display: grid; grid-template-columns: 240px minmax(0, 1fr) 340px; gap: var(--space-3);
  align-items: stretch; min-height: 560px;
}
.ds-panel-h { font-size: 0.95rem; margin: 0 0 var(--space-2); color: var(--off-white); }
.ds-palette, .ds-side {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-card);
  padding: var(--space-3); overflow: auto; max-height: calc(100vh - 180px); min-width: 0;
}
.ds-palette-list { display: flex; flex-direction: column; gap: var(--space-3); margin-top: var(--space-2); }
.ds-palette-cat > h3 { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); margin: 0 0 var(--space-1); }
.ds-palette-item {
  display: flex; align-items: center; gap: 0.5rem; width: 100%; text-align: left; cursor: pointer;
  background: var(--sidebar-bg); border: 1px solid var(--line); border-left: 3px solid var(--muted);
  border-radius: 8px; padding: 0.4rem 0.55rem; color: var(--warm-grey); font: inherit; font-size: 0.82rem;
  margin-bottom: 0.3rem;
}
.ds-palette-item:hover { border-color: var(--line-hi); color: var(--off-white); }
.ds-palette-item.cat-source { border-left-color: #3b82f6; }
.ds-palette-item.cat-parse { border-left-color: #a855f7; }
.ds-palette-item.cat-process { border-left-color: #06b6d4; }
.ds-palette-item.cat-quality_security { border-left-color: var(--danger); }
.ds-palette-item.cat-delivery { border-left-color: #22c55e; }
.ds-palette-item.cat-documentation { border-left-color: #94a3b8; }

/* Canvas */
.ds-canvas-wrap { display: flex; flex-direction: column; min-width: 0; }
.ds-canvas-tools { display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-2); flex-wrap: wrap; }
.ds-canvas-status { font-size: 0.8rem; color: var(--muted); margin-left: auto; }
.ds-canvas {
  position: relative; flex: 1 1 auto; min-height: 460px; overflow: hidden;
  background-color: #0e1116;
  background-image: radial-gradient(circle, rgba(255,255,255,0.06) 1px, transparent 1px);
  background-size: 22px 22px;
  border: 1px solid var(--line); border-radius: var(--radius-card);
}
.ds-canvas:focus-visible { outline: var(--focus); outline-offset: -2px; }
.ds-canvas [data-ds-svg] { display: block; touch-action: none; }
svg .ds-node-box { fill: var(--surface); stroke: var(--line-hi); stroke-width: 1.5; cursor: grab; }
svg .ds-node.is-selected .ds-node-box { stroke: var(--orange); stroke-width: 2.5; }
svg .ds-node-accent { }
svg .ds-node-title { fill: var(--off-white); font-family: var(--font); font-size: 13px; font-weight: 600; pointer-events: none; }
svg .ds-node-type { font-family: var(--font); font-size: 11px; pointer-events: none; }
svg .ds-edge { stroke: #64748b; stroke-width: 2; fill: none; }
svg .ds-edge.is-error { stroke: var(--danger); stroke-dasharray: 6 4; }
svg .ds-edge.is-selected { stroke: var(--orange); stroke-width: 3; }
svg .ds-edge-hit { stroke: transparent; stroke-width: 14; fill: none; cursor: pointer; }
svg .ds-port { fill: var(--sidebar-bg); stroke: var(--muted); stroke-width: 1.5; cursor: crosshair; }
svg .ds-port:hover, svg .ds-port.is-armed { fill: var(--orange); stroke: var(--orange); }
svg .ds-edge-label { fill: var(--warm-grey); font-family: var(--font); font-size: 10px; }
svg .ds-edge-label-bg { fill: #0e1116; }

/* Outline (accessible) */
.ds-outline { margin-top: var(--space-3); background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-card); padding: var(--space-3); }
.ds-outline ul { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.35rem; }
.ds-outline-node { display: flex; align-items: center; gap: 0.5rem; padding: 0.4rem 0.5rem; border: 1px solid var(--line); border-radius: 8px; }
.ds-outline-node.is-selected { border-color: var(--orange); }
.ds-outline-node button { background: none; border: 0; color: var(--warm-grey); font: inherit; cursor: pointer; text-align: left; flex: 1 1 auto; min-width: 0; }
.ds-outline-conns { font-size: 0.78rem; color: var(--muted); margin: 0.15rem 0 0.5rem 0.75rem; }

/* Side tabs + inspector */
.ds-tabs { display: flex; gap: 0.25rem; border-bottom: 1px solid var(--line); margin-bottom: var(--space-3); }
.ds-tab { background: none; border: 0; border-bottom: 2px solid transparent; color: var(--muted); font: inherit; padding: 0.4rem 0.6rem; cursor: pointer; }
.ds-tab.is-active { color: var(--off-white); border-bottom-color: var(--orange); }
.ds-tabpanel .field { margin-bottom: var(--space-3); }
.ds-insp-title { font-size: 0.95rem; color: var(--off-white); margin: 0 0 0.15rem; }
.ds-insp-sub { font-size: 0.78rem; color: var(--muted); margin: 0 0 var(--space-3); }

/* Validation panel */
.ds-issue { display: flex; gap: 0.5rem; padding: 0.5rem 0.6rem; border-radius: 8px; margin-bottom: 0.4rem; font-size: 0.85rem; }
.ds-issue.is-error { background: rgba(255,90,82,0.1); border: 1px solid rgba(255,90,82,0.35); color: #ffd7d4; }
.ds-issue.is-warning { background: rgba(245,158,11,0.1); border: 1px solid rgba(245,158,11,0.35); color: #ffe8c2; }
.ds-issue.is-ok { color: #86efac; }

/* Versions + comments */
.ds-versions { display: flex; flex-direction: column; gap: 0.3rem; margin-bottom: var(--space-3); }
.ds-version-row { display: flex; justify-content: space-between; font-size: 0.82rem; color: var(--warm-grey); border: 1px solid var(--line); border-radius: 8px; padding: 0.35rem 0.5rem; }
.ds-review-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-3); }
.ds-review-actions form { margin: 0; }
.ds-comments { display: flex; flex-direction: column; gap: 0.5rem; margin-bottom: var(--space-3); }
.ds-comment { border: 1px solid var(--line); border-radius: 8px; padding: 0.5rem 0.6rem; font-size: 0.85rem; }
.ds-comment.is-internal { border-color: rgba(245,158,11,0.4); background: rgba(245,158,11,0.06); }
.ds-comment-meta { font-size: 0.72rem; color: var(--muted); margin-bottom: 0.2rem; display: flex; gap: 0.4rem; flex-wrap: wrap; }
.ds-comment-form { margin-top: var(--space-2); }
.ds-check { display: flex; align-items: center; gap: 0.4rem; font-size: 0.82rem; color: var(--warm-grey); }

/* Responsive: collapse to a single column on tablet/mobile */
@media (max-width: 1180px) {
  .ds-workspace { grid-template-columns: 200px minmax(0, 1fr) 300px; }
}
@media (max-width: 960px) {
  .ds-workspace { display: block; }
  .ds-palette, .ds-side { max-height: none; margin-bottom: var(--space-3); }
  .ds-canvas { min-height: 52vh; }
  .ds-bar { position: static; }
}

@media (prefers-reduced-motion: reduce) {
  .ds-canvas [data-ds-svg] * { transition: none !important; }
}
@media (forced-colors: active) {
  svg .ds-node-box { stroke: CanvasText; fill: Canvas; }
  svg .ds-edge { stroke: CanvasText; }
  .ds-palette-item, .ds-comment, .ds-version-row, .ds-issue { border: 1px solid CanvasText; }
}
