/* Copyright (c) 2026 VOOPS. All rights reserved. Proprietary and confidential. */

/* ═══════════════════════════════════════════════════════════════════════════
   Self-hosted faces. Both are SIL OFL 1.1 (licences in assets/fonts/), served
   from our own origin because `font-src 'self'` forbids a CDN.

   Geist Mono declares ONLY the digits, so the browser reaches for it whenever it
   renders 0-9 and falls through to Inter for every other character. That is what
   puts every number in the app on the numeral face without a single class on a
   single element — and it cannot drift, because there is no opt-in to forget.

   Inter is subset to Latin, punctuation and currency. Arabic, Japanese and
   Chinese are not in Inter at all and fall through to the system stack, so
   shipping more would embed glyphs no locale can use.
   ═══════════════════════════════════════════════════════════════════════════ */
@font-face {
  font-family: "Geist Mono";
  src: url("/assets/fonts/geist-mono-digits.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0030-0039;
}
@font-face {
  font-family: "Inter";
  src: url("/assets/fonts/inter-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* ═══════════════════════════════════════════════════════════════════════════
   VOOPS design tokens — dark theme + orange accent (per docs/mockups).
   Every page inherits these; never hardcode colors in a template.
   ═══════════════════════════════════════════════════════════════════════════ */
:root {
  color-scheme: dark;

  /* Surfaces */
  --voops-bg:        #0a0a0b;   /* app background (near-black)          */
  --voops-surface:   #141416;   /* cards / panels                       */
  --voops-surface-2: #1b1b1f;   /* inputs / raised elements             */
  --voops-elevated:  #202024;   /* hover / active surface               */
  --voops-border:    #2a2a30;   /* hairline borders                     */
  --voops-border-2:  #3a3a42;   /* stronger border / focus ring base    */

  /* Brand */
  --voops-accent:      #f2530f; /* primary orange                       */
  --voops-accent-hover:#ff6a2b;
  --voops-accent-soft: rgba(242, 83, 15, .14); /* tinted fills          */
  --voops-accent-grad: linear-gradient(100deg, #f2530f 0%, #ff7a35 52%, #ff9457 100%);
  /* Warm edge, amber into the brand orange. Both ends come from the supplied
     palette; the red end of that palette is deliberately left out, because red
     is `--voops-error` here and a red-edged card reads as a failing one. Two
     hues with one transition, not a spectrum. */
  --voops-warm-grad: linear-gradient(115deg, #ffc300 0%, #ff9f00 32%, #f2530f 100%);
  --voops-warm-grad-hover: linear-gradient(115deg, #ffd23f 0%, #ffb02e 32%, #ff6a2b 100%);
  --voops-accent-glow: rgba(242, 83, 15, .28);
  --voops-btn-highlight: inset 0 1px 0 rgba(255, 255, 255, .20);

  /* Text */
  --voops-text:   #f4f5f7;      /* primary text                         */
  --voops-muted:  #9aa0ab;      /* secondary text                       */
  --voops-faint:  #6b707b;      /* tertiary / placeholders              */

  /* Status */
  --voops-success: #2fbf71;
  --voops-warning: #f5a623;
  --voops-error:   #ef4444;
  --voops-danger:  #ef4444;      /* alias used by required markers / invalid  */

  /* Shape */
  --voops-radius:    14px;      /* cards / panels                       */
  --voops-radius-sm: 10px;      /* inputs / buttons                     */
  --voops-radius-xs: 8px;
  --voops-radius-lg:  18px;
  --voops-card-bg:    linear-gradient(180deg, #17171a 0%, #131315 100%);
  --voops-card-shadow: 0 18px 44px rgba(0, 0, 0, .34);

  /* ── Theme-swappable derived colours ──────────────────────────────────────
     Everything below was hard-coded throughout the sheet, which made a second
     palette impossible: a light theme cannot be expressed by swapping six
     surface variables when 177 literal colours sit under them. Each family is
     named for its ROLE, not its value, so `[data-theme="light"]` can redefine
     the value without touching a single rule.

     The neutral tints are the clearest case: `rgba(255,255,255,.05)` is "lift
     this surface slightly", which on a light ground has to become a black wash,
     not a white one. */

  /* Neutral tints — lift a surface relative to its ground. */
  --voops-tint-weak:   rgba(255, 255, 255, .04);
  --voops-tint:        rgba(255, 255, 255, .05);
  --voops-tint-strong: rgba(255, 255, 255, .10);
  --voops-tint-heavy:  rgba(255, 255, 255, .42);

  /* Shadows and scrims. */
  --voops-shadow-soft: rgba(0, 0, 0, .30);
  --voops-shadow-mid:  rgba(0, 0, 0, .45);
  --voops-shadow-deep: rgba(0, 0, 0, .60);

  /* Opaque chrome surfaces. */
  --voops-bar-bg:       rgba(8, 8, 10, .95);
  --voops-bar-bg-solid: rgba(8, 8, 10, .985);
  --voops-scrim:        rgba(8, 8, 10, .62);
  --voops-scrim-fade:   rgba(8, 8, 10, .18);
  --voops-scrim-fade-2: rgba(8, 8, 10, .06);
  --voops-rail-bg:      rgba(22, 22, 25, .92);
  --voops-menu-bg:      rgba(26, 26, 30, .98);
  --voops-attention-bg: rgba(30, 16, 16, .9);

  /* Status washes and hairlines, one pair per state. */
  --voops-success-soft: rgba(47, 191, 113, .12);
  --voops-success-line: rgba(47, 191, 113, .30);
  --voops-warning-soft: rgba(245, 166, 35, .12);
  --voops-warning-line: rgba(245, 166, 35, .30);
  --voops-error-soft:   rgba(239, 68, 68, .12);
  --voops-error-line:   rgba(239, 68, 68, .35);
  --voops-error-wash:   rgba(239, 68, 68, .06);
  --voops-accent-line:  rgba(242, 83, 15, .30);
  --voops-info-soft:    rgba(76, 141, 255, .12);
  --voops-info-line:    rgba(76, 141, 255, .30);
  --voops-info:         #4c8dff;

  /* Chart series. Mid-tones chosen to sit on the dark ground; the light theme
     darkens them so they keep their contrast against white. */
  --voops-series-1: #f2530f;
  --voops-series-2: #ff9457;
  --voops-series-3: #9b6bd6;
  --voops-series-4: #3f8fd6;
  --voops-series-5: #4a5563;

  /* Text that sits ON a filled accent or status colour, never on the page. */
  --voops-on-accent: #fff;
  --voops-split-seam:  rgba(0, 0, 0, .22);
}

* { box-sizing: border-box; }
.voops-sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }

body {
  margin: 0;
  font-family: "Geist Mono", "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  background: var(--voops-bg);
  color: var(--voops-text);
  -webkit-font-smoothing: antialiased;
}

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

/* ─── Toasts: fixed top-right, plain message (no heading/icon) ─────────────── */
.voops-toasts { position: fixed; top: 16px; inset-inline-end: 16px; display: flex; flex-direction: column; gap: 8px; z-index: 1000; max-width: min(420px, calc(100vw - 32px)); }
.voops-toast {
  padding: 11px 16px; border-radius: var(--voops-radius-sm); font-size: 14px;
  color: var(--voops-text); background: var(--voops-surface-2);
  border: 1px solid var(--voops-border); border-inline-start: 3px solid var(--voops-border-2);
  box-shadow: 0 8px 28px var(--voops-shadow-mid); opacity: 1; transition: opacity .4s, transform .4s;
}
.voops-toast--out { opacity: 0; transform: translateY(-4px); }
.voops-toast--success { border-inline-start-color: var(--voops-success); }
.voops-toast--warning { border-inline-start-color: var(--voops-warning); }
.voops-toast--error   { border-inline-start-color: var(--voops-error); }

/* ─── Modal: header / content / footer (buttons in footer) ────────────────── */
.voops-modal { display: none; position: fixed; inset: 0; background: var(--voops-shadow-deep); backdrop-filter: blur(2px); align-items: center; justify-content: center; z-index: 900; }
.voops-modal.is-open { display: flex; }
.voops-modal__dialog { background: var(--voops-surface); border: 1px solid var(--voops-border); border-radius: var(--voops-radius); width: min(560px, 92vw); max-height: calc(100vh - 32px); overflow: hidden; box-shadow: 0 24px 60px var(--voops-shadow-mid); display: flex; flex-direction: column; }
.voops-modal__dialog > form { display: flex; flex: 1 1 auto; flex-direction: column; min-height: 0; }
.voops-modal__header { padding: 16px 20px; font-weight: 600; border-bottom: 1px solid var(--voops-border); }
.voops-modal__content { padding: 20px; color: var(--voops-muted); overflow-y: auto; overscroll-behavior: contain; }
.voops-modal__footer { padding: 14px 20px; display: flex; justify-content: flex-end; gap: 10px; border-top: 1px solid var(--voops-border); }
/* Wider dialog for a form with side-by-side fields (the rule editor). The default
   560px forces those into one column; this was named in the markup before it had a
   rule behind it, so the rule editor rendered at the narrow width. */
.voops-modal__dialog--wide { width: min(760px, 94vw); }

/* ─── Toggle switch: the ONLY checkbox-like control ───────────────────────── */
/* `flex: none` so the control keeps its size inside a flex row that also holds prose.
   The provider onboarding heads (`.ob-head`) are exactly that, and the switch they
   used to carry set `flex-shrink: 0` for the same reason. */
.voops-toggle { display: inline-flex; align-items: center; gap: 9px; cursor: pointer; font-size: 13px; color: var(--voops-muted); flex: none; }
.voops-toggle input { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; }
.voops-toggle__track { width: 38px; height: 21px; background: var(--voops-border-2); border-radius: 999px; position: relative; transition: background .2s; flex: none; }
.voops-toggle__thumb { position: absolute; top: 2px; left: 2px; width: 17px; height: 17px; background: var(--voops-on-accent); border-radius: 50%; transition: left .2s; }
.voops-toggle input:checked + .voops-toggle__track { background: var(--voops-accent); }
.voops-toggle input:checked + .voops-toggle__track .voops-toggle__thumb { left: 19px; }
.voops-toggle input:focus-visible + .voops-toggle__track { outline: 2px solid var(--voops-accent); outline-offset: 2px; }
/* The label is the only part of the switch allowed to give up width. `.voops-toggle`
   is `flex: none`, so without this a long label (or a long single word in a narrow
   settings column) pushes the track out of its row instead of wrapping. */
.voops-toggle__label { min-width: 0; overflow-wrap: anywhere; }

/* ─── Form primitives ─────────────────────────────────────────────────────── */
.voops-field { display: flex; flex-direction: column; gap: 7px; }
.voops-label { font-size: 13px; font-weight: 500; color: var(--voops-text); }
.voops-input {
  width: 100%; min-height: 40px; padding: 10px 14px; font-size: 14px;
  color: var(--voops-text); background: var(--voops-surface-2);
  border: 1px solid var(--voops-border); border-radius: var(--voops-radius-sm);
  transition: border-color .15s, box-shadow .15s;
}
.voops-input::placeholder { color: var(--voops-faint); }
.voops-input:focus { outline: none; border-color: var(--voops-accent); box-shadow: 0 0 0 3px var(--voops-accent-soft); }
.voops-input[type="file"] { padding: 7px; color: var(--voops-muted); }
.voops-input[type="file"]::file-selector-button {
  appearance: none; min-height: 30px; margin-inline-end: 10px; padding: 6px 11px;
  border: 1px solid var(--voops-border-2); border-radius: var(--voops-radius-sm);
  background: transparent; color: var(--voops-text); font: inherit; font-weight: 600; cursor: pointer;
}
.voops-input[type="file"]::file-selector-button:hover { background: var(--voops-tint); border-color: var(--voops-faint); }

/* Machine-readable values keep their visual order inside an Arabic page. */
input[type="email"], input[type="url"], input[type="date"], input[type="datetime-local"],
input[name*="email"], input[name*="domain"], input[name*="url"], input[name*="key"],
code, pre, .voops-mono, .voops-num, .voops-dns__detail {
  direction: ltr;
  unicode-bidi: isolate;
  text-align: left;
}

/* Tags / pills input (built by tags.js). The container reuses `.voops-input`
   styling; it holds pills + a borderless text input. */
.voops-tags { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; cursor: text; min-height: 40px; padding: 8px 10px; }
.voops-tags__list { display: contents; }
.voops-tag { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; min-width: 0; font-size: 12.5px; color: var(--voops-text); background: var(--voops-tint); border: 1px solid var(--voops-border-2); border-radius: 999px; padding: 3px 6px 3px 10px; }
.voops-tag__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.voops-tag__x { border: 0; background: none; color: var(--voops-muted); flex: 0 0 auto; font-size: 15px; line-height: 1; cursor: pointer; padding: 0 2px; border-radius: 50%; }
.voops-tag__x:hover { color: var(--voops-danger); }
.voops-tags__input { flex: 1; min-width: 120px; border: 0; outline: none; background: transparent; color: var(--voops-text); font-size: 14px; padding: 2px 0; }
.voops-tags__input::placeholder { color: var(--voops-faint); }
.voops-tags:focus-within { border-color: var(--voops-accent); box-shadow: 0 0 0 3px var(--voops-accent-soft); }

/* Split email input (built by emailfield.js): local-part box + "@" + trusted
   domain dropdown, sharing one `.voops-input` frame. */
.voops-emailbox { display: flex; align-items: center; gap: 6px; padding: 0 10px; min-height: 40px; }
.voops-emailbox__local { flex: 1; min-width: 80px; border: 0; outline: none; background: transparent; color: var(--voops-text); font-size: 14px; padding: 2px 0; }
.voops-emailbox__local::placeholder { color: var(--voops-faint); }
.voops-emailbox__at { color: var(--voops-muted); font-size: 14px; user-select: none; }
.voops-emailbox__domain { border: 0; outline: none; background: transparent; color: var(--voops-text); font-size: 14px; padding: 2px 0; cursor: pointer; max-width: 55%; }
.voops-emailbox__domain option { background: var(--voops-surface-2); color: var(--voops-text); }
.voops-emailbox:focus-within { border-color: var(--voops-accent); box-shadow: 0 0 0 3px var(--voops-accent-soft); }
/* Disabled state — the whole control (or a field gated on trusted domains). */
.voops-emailbox--disabled { opacity: .5; cursor: not-allowed; }
.voops-emailbox--disabled .voops-emailbox__local,
.voops-emailbox--disabled .voops-emailbox__domain { cursor: not-allowed; }
.voops-input--gated { opacity: .5; cursor: not-allowed; }

/* Native date input follows the active theme.

   ONE treatment, not two. `color-scheme: dark` already tells the browser to draw
   its built-in controls for a dark surface, and Chrome responds by picking a light
   calendar glyph. The old rule then ALSO applied `filter: invert(1)`, flipping that
   light glyph back to near-black against the dark field — the icon disappeared
   precisely because both fixes were applied at once, each correct on its own.

   `color-scheme` is the theme-safe half: it is declarative, the browser picks a
   glyph that contrasts with the scheme it is told about, and it keeps working if
   the palette changes. The inversion is the half that assumes what the browser
   drew, so it is the half that goes. Opacity still carries the resting/hover
   states, and the whole field remains the click target. */
input[type="date"].voops-input { color-scheme: inherit; cursor: pointer; }
input[type="date"].voops-input::-webkit-calendar-picker-indicator {
  opacity: .7; cursor: pointer;
}
input[type="date"].voops-input::-webkit-calendar-picker-indicator:hover { opacity: 1; }

/* Read-only skeleton (license expired): shimmering placeholder blocks shown in
   place of real portal data. */
.voops-skeleton { display: grid; gap: 12px; margin-top: 8px; }
.voops-skeleton__row {
  height: 44px; border-radius: 10px;
  background: linear-gradient(90deg,
    var(--voops-tint-weak) 25%, var(--voops-tint-strong) 37%, var(--voops-tint-weak) 63%);
  background-size: 400% 100%;
  animation: voops-shimmer 1.4s ease-in-out infinite;
}
.voops-skeleton__row--head { height: 28px; width: 40%; }
@keyframes voops-shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }
@media (prefers-reduced-motion: reduce) { .voops-skeleton__row { animation: none; } }
.voops-lockbanner {
  display: flex; gap: 10px; align-items: flex-start; margin-bottom: 16px;
  padding: 14px 16px; border-radius: 12px;
  border: 1px solid var(--voops-danger);
  background: var(--voops-error-wash); color: var(--voops-text);
}
.voops-lockbanner strong { display: block; margin-bottom: 2px; }

/* Required-field marker (added by forms.js) + failed-validation outline.
   Higher-specificity selector so the red beats `.voops-label`'s inherited color. */
.voops-label .voops-req,
.voops-req { color: var(--voops-danger); font-weight: 700; }
/* Invalid outline — higher specificity than `.voops-input:focus` so it wins even
   when the field is focused, and applies to input/select/textarea alike. */
.voops-input.voops-input--invalid,
.voops-input.voops-input--invalid:focus,
select.voops-input--invalid,
textarea.voops-input--invalid {
  border-color: var(--voops-danger) !important;
  box-shadow: 0 0 0 3px var(--voops-error-soft) !important;
  background: var(--voops-error-wash);
}

/* input with a trailing icon-button (e.g. password reveal) */
.voops-input-wrap { position: relative; display: flex; align-items: center; }
.voops-input-wrap .voops-input { padding-inline-end: 44px; }
.voops-input-icon {
  position: absolute; inset-inline-end: 6px; display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border: 0; background: transparent; color: var(--voops-faint);
  cursor: pointer; border-radius: var(--voops-radius-xs);
}
.voops-input-icon:hover { color: var(--voops-text); background: var(--voops-elevated); }

/* ─── Buttons ─────────────────────────────────────────────────────────────── */
.voops-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 40px; padding: 10px 16px; font-size: 14px; font-weight: 600; cursor: pointer;
  border-radius: var(--voops-radius-sm); border: 1px solid transparent; width: auto;
  appearance: none; background: transparent; color: inherit; font-family: inherit; line-height: 1.2;
  text-decoration: none;
  /* A button label must never wrap. In a filter bar the input takes width: 100%,
     so flex-shrink squeezes neighbouring buttons below their content width; a
     wrapping label then doubles the control's height and the row stops being
     level. Overflowing on one line is the correct failure, not growing taller. */
  white-space: nowrap;
  transition: background .15s, border-color .15s, color .15s;
}
.voops-btn--primary {
  background: var(--voops-accent-grad); color: var(--voops-on-accent);
  border-color: var(--voops-tint); box-shadow: var(--voops-btn-highlight);
}
.voops-btn--primary:hover, a.voops-btn--primary:hover {
  color: var(--voops-on-accent); filter: brightness(1.07);
  box-shadow: 0 4px 14px var(--voops-accent-glow), var(--voops-btn-highlight);
}
.voops-btn--ghost { background: transparent; color: var(--voops-text); border-color: var(--voops-border-2); }
.voops-btn--ghost:hover { background: var(--voops-elevated); }
.voops-btn:disabled { opacity: .55; cursor: not-allowed; }
.voops-partner-actions, .voops-partner-account-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.voops-partner-account-actions { margin-top: 16px; }
.voops-stats--partner { margin-bottom: 28px; }
.voops-dashboard-empty { min-height: 220px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px; }
.voops-dashboard-empty--wide, .voops-dashboard-clients--wide { grid-column: 1 / -1; }
.voops-dashboard-estates, .voops-dashboard-clients { min-width: 0; }
.voops-dashboard-estates__head { display: flex; justify-content: space-between; align-items: end; gap: 24px; margin-bottom: 14px; }
.voops-dashboard-estates__head h2, .voops-dashboard-clients h2 { margin: 0 0 4px; font-size: 18px; }
.voops-dashboard-estates__head p { margin: 0; color: var(--voops-muted); font-size: 13px; }
.voops-dashboard-filter { min-width: min(320px, 100%); }
.voops-dashboard-filter label { display: block; margin-bottom: 6px; color: var(--voops-muted); font-size: 12px; }
.voops-estate-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(360px, 100%), 1fr)); gap: 12px; }
.voops-estate { display: flex; align-items: center; justify-content: space-between; gap: 20px; padding: 18px; color: var(--voops-text); border: 1px solid var(--voops-border); border-radius: var(--voops-radius); background: var(--voops-surface); }
.voops-estate:hover { color: var(--voops-text); border-color: var(--voops-accent); background: var(--voops-elevated); }
.voops-estate strong, .voops-estate span { display: block; }
.voops-estate > div > span { margin-top: 4px; color: var(--voops-muted); font-size: 13px; }
.voops-estate__meta { display: flex; align-items: center; gap: 10px; color: var(--voops-muted); white-space: nowrap; }
.voops-estate__meta span { margin: 0; }
@media (max-width: 720px) {
  .voops-dashboard-estates__head { align-items: stretch; flex-direction: column; }
  .voops-dashboard-filter { width: 100%; }
  .voops-estate { align-items: flex-start; flex-direction: column; }
}

/* ─── Icons (Nucleo, inlined via the icon() macro; theme via currentColor) ── */
.voops-ico { display: block; flex: none; }

/* ─── Login page (two-pane panel per mockup) ──────────────────────────────── */
.voops-auth { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 24px; }
.voops-auth__panel {
  position: relative;
  display: flex; width: min(1120px, 100%); min-height: 620px;
  background: var(--voops-surface); border: 1px solid var(--voops-border);
  border-radius: 20px; overflow: hidden; box-shadow: 0 30px 80px var(--voops-shadow-deep);
}
.voops-auth__form {
  flex: 0 0 52%; padding: 48px 52px; position: relative; z-index: 2;
  display: flex; flex-direction: column; justify-content: center;
}
/* The backdrop: one static SVG code field, generated once and served from our own
   origin because `font-src`/`img-src` are 'self'. `cover` guarantees it fills the
   panel at every aspect ratio, so it can never under-fill and leave a bare corner.
   Steel, not accent, so it does not compete with the orange on top of it. No
   animation and no script — this is the first page an unauthenticated visitor sees. */
.voops-auth__panel::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image: url("/assets/images/login-code-field.svg");
  background-size: cover; background-position: center;
}
/* Near-opaque under the form, clear at the trailing edge. */
.voops-auth__panel::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    linear-gradient(90deg, var(--voops-bar-bg-solid) 0, var(--voops-bar-bg) 26%,
                    var(--voops-scrim) 55%, var(--voops-scrim-fade) 82%, var(--voops-scrim-fade-2) 100%),
    radial-gradient(64% 58% at 10% 28%, var(--voops-accent-soft), transparent 64%);
}
/* A gradient has a direction; logical properties do not mirror one. */
html[dir="rtl"] .voops-auth__panel::after { transform: scaleX(-1); }
/* ── SecOps wordmark ──────────────────────────────────────────────────────────
   The mark is an inline SVG whose letters are `currentColor`, so it follows the
   theme with no second asset and no blend-mode trick. Sizing rules set ONE
   dimension; the SVG's own viewBox supplies the other. */
.voops-wordmark { display: block; color: var(--voops-text); }
.voops-wordmark__svg { display: block; width: 100%; height: 100%; }

.voops-auth__logo { width: 250px; max-width: 70%; height: auto; align-self: flex-start; margin-bottom: 30px; }
.voops-auth__title { font-size: 27px; font-weight: 700; margin: 0 0 6px; }
.voops-auth__subtitle { font-size: 14px; color: var(--voops-muted); margin: 0 0 30px; }
.voops-auth form { display: flex; flex-direction: column; gap: 18px; }
.voops-auth__row { display: flex; align-items: center; justify-content: space-between; font-size: 13px; }
.voops-auth__sep { display: flex; align-items: center; gap: 12px; color: var(--voops-faint); font-size: 12px; margin: 2px 0; }
.voops-auth__sep::before, .voops-auth__sep::after { content: ""; flex: 1; height: 1px; background: var(--voops-border); }
.voops-auth__legal { font-size: 12px; color: var(--voops-faint); text-align: center; margin: 14px 0 0; line-height: 1.5; }
.voops-auth__notice { margin: 18px 0 4px; padding: 14px 16px; background: var(--voops-success-soft); border: 1px solid var(--voops-success-line); border-radius: var(--voops-radius); font-size: 13px; color: var(--voops-text); line-height: 1.5; }
.voops-auth__notice p { margin: 0; }

/* Proof-of-work solver status (multi-round; button stays disabled until done) */
.voops-auth__pow { min-height: 16px; text-align: center; }
.voops-auth__pow-status { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--voops-muted); }
.voops-auth__pow-ready { font-size: 12px; color: var(--voops-success); }
@keyframes spin { to { transform: rotate(360deg); } }

/* Right pane: fixed dashboard composition, deliberately without loading skeletons. */

@media (max-width: 900px) {
  .voops-auth__form { flex: 1; }
  /* The form covers the whole panel at this width, so the artwork is only
     visible as texture behind it. Dim it rather than removing it. */
  .voops-auth__panel::before { opacity: .45; }
}

/* ─── Authenticated shell (per-role landing) ──────────────────────────────── */
.voops-shell { min-height: 100vh; display: flex; flex-direction: column; }
.voops-topbar { display: flex; align-items: center; gap: 16px; padding: 14px 22px; border-bottom: 1px solid var(--voops-border); background: var(--voops-surface); }
.voops-topbar__logo { height: 24px; width: auto; }
.voops-topbar__spacer { flex: 1; }
.voops-topbar__user { font-size: 13px; color: var(--voops-muted); }
.voops-topbar__signout { width: auto; padding: 8px 14px; }
.voops-shell__body { flex: 1; display: flex; align-items: flex-start; justify-content: center; padding: 48px 22px; }
.voops-card {
  position: relative; background: var(--voops-card-bg);
  border: 1px solid var(--voops-border); border-radius: var(--voops-radius-lg);
  padding: 32px; box-shadow: var(--voops-card-shadow);
}
/* A 1px top highlight is what lifts a card off a near-black ground; raising the
   fill instead would glare. Fades at both ends so it never reads as a border. */
.voops-card::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 1px;
  border-radius: var(--voops-radius-lg) var(--voops-radius-lg) 0 0;
  background: linear-gradient(90deg, transparent, var(--voops-tint-strong) 22%,
                              var(--voops-tint-strong) 78%, transparent);
}
.voops-content__body > .voops-card + .voops-card { margin-top: 18px; }
.voops-card--form-sm { max-width: 560px; }
.voops-card--form-md { max-width: 640px; }
.voops-card--form-lg { max-width: 760px; }
.voops-form-stack { display: flex; flex-direction: column; gap: 16px; }
/* The full-page rule builder. One card per decision, a bounded measure so the
   inputs do not stretch to a 1440px viewport, and the commit pair pinned to the
   end of the flow rather than floating in a dialog footer. */
/* Window selector on the gap trend. Links, not buttons: each window is a real
   URL, so a chosen window survives a filter change and can be shared. */
.voops-trend__window {
  display: inline-flex; align-items: center; min-height: 32px; padding: 0 12px;
  border: 1px solid var(--voops-border); border-radius: 999px;
  color: var(--voops-muted); text-decoration: none; font-size: 13px; font-weight: 600;
}
.voops-trend__window:hover { border-color: var(--voops-border-2); color: var(--voops-text); }
.voops-trend__window.is-active {
  border-color: var(--voops-accent); color: var(--voops-accent);
  background: var(--voops-accent-soft);
}

/* ── Right-hand conversation panel ────────────────────────────────────────────
   90% of the viewport on a phone, a bounded column on a desktop: a conversation
   does not get easier to read at 1400px. The composer is pinned to the bottom
   and the log scrolls above it, so the input stays where the hand expects it
   however long the exchange runs. */
.voops-drawer-panel { position: fixed; inset: 0; z-index: 1000; }
.voops-drawer-panel[hidden] { display: none; }
.voops-drawer-panel__scrim { position: absolute; inset: 0; background: var(--voops-scrim); }
.voops-drawer-panel__body {
  position: absolute; inset-block: 0; inset-inline-end: 0;
  width: 90vw; display: flex; flex-direction: column;
  background: var(--voops-surface); border-inline-start: 1px solid var(--voops-border);
  box-shadow: -20px 0 60px var(--voops-shadow-deep);
}
.voops-drawer-panel__head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 18px 20px; border-bottom: 1px solid var(--voops-border);
}
.voops-drawer-panel__head h2 { margin: 0; font-size: 16px; }
.voops-drawer-panel__log {
  flex: 1; overflow-y: auto; padding: 18px 20px;
  display: flex; flex-direction: column; gap: 12px;
}
/* The panel is wide; the reading measure is not. Centring the flow keeps line
   length sane without shrinking the surface the user asked for. */
.voops-drawer-panel__log,
.voops-drawer-panel__composer,
.voops-drawer-panel__draft { margin-inline: auto; width: min(100%, 860px); }
.voops-drawer-panel__msg {
  margin: 0; padding: 11px 13px; border-radius: var(--voops-radius-sm);
  font-size: 14px; line-height: 1.55; max-width: 92%; white-space: pre-wrap;
}
.voops-drawer-panel__msg.is-you {
  align-self: flex-end; background: var(--voops-accent-soft);
  border: 1px solid var(--voops-accent-line); color: var(--voops-text);
}
.voops-drawer-panel__msg.is-ai {
  align-self: flex-start; background: var(--voops-surface-2);
  border: 1px solid var(--voops-border); color: var(--voops-text);
}
.voops-drawer-panel__msg.is-error {
  align-self: flex-start; background: var(--voops-error-soft);
  border: 1px solid var(--voops-error-line); color: var(--voops-error);
}
.voops-drawer-panel__draft {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 14px 20px; border-top: 1px solid var(--voops-border);
  background: var(--voops-surface-2);
}
.voops-drawer-panel__draft .voops-hint { margin: 0; }
.voops-drawer-panel__draft[hidden] { display: none; }
.voops-drawer-panel__composer {
  display: flex; align-items: flex-end; gap: 10px;
  padding: 14px 20px 18px; border-top: 1px solid var(--voops-border);
}
.voops-drawer-panel__composer .voops-input { flex: 1; resize: vertical; }

.voops-rule-form { display: flex; flex-direction: column; gap: 18px; }
/* Two columns, packed by height rather than by row. CSS columns give true
   masonry here — the five sections are wildly different heights, and a grid
   would leave a tall Actions card dragging a short Recovery card's row down
   with it. `break-inside: avoid` keeps a card whole. */
.voops-rule-form__cards { columns: 2; column-gap: 20px; }
.voops-rule-form__card {
  margin: 0 0 20px; break-inside: avoid; -webkit-column-break-inside: avoid;
  display: inline-block; width: 100%;
}
/* One column per card now that each card is half the page. */
.voops-rule-form .voops-form-stack {
  display: flex; flex-direction: column; gap: 16px;
}
@media (max-width: 900px) {
  .voops-rule-form__cards { columns: 1; }
}

/* Wraps: at phone width a longer translation of the commit pair ("Regel erstellen")
   would otherwise push the primary button past the edge of the page. */
.voops-rule-form__footer {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px; padding-top: 4px;
}
/* Pushes the commit pair to the end, leaving the arm-on-create toggle at the
   start where it reads as a property of the rule rather than a third button. */
.voops-rule-form__spacer { flex: 1; }
/* The editor hides whole fields and cards by signal (a Workbench alert has no duration
   or recovery). Those carry their own `display`, which outranks the `hidden` attribute,
   so both rule forms restate it — the per-component pattern used for every other
   hideable part in this sheet. */
[data-rule-form] [hidden] { display: none; }

/* Field sizing inside the rule form.

   Every control was stretching to the card width, so a threshold of "80" got the
   same 500px box as a rule name. Controls are sized to what they hold: numbers
   stay short, dropdowns take their content, and only free text spans. */
.voops-rule-form .voops-field { align-items: start; min-width: 0; }
.voops-rule-form .voops-field > .voops-label { align-self: stretch; }
.voops-rule-form input[type="number"] { width: 130px; min-width: 0; }
.voops-rule-form .voops-select { width: auto; max-width: 100%; }
.voops-rule-form input[type="text"],
.voops-rule-form textarea,
.voops-rule-form .voops-multiselect,
.voops-rule-form .voops-single-select { align-self: stretch; width: 100%; }
/* A labelled row of short controls: "below · 80 · for 60 minutes". Wraps to
   the next line rather than shrinking, so a narrow column keeps each box at a
   usable width instead of squeezing three onto one cramped line. */
.voops-inline-fields { display: flex; flex-wrap: wrap; gap: 12px; align-items: end; }
.voops-subfield { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.voops-subfield > span {
  font-size: 11.5px; font-weight: 600; color: var(--voops-faint);
  letter-spacing: .02em;
}
.voops-subfield input[type="number"] { width: 104px; }
.voops-subfield .voops-select { width: auto; min-width: 132px; max-width: 100%; }

/* Below the masonry breakpoint the cards are full width but the viewport is
   narrow, so the row stacks and every control takes the line. Sized controls
   that cannot shrink are what pushed the field past the card edge. */
@media (max-width: 560px) {
  .voops-subfield { flex: 1 1 100%; }
  .voops-subfield input[type="number"],
  .voops-subfield .voops-select { width: 100%; min-width: 0; }
  .voops-rule-form .voops-select { width: 100%; }
}
.voops-notice--inline {
  margin: 0; padding: 11px 13px; border-radius: var(--voops-radius-sm);
  background: var(--voops-accent-soft); border: 1px solid var(--voops-accent-line);
  color: var(--voops-muted); font-size: 13px; line-height: 1.5;
}
.voops-section-stack { display: flex; flex-direction: column; gap: 20px; }
.voops-space-before { margin-top: 28px; }
.voops-space-after { margin-bottom: 28px; }
.voops-hidden { display: none !important; }
.voops-spin { animation: spin 1s linear infinite; }
.voops-field--narrow { max-width: 320px; }
.voops-field--compact { max-width: 220px; }
.voops-table-field { width: 100%; max-width: 140px; }
.voops-table__control-cell { vertical-align: middle; }
.voops-table__control-cell .voops-table-field { display: block; margin: 0; }
.voops-formchecks { display: flex; flex-wrap: wrap; gap: 14px 20px; }
.voops-formchecks--spaced { margin-top: 16px; }
.voops-toggle--spaced { margin-bottom: 14px; }
.voops-toggle--section { margin: 20px 0 14px; }
.voops-table-wrap--spaced, .voops-empty--spaced { margin-top: 16px; }
.voops-welcome { max-width: 560px; width: 100%; }
.voops-welcome h1 { font-size: 22px; font-weight: 700; margin: 0 0 6px; }
.voops-welcome__sub { font-size: 14px; color: var(--voops-muted); margin: 0 0 22px; }
.voops-meta { display: grid; grid-template-columns: auto 1fr; gap: 6px 16px; margin: 0 0 22px; font-size: 13px; }
.voops-meta dt { color: var(--voops-faint); }
.voops-meta dd { margin: 0; color: var(--voops-text); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.voops-welcome__soon { font-size: 13px; color: var(--voops-muted); background: var(--voops-surface-2); border: 1px solid var(--voops-border); border-radius: var(--voops-radius-sm); padding: 12px 14px; margin: 0; }

/* ─── Admin plane (partners) ──────────────────────────────────────────────── */
.voops-btn--auto { width: auto; }
.voops-btn--block { width: 100%; }
.voops-btn--sm { width: auto; min-height: 34px; padding: 6px 12px; font-size: 13px; }
.voops-btn--danger { background: transparent; color: var(--voops-error); border-color: var(--voops-error-line); }
.voops-btn--danger:hover { background: var(--voops-error-soft); }
.voops-cell--end, .voops-table th.voops-cell--end { text-align: end; }
.voops-table__actions { display: flex; min-width: 0; align-items: center; justify-content: flex-end; gap: 6px; flex-wrap: wrap; }

.voops-admin { max-width: 960px; margin: 0 auto; padding: 40px 24px 80px; width: 100%; }
.voops-admin__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 26px; }
.voops-admin__head h1 { font-size: 24px; font-weight: 700; margin: 0 0 4px; }
.voops-admin__sub { font-size: 14px; color: var(--voops-muted); margin: 0; }

.voops-table { width: 100%; border-collapse: separate; border-spacing: 0; background: var(--voops-surface); border: 1px solid var(--voops-border); border-radius: var(--voops-radius); overflow: hidden; }
.voops-table th { text-align: start; font-size: 12px; font-weight: 600; color: var(--voops-accent); text-transform: uppercase; letter-spacing: .04em; padding: 12px 16px; border-bottom: 1px solid var(--voops-border); }
.voops-table td { vertical-align: middle; font-size: 14px; padding: 14px 16px; border-bottom: 1px solid var(--voops-border); }
.voops-table tbody tr:last-child td { border-bottom: 0; }
.voops-table__muted { color: var(--voops-muted); }
.voops-table--stable { table-layout: fixed; }
.voops-table--min-640 { min-width: 640px; }
.voops-table--min-760 { min-width: 760px; }
.voops-table--min-900 { min-width: 900px; }
.voops-table--min-1100 { min-width: 1100px; }
.voops-table--min-1280 { min-width: 1280px; }
.voops-table--clients,
.voops-table--users { width: 100%; min-width: 0; table-layout: fixed; }
/* Fit-to-width like the two above wherever its container is at least 760px wide, but
   no narrower: the template adds `voops-table--min-760`, so on tablet and phone widths
   the table scrolls inside its `voops-table-wrap` instead of squeezing seven columns
   until the row actions overflow their cell and are clipped. */
.voops-table--integrations { width: 100%; table-layout: fixed; }
.voops-table--integrations .voops-table__actions { justify-content: flex-end; }
.voops-table--integrations .voops-alertcell { min-width: 0; }
.voops-integration-col--name { width: 13%; }
.voops-integration-col--kind { width: 10%; }
/* The one column without a width: it takes whatever the others leave. */
.voops-integration-col--client { width: auto; }
.voops-integration-col--region { width: 10%; }
.voops-integration-col--status { width: 10%; }
.voops-integration-col--alerts { width: 17%; }
/* Fixed, not a share of the table. Row action labels never wrap (the shared button
   contract) and the cell clips, so the column must hold the widest translated label:
   German "API-Schlüssel ersetzen" measures 173px, and 224px less the cell's 32px
   padding leaves 192px. A percentage gave 120px at the table's 760px minimum, which
   clipped that label in five locales and the English ones too. */
.voops-integration-col--actions { width: 224px; }
.voops-table--users td,
.voops-table--clients td,
.voops-table--integrations td { overflow: hidden; }
.voops-inline-action { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; }
.voops-inline-action svg { flex: none; }
.voops-field--spaced { margin-top: 18px; }
.voops-field--dialog { gap: 10px; }
.voops-table--distribution col:last-child { width: 132px; }
.voops-table--feature-adoption col:last-child { width: 132px; }
.voops-table--distribution th:last-child,
.voops-table--distribution td:last-child,
.voops-table--feature-adoption th:last-child,
.voops-table--feature-adoption td:last-child { text-align: right; white-space: nowrap; }
.voops-table--tickets { min-width: 0; }
.voops-table--tickets .voops-col--ref { width: 7%; }
.voops-table--tickets .voops-col--wide { width: 22%; }
.voops-table--tickets .voops-col--medium { width: 15%; }
.voops-table--tickets .voops-col--priority { width: 9%; }
.voops-table--tickets .voops-col--status { width: 10%; }
.voops-table--tickets .voops-col--sla { width: 12%; }
.voops-table--tickets .voops-col--date { width: 10%; }
.voops-table--report-schedules { min-width: 0; }
.voops-report-col--customer { width: 20%; }
.voops-report-col--type { width: 15%; }
.voops-report-col--cadence { width: 14%; }
.voops-report-col--language { width: 10%; }
.voops-report-col--recipients { width: 8%; }
.voops-report-col--status { width: 10%; }
.voops-report-col--actions { width: 23%; }
.voops-rules-table { min-width: 1100px; }
.voops-rules-col--name { width: 18%; }
.voops-rules-col--scope { width: 13%; }
.voops-rules-col--condition { width: 20%; }
.voops-rules-col--actions { width: 13%; }
.voops-rules-col--status { width: 9%; }
.voops-rules-col--triggered { width: 13%; }
.voops-rules-col--manage { width: 108px; }
.voops-rules-table__text { overflow-wrap: break-word; }
.voops-rules-table__manage { flex-wrap: nowrap; }
.voops-col--number { width: 96px; }
.voops-col--ref { width: 110px; }
.voops-col--priority { width: 105px; }
.voops-col--sla { width: 170px; }
.voops-col--status { width: 132px; }
.voops-col--date { width: 210px; }
.voops-col--short { width: 150px; }
.voops-col--medium { width: 220px; }
.voops-col--wide { width: 300px; }
.voops-col--email { width: 240px; }
.voops-col--actions-sm { width: 150px; }
.voops-col--actions-md { width: 220px; }
.voops-col--actions-lg { width: 300px; }
/* Client profiles: Edit + Disable + "Delete permanently" measure ~300px of
   buttons before the cell's own padding, so at `actions-lg` the last button
   wrapped onto a second line. The row keeps all three on one line. */
.voops-col--actions-xl { width: 360px; }
.voops-cell--truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.voops-cell--wrap { overflow-wrap: anywhere; }
.voops-table th.voops-cell--number,
.voops-table td.voops-cell--number { text-align: end; font-variant-numeric: tabular-nums; }
.voops-table__action-cell { text-align: end; }
.voops-table__action-cell .voops-inline-form { margin-top: 0; flex-wrap: nowrap; }
/* Inline secondary text — e.g. the "Disabled" marker after a client's name, which
   must read as a qualifier of the name rather than as part of it. */
.voops-muted { color: var(--voops-muted); }

.voops-badge {
  display: inline-block; font-size: 11px; font-weight: 700; letter-spacing: .07em;
  padding: 5px 12px; border-radius: 999px; border: 1px solid transparent;
  text-transform: none; white-space: nowrap;
}
.voops-badge--active { color: var(--voops-success); background: var(--voops-success-soft); border-color: var(--voops-success-line); }
.voops-badge--suspended { color: var(--voops-warning); background: var(--voops-warning-soft); border-color: var(--voops-warning-line); }
.voops-badge--deletion_pending { color: var(--voops-danger); background: var(--voops-error-soft); border-color: var(--voops-error-line); }
/* Marks the entry explaining why a ticket was resolved, so it is findable in a
   long thread without re-reading it. Uses the success token the resolved status
   already uses, so the two read as the same idea. */
.voops-badge--resolution { color: var(--voops-success); background: var(--voops-success-soft); border-color: var(--voops-success-line); }
.voops-badge--invited { color: var(--voops-accent); background: var(--voops-accent-soft); border-color: var(--voops-accent-line); }
.voops-badge--incident { color: var(--voops-danger); background: var(--voops-error-soft); border-color: var(--voops-error-line); }
.voops-badge--healthy { color: var(--voops-success); background: var(--voops-success-soft); border-color: var(--voops-success-line); }
.voops-alertcell { min-width: 190px; }
.voops-alertcell__pending { color: var(--voops-warning); }
/* Workbench collection status under the alert badges (WB-1): a badge and up to three
   short lines, stacked so a long translation grows the row rather than the column.
   `minmax(0, 1fr)` rather than the implicit `auto` track: an auto track is never
   narrower than the longest unbreakable word, and at the table's 760px minimum the
   column has under 100px — German "möglicherweise" or French "automatiquement" alone
   pushed the whole block past the cell edge, where it was clipped. `anywhere` lets
   such a word break instead. */
.voops-alertcell__workbench { display: grid; grid-template-columns: minmax(0, 1fr); gap: 4px; justify-items: start; margin-top: 8px; min-width: 0; overflow-wrap: anywhere; }
/* A status badge allowed to wrap. The base badge is `nowrap`, which is right for short
   chips but clips inside a narrow fixed-layout cell whose `td` hides overflow — the
   integrations Alerts column is under 100px of content at the table's 760px minimum.
   Composes with any colour modifier. */
.voops-badge--wrap { white-space: normal; overflow-wrap: anywhere; max-width: 100%; line-height: 1.35; }
.voops-badge--disabled { color: var(--voops-faint); background: var(--voops-tint); border-color: var(--voops-border-2); }
.voops-badge--verified,
.voops-badge--tampered { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; text-transform: none; }
.voops-badge--verified { color: var(--voops-success); background: var(--voops-success-soft); border-color: var(--voops-success-line); }
.voops-badge--tampered { color: var(--voops-danger); background: var(--voops-error-soft); border-color: var(--voops-error-line); }
.voops-badge--verified .voops-ico,
.voops-badge--tampered .voops-ico { flex: none; }

/* Small "superscript" chip pinned to the top of a page title. */
.voops-title-with-badge { display: inline-flex; align-items: flex-start; gap: 10px; }
.voops-badge--sup { align-self: flex-start; margin-top: .15em; font-size: 11px; padding: 2px 8px; }
/* Action names are dotted identifiers with no spaces, and the base badge is
   `white-space: nowrap`. In the audit log's fixed-layout table that made a long
   one — `settings.trendai.alerting.update` — run straight out of its 220px
   column and across the next, which is the reported column overlap. It wraps
   here instead; `anywhere` rather than `break-word` because there is no space
   in the string to break at. */
.voops-badge--action { color: var(--voops-muted); background: var(--voops-tint); border-color: var(--voops-border-2); text-transform: none; font-family: var(--voops-mono, ui-monospace, SFMono-Regular, Menlo, monospace); font-weight: 500; white-space: normal; overflow-wrap: anywhere; max-width: 100%; }
.voops-badge--lane-tx { color: var(--voops-accent); background: var(--voops-accent-soft); border-color: var(--voops-accent-line); text-transform: none; }
.voops-badge--lane-bulk { color: var(--voops-faint); background: var(--voops-tint); border-color: var(--voops-border-2); text-transform: none; }

/* Ticket priority + status badges */
.voops-badge--prio-p1 { color: var(--voops-danger); background: var(--voops-error-soft); border-color: var(--voops-error-line); text-transform: none; }
.voops-badge--prio-p2 { color: var(--voops-warning); background: var(--voops-warning-soft); border-color: var(--voops-warning-line); text-transform: none; }
.voops-badge--prio-p3 { color: var(--voops-muted); background: var(--voops-tint); border-color: var(--voops-border-2); text-transform: none; }
.voops-badge--prio-p4 { color: var(--voops-faint); background: var(--voops-tint-weak); border-color: var(--voops-border-2); text-transform: none; }
.voops-badge--tkt-open { color: var(--voops-accent); background: var(--voops-accent-soft); border-color: var(--voops-accent-line); text-transform: none; }
.voops-badge--tkt-in_progress { color: var(--voops-info); background: var(--voops-info-soft); border-color: var(--voops-info-line); text-transform: none; }
.voops-badge--tkt-on_hold { color: var(--voops-warning); background: var(--voops-warning-soft); border-color: var(--voops-warning-line); text-transform: none; }
.voops-badge--tkt-resolved { color: var(--voops-success); background: var(--voops-success-soft); border-color: var(--voops-success-line); text-transform: none; }
.voops-badge--tkt-closed { color: var(--voops-faint); background: var(--voops-tint); border-color: var(--voops-border-2); text-transform: none; }

/* Ticket queue rows are clickable */
.voops-tickets__row { cursor: pointer; }
.voops-tickets__row:hover td { background: var(--voops-tint-weak); }
.voops-tickets__ref { font-family: var(--voops-mono, ui-monospace, SFMono-Regular, Menlo, monospace); font-size: 13px; color: var(--voops-muted); white-space: nowrap; }
.voops-tickets__title { font-weight: 500; }

/* Ticket detail: two-column main + side */
/* `minmax(0, 1fr)`, not `1fr`: a bare `1fr` column grows to its widest unbreakable
   content, which in longer languages pushed the ticket past a phone's width. */
.voops-ticket { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 20px; align-items: start; }
@media (max-width: 900px) { .voops-ticket { grid-template-columns: minmax(0, 1fr); } }
.voops-ticket-create { width: 100%; }
.voops-ticket-create__form { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; }
.voops-ticket-create__wide { grid-column: 1 / -1; }
.voops-ticket-create__submit { grid-column: 1 / -1; justify-self: start; }
.voops-ai-drawer-toggle {
  position: fixed; z-index: 71; inset-inline-end: 0; top: 50%;
  display: inline-flex; align-items: center; gap: 7px; padding: 11px 13px;
  color: var(--voops-on-accent); background: var(--voops-accent); border: 0;
  border-radius: 8px 0 0 8px; font: inherit; font-size: 12px; font-weight: 700;
  cursor: pointer; box-shadow: 0 10px 30px var(--voops-shadow-soft);
}
.voops-ai-drawer-toggle:hover { background: var(--voops-accent-hover); }
[dir="rtl"] .voops-ai-drawer-toggle { border-radius: 0 8px 8px 0; }
.voops-ai-drawer {
  position: fixed; z-index: 72; inset-block: 0; inset-inline-end: 0;
  width: min(440px, 100vw); display: flex; flex-direction: column;
  color: var(--voops-text); background: var(--voops-bg);
  border-inline-start: 1px solid var(--voops-border-2);
  box-shadow: -18px 0 50px var(--voops-shadow-mid);
  transform: translateX(102%); visibility: hidden;
  transition: transform .2s ease, visibility .2s;
}
[dir="rtl"] .voops-ai-drawer { transform: translateX(-102%); }
.voops-ai-drawer.is-open { transform: translateX(0); visibility: visible; }
.voops-ai-drawer__head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 18px;
  padding: 22px 22px 18px; border-bottom: 1px solid var(--voops-border);
}
.voops-ai-drawer__head h2 { margin: 0 0 5px; font-size: 18px; }
.voops-ai-drawer__head p { margin: 0; color: var(--voops-muted); font-size: 12px; line-height: 1.5; }
.voops-icon-btn {
  flex: none; width: 36px; height: 36px; display: inline-flex; align-items: center;
  justify-content: center; padding: 0; color: var(--voops-muted);
  background: transparent; border: 1px solid var(--voops-border-2); border-radius: 6px;
  cursor: pointer;
}
.voops-icon-btn:hover { color: var(--voops-text); background: var(--voops-surface); }
.voops-ai-drawer__body { display: flex; flex-direction: column; gap: 16px; padding: 22px; overflow-y: auto; }
.voops-ai-drawer__body textarea { min-height: 210px; resize: vertical; }
.voops-ai-drawer__status { min-height: 20px; margin: 0; color: var(--voops-muted); font-size: 12px; line-height: 1.5; }
.voops-ai-drawer__status.is-success { color: var(--voops-success); }
.voops-ai-drawer__status.is-error { color: var(--voops-danger); }
@media (max-width: 900px) {
  .voops-ticket-create__form { grid-template-columns: 1fr; }
  .voops-ticket-create__wide,
  .voops-ticket-create__submit { grid-column: 1; }
  .voops-ai-drawer-toggle { top: auto; bottom: 22px; }
}
.voops-ticket__desc { white-space: pre-wrap; font-size: 14px; line-height: 1.6; }
.voops-ticket__meta { font-size: 12px; color: var(--voops-faint); margin: 12px 0 0; }
.voops-ticket__reply {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 12px;
  margin-top: 18px;
  min-width: 0;
  width: 100%;
}
.voops-ticket__reply > .voops-ed { min-width: 0; width: 100%; }
.voops-ticket__reply > .voops-btn { align-self: flex-start; }

/* Wraps when the author, badges and time do not fit on one line (a long Vision One
   author name, a longer language, a phone). */
.voops-thread__head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 4px 8px; font-size: 13px; margin-bottom: 6px; }
.voops-thread__body { white-space: pre-wrap; font-size: 14px; line-height: 1.55; }

/* Initials avatar chip (reused for the opener + comments) */
.voops-avatar-chip { flex: none; width: 32px; height: 32px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 700; color: var(--voops-text); background: var(--voops-surface-2, var(--voops-tint-strong)); border: 1px solid var(--voops-border-2); letter-spacing: .02em; }
.voops-avatar-chip--me { color: var(--voops-accent); background: var(--voops-accent-soft); border-color: var(--voops-accent-line); }
.voops-you { font-size: 11px; font-weight: 600; color: var(--voops-accent); background: var(--voops-accent-soft); border: 1px solid var(--voops-accent-line); border-radius: 999px; padding: 0 7px; }

/* Ticket opener (description) block */
.voops-ticket__opener { display: flex; gap: 12px; align-items: flex-start; }
.voops-ticket__opener-body { flex: 1; min-width: 0; }
.voops-ticket__desc--empty { margin: 4px 0 0; font-style: italic; }

/* Activity/comment timeline */
.voops-timeline { list-style: none; margin: 0 0 8px; padding: 0; position: relative; }
.voops-timeline__item { position: relative; display: flex; gap: 12px; padding: 6px 0; }
.voops-timeline__item--activity { align-items: center; padding-inline-start: 4px; }
.voops-timeline__dot { flex: none; width: 8px; height: 8px; margin: 0 12px; border-radius: 50%; background: var(--voops-border-2); }
.voops-timeline__line { font-size: 12.5px; color: var(--voops-muted); }
.voops-timeline__item--comment { padding: 8px 0; }
.voops-comment { flex: 1; min-width: 0; background: var(--voops-surface); border: 1px solid var(--voops-border); border-radius: var(--voops-radius); padding: 12px 14px; }

/* Inline resolution-note panel (replaces the native prompt) */
.voops-resolve-note { margin-top: 8px; display: flex; flex-direction: column; gap: 6px; }
.voops-resolve-note[hidden] { display: none; }
/* A Vision One note is the vendor's plain text; its line breaks are part of it. */
.voops-thread__body--plain { white-space: pre-wrap; overflow-wrap: anywhere; }
/* The Vision One panel's conflict choices wrap rather than push past a narrow card. */
.voops-ticket__v1-conflict { display: grid; gap: 6px; padding-top: 8px; }
.voops-ticket__v1-actions { display: flex; flex-wrap: wrap; gap: 8px; }
/* A comment's delivery to Vision One (WB-4): badge, who confirmed, and the uncertain
   workflow's matches and resend, all wrapping inside a narrow thread. */
.voops-thread__v1 { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin-top: 8px; }
.voops-thread__v1 > .voops-hint, .voops-thread__v1 > .voops-label { flex-basis: 100%; margin: 0; }
.voops-thread__v1-candidates { flex-basis: 100%; list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.voops-thread__v1-candidates li { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; overflow-wrap: anywhere; }
.voops-resolve-note__actions { display: flex; gap: 8px; justify-content: flex-end; }

.voops-prop { display: flex; flex-direction: column; gap: 5px; padding: 10px 0; border-bottom: 1px solid var(--voops-border); }
.voops-prop:last-child { border-bottom: 0; }
.voops-prop__k { font-size: 12px; color: var(--voops-faint); }
.voops-prop__v { font-size: 14px; }
.voops-input--sm { padding: 6px 10px; font-size: 13px; }

/* SLA indicators (R = response, F = resolution/fix) */
/* The two clocks stack. Side by side they fitted only while each was a single
   letter and a number; named lanes and a real duration need their own line. */
.voops-sla-cell { display: grid; gap: 4px; justify-items: start; white-space: nowrap; }
.voops-sla { display: inline-flex; align-items: baseline; gap: 5px; font-size: 11px; font-weight: 600; padding: 2px 7px; border-radius: 999px; border: 1px solid transparent; }
/* The lane name is the constant; the figure is what changes and is read first. */
.voops-sla__lane { font-style: normal; font-weight: 500; opacity: .75; }
.voops-sla__value { font-variant-numeric: tabular-nums; }
.voops-sla--met { color: var(--voops-success); background: var(--voops-success-soft); border-color: var(--voops-success-line); }
.voops-sla--running { color: var(--voops-muted); background: var(--voops-tint); border-color: var(--voops-border-2); }
.voops-sla--breached { color: var(--voops-danger); background: var(--voops-error-soft); border-color: var(--voops-error-line); }
.voops-sla--na { color: var(--voops-faint); background: var(--voops-tint-weak); border-color: var(--voops-border-2); }
.voops-seed-locked { display: inline-flex; align-items: center; gap: 8px; margin: 0; }
.voops-seed-locked .voops-ico { color: var(--voops-muted); flex: none; }

/* Client-profile quota usage indicator */
.voops-usage { display: flex; align-items: center; gap: 10px; margin: 0 0 18px; font-size: 13px; color: var(--voops-muted); }
.voops-usage__count { font-weight: 600; color: var(--voops-text); font-variant-numeric: tabular-nums; }
.voops-usage__count--full { color: var(--voops-warning); }
.voops-usage__note { color: var(--voops-warning); }

/* ── Audit log ── */
.voops-audit__bar { display: flex; align-items: center; gap: 14px; margin: 4px 0 18px; }
.voops-audit__count { font-size: 13px; color: var(--voops-muted); }
.voops-audit__filters { display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; margin-bottom: 18px; }
.voops-audit__filter { display: flex; flex-direction: column; gap: 5px; }
.voops-audit__flabel { font-size: 12px; color: var(--voops-faint); }
.voops-audit__filters .voops-input { min-width: 200px; }
.voops-audit__filters .voops-btn { flex-shrink: 0; }
.voops-audit__table td { vertical-align: top; }
.voops-audit__ts { white-space: nowrap; color: var(--voops-muted); font-variant-numeric: tabular-nums; }
.voops-audit__target { font-family: var(--voops-mono, ui-monospace, SFMono-Regular, Menlo, monospace); font-size: 13px; color: var(--voops-muted); word-break: break-all; }
.voops-audit__detail > summary { list-style: none; cursor: pointer; color: var(--voops-accent); font-size: 13px; font-weight: 500; display: inline-flex; align-items: center; gap: 5px; user-select: none; }
.voops-audit__detail > summary::-webkit-details-marker { display: none; }
.voops-audit__detail[open] > summary { margin-bottom: 8px; }
.voops-audit__diff { display: flex; flex-direction: column; gap: 6px; max-width: 520px; }
.voops-audit__diffrow { display: flex; gap: 8px; align-items: baseline; }
.voops-audit__difflabel { flex: 0 0 auto; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; padding-top: 1px; }
.voops-audit__difflabel--before { color: var(--voops-warning); }
.voops-audit__difflabel--after { color: var(--voops-success); }
.voops-audit__diffrow code { font-size: 12.5px; color: var(--voops-text); background: var(--voops-tint-weak); border: 1px solid var(--voops-border); border-radius: 6px; padding: 3px 7px; word-break: break-word; white-space: pre-wrap; }

.voops-empty { background: var(--voops-surface); border: 1px dashed var(--voops-border-2); border-radius: var(--voops-radius); padding: 40px; text-align: center; color: var(--voops-muted); font-size: 14px; }

/* An inline notice about the state of the system, as distinct from `.voops-empty`,
   which says a collection has no members. A warning is left-aligned and rule-marked
   because it is prose the reader has to act on; an empty state is centred and dashed
   because there is nothing to read. Four templates were using `voops-alert` with no
   rule behind it at all, so every one of those warnings rendered as bare body text. */
.voops-notice { display: block; background: var(--voops-surface); border: 1px solid var(--voops-border-2); border-inline-start: 3px solid var(--voops-border-2); border-radius: var(--voops-radius); padding: 14px 16px; color: var(--voops-muted); font-size: 13px; line-height: 1.5; text-align: start; }
.voops-notice--warn { border-inline-start-color: var(--voops-warning); color: var(--voops-text); }
/* A notice that sits inside a card or form body, rather than as the whole
   content of one. Without this it butts straight against the container's border
   — the stale-recipient warning in Edit report schedule was touching the box. */
.voops-notice--spaced { margin: 16px 0; }
.voops-notice__title { display: block; font-weight: 600; color: var(--voops-text); margin-bottom: 4px; }
.voops-notice__list { margin: 8px 0 0; padding-inline-start: 18px; }
.voops-notice__list li { margin-top: 4px; }
.voops-notice + .voops-notice { margin-top: 12px; }
.voops-hint { display: block; font-size: 12px; color: var(--voops-faint); margin-top: 6px; }
.voops-link { color: var(--voops-text); font-weight: 500; }
.voops-link:hover { color: var(--voops-accent); }
.voops-admin__section { font-size: 16px; font-weight: 600; margin: 28px 0 12px; }

.voops-subnav { display: flex; gap: 6px; margin-bottom: 24px; border-bottom: 1px solid var(--voops-border); }
.voops-subnav__link { font-size: 14px; color: var(--voops-muted); padding: 8px 14px; border-bottom: 2px solid transparent; margin-bottom: -1px; }
.voops-subnav__link:hover { color: var(--voops-text); }
.voops-subnav__link.is-active { color: var(--voops-text); border-bottom-color: var(--voops-accent); }

/* Invite card + inline form + one-time link result */
.voops-invite { padding: 20px; margin-bottom: 24px; }
.voops-invite h2 { font-size: 16px; font-weight: 600; margin: 0 0 4px; }
.voops-inline-form { display: flex; gap: 10px; align-items: center; margin-top: 12px; flex-wrap: wrap; }
.voops-inline-form .voops-input { flex: 1; min-width: 180px; }
.voops-select { flex: 0 0 auto; min-width: 150px; width: auto; cursor: pointer; }
.voops-invite-link { margin-top: 14px; padding: 14px 16px; background: var(--voops-accent-soft); border: 1px solid var(--voops-border-2); border-inline-start: 3px solid var(--voops-accent); border-radius: var(--voops-radius-sm); font-size: 13px; color: var(--voops-muted); }
.voops-invite-link p { margin: 0 0 8px; }
.voops-invite-link code { display: block; word-break: break-all; color: var(--voops-text); background: var(--voops-surface-2); border: 1px solid var(--voops-border); border-radius: 6px; padding: 8px 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }

.voops-auth__panel--single .voops-auth__form { flex: 1; }

/* ─── Legal pages (Terms / Privacy) ───────────────────────────────────────── */
.voops-legal { max-width: 760px; margin: 0 auto; padding: 56px 24px 96px; }
.voops-legal__back { display: inline-block; font-size: 13px; margin-bottom: 28px; }
.voops-legal__logo { width: 120px; height: auto; margin-bottom: 22px; }
.voops-legal h1 { font-size: 30px; font-weight: 700; margin: 0 0 6px; }
.voops-legal__meta { font-size: 13px; color: var(--voops-faint); margin: 0 0 26px; }
.voops-legal__note {
  font-size: 13px; color: var(--voops-muted); line-height: 1.6;
  background: var(--voops-accent-soft); border: 1px solid var(--voops-border-2);
  border-inline-start: 3px solid var(--voops-accent); border-radius: var(--voops-radius-sm);
  padding: 14px 16px; margin: 0 0 32px;
}
.voops-legal h2 { font-size: 18px; font-weight: 600; margin: 34px 0 10px; }
.voops-legal p { font-size: 15px; line-height: 1.75; color: var(--voops-muted); margin: 0 0 14px; }
.voops-legal__seealso { margin-top: 40px; padding-top: 20px; border-top: 1px solid var(--voops-border); }

/* ── Platform Settings → Email (outbound console) ─────────────────────────── */
.htmx-indicator { opacity: 0; transition: opacity .15s; }
.htmx-request .htmx-indicator, .htmx-request.htmx-indicator { opacity: 1; }
.full-width { grid-column: 1 / -1; }

.voops-tabbar { display: flex; gap: 0; border-bottom: 1px solid var(--voops-border); margin-bottom: 20px; flex-wrap: wrap; }
.voops-tabbar__tab { padding: 10px 18px; font-size: 13px; font-weight: 600; color: var(--voops-muted); cursor: pointer; background: none; border: none; border-bottom: 2px solid transparent; margin-bottom: -1px; transition: color .15s, border-color .15s; }
.voops-tabbar__tab:hover { color: var(--voops-text); }
.voops-tabbar__tab.active { color: var(--voops-accent); border-bottom-color: var(--voops-accent); }
.voops-tabbar__tab .voops-badge { margin-inline-start: 6px; font-size: 11px; padding: 1px 7px; }

/* Pill variant of the tab bar, for switching a view rather than a page section.
   Same tab semantics and the same __tab element, so the button contract and the
   keyboard behaviour are shared rather than reimplemented. */
/* One explicit height, shared with the quick-actions pill beside it. Letting each
   control derive its own from padding and content leaves them a pixel apart,
   which is enough to read as crooked on a title row. */
.voops-tabbar--segmented {
  /* 40px outer, the shared control height. The inner tabs are 32px so the pill
     wall, its padding and its border add up to that height rather than to a
     number of this control's own invention. */
  display: inline-flex; align-items: center; gap: 2px; height: 40px; padding: 3px;
  /* The base tab bar is a page-section strip: it carries a bottom rule and a
     20px bottom margin to separate itself from the section below. A segmented
     control sits inline beside other controls and needs neither — the margin was
     making the row 62px tall and pinning this control to its top. */
  border-bottom: 0; margin-bottom: 0; background: var(--voops-surface-2);
  border: 1px solid var(--voops-border); border-radius: 999px;
}
.voops-tabbar--segmented .voops-tabbar__tab {
  min-height: 32px; padding: 0 16px; border-radius: 999px; border-bottom: 0;
  display: inline-flex; align-items: center; font-size: 13px;
}
.voops-tabbar--segmented .voops-tabbar__tab[aria-selected="true"] {
  color: var(--voops-text); background: var(--voops-elevated);
  box-shadow: inset 0 1px 0 var(--voops-tint);
}
/* A control that does not apply right now. Dimmed and unclickable rather than
   removed: a switch that disappears makes the reader wonder what they pressed. */
.voops-tabbar--segmented.is-disabled { opacity: .45; }
.voops-tabbar--segmented.is-disabled .voops-tabbar__tab { cursor: not-allowed; }

.voops-tabbar--segmented .voops-tabbar__tab:focus-visible {
  outline: 2px solid var(--voops-accent); outline-offset: 2px;
}

/* Two segmented controls sit side by side on gap analysis, and identical pills
   made them look like one four-way choice. The view switch is the outer of the
   two — it decides whether the mode switch applies at all — so it carries the
   accent and the mode switch stays neutral. Hierarchy, not decoration.
   Targeted on the control's own name, so no template knows about this. */
.voops-tabbar--segmented[data-segmented="view"] {
  background: var(--voops-accent-soft); border-color: var(--voops-accent-line);
}
.voops-tabbar--segmented[data-segmented="view"] .voops-tabbar__tab[aria-selected="true"] {
  color: var(--voops-on-accent); background: var(--voops-accent-grad);
  box-shadow: var(--voops-btn-highlight);
}
.voops-tabbar--segmented[data-segmented="view"] .voops-tabbar__tab:not([aria-selected="true"]) {
  color: var(--voops-accent);
}

.ob-panel { display: none; }
.ob-panel.active { display: block; }
.ob-h { font-size: 15px; font-weight: 700; margin: 0 0 4px; color: var(--voops-text); }
.ob-p { font-size: 13px; color: var(--voops-muted); margin: 0 0 14px; line-height: 1.5; }
.ob-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; }
.ob-note { margin-top: 14px; padding: 10px 14px; background: var(--voops-accent-soft); border: 1px solid var(--voops-border-2); border-inline-start: 3px solid var(--voops-accent); border-radius: var(--voops-radius-sm); font-size: 13px; color: var(--voops-muted); line-height: 1.6; }

.ob-head { display: flex; align-items: center; gap: 12px; margin-bottom: 18px; }
.ob-head-label { font-size: 15px; font-weight: 700; color: var(--voops-text); }
.ob-head-sub { font-size: 13px; color: var(--voops-muted); }
.ob-fields { transition: opacity .2s; }
.ob-fields.disabled { opacity: .45; pointer-events: none; }

/* The provider onboarding switches were a second switch component here — `.switch`,
   40x22 with an 18px thumb, against `.voops-toggle`'s 38x21 with a 17px one — so this
   page rendered a visibly different control from every other settings page. They now
   use the shared toggle, and the rules are deleted rather than left behind: a dormant
   second implementation is what the next person copies. */

/* failover drag-drop list */
.fo-list { list-style: none; padding: 0; margin: 0; }
.fo-item { display: flex; align-items: center; gap: 12px; padding: 12px 16px; margin-bottom: 8px; background: var(--voops-elevated); border: 1px solid var(--voops-border); border-radius: var(--voops-radius-sm); cursor: grab; user-select: none; transition: box-shadow .15s, border-color .15s; }
.fo-item:active { cursor: grabbing; }
.fo-item.dragging { opacity: .5; border-color: var(--voops-accent); }
.fo-item.drag-over { border-color: var(--voops-accent); border-style: dashed; }
.fo-handle { color: var(--voops-faint); font-size: 16px; line-height: 1; flex-shrink: 0; }
.fo-rank { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 50%; background: var(--voops-accent); color: var(--voops-on-accent); font-size: 12px; font-weight: 700; flex-shrink: 0; }
.fo-name { font-weight: 600; font-size: 14px; color: var(--voops-text); }
.fo-empty { padding: 24px; text-align: center; color: var(--voops-muted); font-size: 13px; border: 1px dashed var(--voops-border-2); border-radius: var(--voops-radius-sm); }

/* queue stats + actions */
.ob-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-bottom: 16px; }
.ob-stat { background: var(--voops-surface); border: 1px solid var(--voops-border); border-radius: var(--voops-radius); padding: 16px 18px; }
.ob-stat__label { font-size: 12px; font-weight: 600; color: var(--voops-muted); text-transform: uppercase; letter-spacing: .04em; }
.ob-stat__value { font-size: 26px; font-weight: 800; color: var(--voops-text); margin-top: 2px; }
.ob-stat__value--pending { color: var(--voops-accent); }
.ob-stat__value--failed, .voops-text--error { color: var(--voops-error); }
.ob-stat__value--completed { color: var(--voops-success); }
.ob-q-actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* DNS check panel */
.voops-dns__summary { font-size: 13px; font-weight: 600; margin: 0 0 8px; }
.voops-dns__summary--ok { color: var(--voops-success); }
.voops-dns__summary--bad { color: var(--voops-warning); }
.voops-dns__table { width: 100%; border-collapse: collapse; font-size: 13px; }
.voops-dns__row td { padding: 6px 10px; border-bottom: 1px solid var(--voops-border); }
.voops-dns__kind { font-weight: 700; color: var(--voops-text); width: 70px; }
.voops-dns__mark { width: 24px; text-align: center; font-weight: 800; }
.voops-dns__row--ok .voops-dns__mark { color: var(--voops-success); }
.voops-dns__row--bad .voops-dns__mark { color: var(--voops-error); }
.voops-dns__detail { color: var(--voops-muted); word-break: break-all; }

@media (max-width: 640px) {
  .ob-grid, .ob-stats { grid-template-columns: 1fr; }
}

/* topbar nav (platform admin plane) */
.voops-topbar__nav { display: flex; gap: 4px; margin-inline-start: 14px; flex-wrap: wrap; }
.voops-topbar__link { font-size: 13px; font-weight: 600; color: var(--voops-muted); text-decoration: none; padding: 6px 12px; border-radius: var(--voops-radius-sm); transition: color .15s, background .15s; }
.voops-topbar__link:hover { color: var(--voops-text); background: var(--voops-elevated); }
.voops-topbar__link--active { color: var(--voops-accent); }

/* ─── Authenticated app shell: edge ridge + revealing rail ────────────────
   The reveal is a transform on a column that is already narrower than the
   viewport by the rail's width. Animating `margin` instead would reflow the
   column and visibly re-lay out table columns on hover; translating a
   full-width column instead would push its far edge out of reach. This does
   neither. ------------------------------------------------------------- */

/* ── Light theme ──────────────────────────────────────────────────────────────
   A second palette, not a filter. Every token above is redefined here; no rule
   below this point knows which theme is active, which is the whole point of
   having tokenised the sheet first.

   `theme.js` always stamps `data-theme` on <html> before first paint — reading
   the stored choice, or the OS preference when there is none — so this needs no
   `prefers-color-scheme` duplicate. With JavaScript off the app stays dark,
   which is the designed default rather than an accident.

   `color-scheme` is set so the browser's own furniture — scrollbars, form
   controls, spellcheck underlines — follows the page instead of staying dark
   over a white ground. */
:root[data-theme="light"] {
  color-scheme: light;

  /* Surfaces */
  --voops-bg:        #f6f7f9;
  --voops-surface:   #ffffff;
  --voops-surface-2: #f1f2f5;
  --voops-elevated:  #e9ebef;
  --voops-border:    #e3e5eb;
  --voops-border-2:  #c9ced8;

  /* Text. Darkened rather than inverted: #f4f5f7 flipped would be pure black,
     which is harsher on white than this product is on black. */
  --voops-text:   #16181d;
  --voops-muted:  #5b616e;
  --voops-faint:  #868d9a;

  /* Brand. The accent is the identity and does not move; only what sits
     under it does. The soft fill needs more alpha to register on white. */
  --voops-accent-soft: rgba(242, 83, 15, .10);
  --voops-accent-glow: rgba(242, 83, 15, .22);
  --voops-btn-highlight: inset 0 1px 0 rgba(255, 255, 255, .28);

  /* Status text. The dark-theme values are mid-tones tuned for a black ground
     and fail contrast on white, so each is darkened. */
  --voops-success: #12794a;
  --voops-warning: #9a6200;
  --voops-error:   #c62828;
  --voops-danger:  #c62828;
  --voops-info:    #1d5fd0;

  /* Neutral tints invert: "lift this surface" is a black wash on a light
     ground, and a white one would be invisible. */
  --voops-tint-weak:   rgba(16, 18, 24, .03);
  --voops-tint:        rgba(16, 18, 24, .05);
  --voops-tint-strong: rgba(16, 18, 24, .09);
  --voops-tint-heavy:  rgba(16, 18, 24, .26);

  /* Shadows are far lighter: the dark theme's .30–.60 blacks read as smudges
     on white. */
  --voops-shadow-soft: rgba(16, 18, 24, .07);
  --voops-shadow-mid:  rgba(16, 18, 24, .13);
  --voops-shadow-deep: rgba(16, 18, 24, .20);
  --voops-card-shadow: 0 10px 26px rgba(16, 18, 24, .07);
  --voops-card-bg:     linear-gradient(180deg, #ffffff 0%, #fcfcfd 100%);

  /* Chrome */
  --voops-bar-bg:       rgba(255, 255, 255, .95);
  --voops-bar-bg-solid: rgba(255, 255, 255, .985);
  --voops-scrim:        rgba(246, 247, 249, .62);
  --voops-scrim-fade:   rgba(246, 247, 249, .18);
  --voops-scrim-fade-2: rgba(246, 247, 249, .06);
  --voops-rail-bg:      rgba(255, 255, 255, .94);
  --voops-menu-bg:      rgba(255, 255, 255, .99);
  --voops-attention-bg: #fef4f2;

  /* Status washes: same hues, more alpha so they register on white. */
  --voops-success-soft: rgba(18, 121, 74, .10);
  --voops-success-line: rgba(18, 121, 74, .32);
  --voops-warning-soft: rgba(154, 98, 0, .10);
  --voops-warning-line: rgba(154, 98, 0, .32);
  --voops-error-soft:   rgba(198, 40, 40, .09);
  --voops-error-line:   rgba(198, 40, 40, .30);
  --voops-error-wash:   rgba(198, 40, 40, .05);
  --voops-accent-line:  rgba(242, 83, 15, .34);
  --voops-info-soft:    rgba(29, 95, 208, .09);
  --voops-info-line:    rgba(29, 95, 208, .30);

  /* Chart series, darkened to hold their contrast against white. Series 5 is
     the "not evaluated" grey and moved most: #4a5563 vanishes on #fff. */
  --voops-series-1: #d9430a;
  --voops-series-2: #d9772f;
  --voops-series-3: #7346bd;
  --voops-series-4: #2a6cb0;
  --voops-series-5: #7b828e;
}

:root {
  --voops-rail-w: 64px;      /* width of the floating pill                  */
  --voops-rail-rest: 24px;   /* content offset while the rail is hidden     */
  /* Logical properties mirror a layout; they do NOT mirror a transform.
     translateX(+n) moves right in both directions, so under RTL the reveal
     would shove content off the inline start. The sign is flipped explicitly. */
  --voops-reveal: calc(var(--voops-rail-w) - var(--voops-rail-rest));
  --voops-rail-enter: -14px;
}
html[dir="rtl"] {
  --voops-reveal: calc(-1 * (var(--voops-rail-w) - var(--voops-rail-rest)));
  --voops-rail-enter: 14px;
}

.voops-app { position: relative; min-height: 100vh; }

/* The hot zone is wide and invisible; the ridge inside it is the visible part.
   A 3px pointer target cannot be hit reliably with a trackpad. */
.voops-rail-zone {
  position: fixed; inset-block: 0; inset-inline-start: 0; width: 46px; z-index: 40;
}
.voops-ridge {
  position: absolute; inset-block: 0; inset-inline-start: 5px; width: 4px;
  display: flex; align-items: center; pointer-events: none;
}
.voops-ridge::before {
  content: ""; display: block; width: 3px; height: 118px; border-radius: 3px;
  background: linear-gradient(180deg, transparent, var(--voops-border-2) 18%,
                              var(--voops-border-2) 82%, transparent);
  transition: width .18s, height .18s, background .18s, box-shadow .18s;
}
.voops-rail-zone:hover .voops-ridge::before,
.voops-rail-zone:focus-within .voops-ridge::before {
  width: 4px; height: 132px;
  background: linear-gradient(180deg, transparent, var(--voops-accent) 12%,
                              var(--voops-accent) 88%, transparent);
  box-shadow: 0 0 14px var(--voops-accent-line);
}

.voops-rail {
  position: absolute; inset-inline-start: 10px; top: 50%; translate: 0 -50%;
  width: var(--voops-rail-w); padding: 10px 0; z-index: 2;
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  border: 1px solid var(--voops-border); border-radius: 999px;
  background: var(--voops-rail-bg); backdrop-filter: blur(14px);
  box-shadow: 0 20px 50px var(--voops-shadow-deep);
  opacity: 0; pointer-events: none;
  transform: translateX(var(--voops-rail-enter));
  transition: opacity .18s ease, transform .22s cubic-bezier(.2, .7, .3, 1);
}
/* Focus-within, not hover alone: the rail must be reachable by keyboard. */
.voops-rail-zone:hover .voops-rail,
.voops-rail-zone:focus-within .voops-rail {
  opacity: 1; transform: translateX(0); pointer-events: auto;
}
.voops-rail__nav { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.voops-rail__item {
  width: 40px; height: 40px; display: grid; place-items: center; border-radius: 999px;
  color: var(--voops-muted); text-decoration: none;
}
.voops-rail__item:hover { color: var(--voops-text); background: var(--voops-elevated); }
.voops-rail__item.is-active { color: var(--voops-on-accent); background: var(--voops-accent-grad); }
.voops-rail__item:focus-visible { outline: 2px solid var(--voops-accent); outline-offset: 2px; }

/* The rail sets no overflow, and the popover sits on its own layer: a menu
   opened inside a collapsing container is the classic way to lose it. */
.voops-rail-menu { position: relative; }
.voops-rail-menu__popover {
  position: absolute; inset-inline-start: calc(100% + 10px); top: 50%; translate: 0 -50%;
  min-width: 180px; padding: 6px; display: none; z-index: 60;
  border: 1px solid var(--voops-border); border-radius: var(--voops-radius);
  background: var(--voops-menu-bg); box-shadow: 0 20px 50px var(--voops-shadow-deep);
}
.voops-rail-menu:hover .voops-rail-menu__popover,
.voops-rail-menu:focus-within .voops-rail-menu__popover { display: grid; gap: 2px; }
/* Bridge the 10px gap between the rail item and the popover, and overhang it
   vertically. Without this the pointer crosses dead space on its way across,
   the wrapper sees a leave, and the menu closes under the cursor — the same
   defect already fixed on the quick-actions card and missed here. The vertical
   overhang matters because the popover is centred on a 44px item: a pointer
   moving diagonally toward the second link would otherwise leave through the
   top or bottom edge before reaching it. */
.voops-rail-menu__popover::before {
  content: ""; position: absolute; inset-block: -10px;
  inset-inline-start: -14px; width: 14px;
}
.voops-rail-menu__link {
  padding: 9px 12px; border-radius: 9px; font-size: 13px; color: var(--voops-muted);
  text-decoration: none; white-space: nowrap;
}
.voops-rail-menu__link:hover,
.voops-rail-menu__link:focus-visible { color: var(--voops-text); background: var(--voops-surface-2); }
.voops-rail-menu__link.is-active { color: var(--voops-accent); background: var(--voops-accent-soft); }

/* Separators between navigation groups. The rail's is a short centred hairline
   sized to the 40px item; the drawer's spans its width and carries the group
   heading above the items it fences. */
.voops-rail__rule {
  display: block; width: 22px; height: 1px; margin: 3px auto;
  background: var(--voops-border); flex: 0 0 auto;
}
.voops-drawer__rule {
  display: block; width: 100%; height: 1px; margin: 8px 0 4px;
  background: var(--voops-border);
}
.voops-drawer__group {
  margin: 2px 0 2px; padding: 0 12px; font-size: 10.5px; font-weight: 700;
  letter-spacing: .09em; text-transform: uppercase; color: var(--voops-muted);
}

.voops-rail__foot {
  margin-top: 8px; padding-top: 10px; display: flex; flex-direction: column;
  align-items: center; gap: 8px; border-top: 1px solid var(--voops-border); width: 60%;
}
.voops-rail__avatar {
  position: relative; width: 36px; height: 36px; border-radius: 50%;
  display: grid; place-items: center; font-size: 12px; font-weight: 700;
  color: var(--voops-text); background: var(--voops-surface-2);
  border: 1px solid var(--voops-border); text-decoration: none;
}
.voops-rail__dot {
  position: absolute; inset-inline-end: -1px; bottom: -1px; width: 11px; height: 11px;
  border-radius: 50%; background: var(--voops-success); border: 2px solid var(--voops-surface);
}
.voops-shell__logout-form { margin: 0; display: contents; }
/* Theme toggle. Both icons are in the markup on every page and CSS picks the
   one for the active theme, so the right icon is painted before any script
   runs — swapping them in JS would show the wrong one on a slow load. The
   button shows the theme you would switch TO, which is the convention every
   OS uses. */
.voops-rail__theme {
  width: 34px; height: 34px; display: grid; place-items: center;
  border: 0; border-radius: 50%; background: transparent; cursor: pointer;
  color: var(--voops-muted); padding: 0;
}
.voops-rail__theme:hover { background: var(--voops-tint); color: var(--voops-text); }
.voops-rail__theme:focus-visible { outline: 2px solid var(--voops-accent); outline-offset: 2px; }
.voops-rail__theme > span { display: none; grid-area: 1 / 1; }
.voops-drawer__theme-dark, .voops-drawer__theme-light { display: none; }
.voops-drawer__theme-light { display: inline-flex; }
:root[data-theme="light"] .voops-drawer__theme-light { display: none; }
:root[data-theme="light"] .voops-drawer__theme-dark { display: inline-flex; }
/* Dark is active → offer the sun. */
.voops-rail__theme .voops-rail__theme-light { display: grid; }
:root[data-theme="light"] .voops-rail__theme .voops-rail__theme-light { display: none; }
:root[data-theme="light"] .voops-rail__theme .voops-rail__theme-dark { display: grid; }

.voops-rail__logout {
  width: 36px; height: 36px; display: grid; place-items: center; border-radius: 10px;
  border: 0; background: transparent; color: var(--voops-muted); cursor: pointer;
}
.voops-rail__logout:hover { color: var(--voops-text); background: var(--voops-elevated); }

/* ── Mobile drawer. Every destination for the role, because a bottom bar holds
      about five and this role has ten. ── */
.voops-content__menu { display: none; order: -1; padding: 0 12px; }
.voops-drawer { position: fixed; inset: 0; z-index: 90; }
.voops-drawer__backdrop { position: absolute; inset: 0; background: var(--voops-shadow-deep); }
.voops-drawer__panel {
  position: absolute; inset-block: 0; inset-inline-start: 0; width: min(320px, 86vw);
  display: flex; flex-direction: column; gap: 6px; padding: 18px 16px;
  background: var(--voops-surface); border-inline-end: 1px solid var(--voops-border);
  box-shadow: 0 20px 50px var(--voops-shadow-deep); overflow-y: auto;
}
.voops-drawer__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 10px; }
.voops-drawer__logo { height: 26px; width: auto; }
.voops-drawer__close { padding: 0 10px; }
.voops-drawer__nav { display: flex; flex-direction: column; gap: 2px; }
.voops-drawer__item {
  display: flex; align-items: center; gap: 12px; min-height: 44px; padding: 0 12px;
  border-radius: var(--voops-radius-sm); color: var(--voops-muted); text-decoration: none;
  font-size: 14px; font-weight: 550;
}
.voops-drawer__item:hover { color: var(--voops-text); background: var(--voops-elevated); }
.voops-drawer__item.is-active { color: var(--voops-on-accent); background: var(--voops-accent-grad); }
.voops-drawer__foot { margin-top: auto; padding-top: 14px; border-top: 1px solid var(--voops-border); display: flex; flex-direction: column; gap: 8px; }


/* content area */
.voops-content {
  min-width: 0; padding: 36px 40px 64px;
  /* Already narrower than the viewport by the rail's width, so the reveal below
     slides it into reserved space and it can never reach the far edge. */
  width: calc(100% - var(--voops-rail-w));
  margin-inline-start: var(--voops-rail-rest);
  /* `none`, not `translateX(0)`. ANY transform — including an identity one —
     makes this element the containing block for every `position: fixed`
     descendant, so a modal, a toast or a popover inside the page would resolve
     against this full-height column instead of the viewport and be centred in
     the page rather than on screen. At rest there is no transform and fixed
     positioning behaves normally; `none` still interpolates to a translation,
     so the reveal animates exactly as before. */
  transform: none;
  transition: transform .22s cubic-bezier(.2, .7, .3, 1);
}
.voops-rail-zone:hover ~ .voops-content,
.voops-rail-zone:focus-within ~ .voops-content { transform: translateX(var(--voops-reveal)); }
/* While a modal is open the reveal is suppressed entirely. Applying the
   transform then would re-establish the containing block underneath the open
   dialog and yank it out of position mid-interaction — and the rail is not
   reachable behind a modal anyway. */
.voops-app:has(.voops-modal.is-open) .voops-rail-zone:hover ~ .voops-content,
.voops-app:has(.voops-modal.is-open) .voops-rail-zone:focus-within ~ .voops-content {
  transform: none;
}
/* While the navigation is open, a 2px accent line marks the far edge of the
   application. Accent, not error red: nothing is wrong when the navigation opens.

   It is a sibling of the content column, not a pseudo-element on it. A
   transformed ancestor makes a `position: fixed` descendant resolve against that
   ancestor rather than the viewport, so as a child of the transformed column the
   line was bounded by the column's height and travelled with it — it stopped
   short and drifted. Out here it spans the full viewport height and holds still.

   Continuous, not a fading gradient: a line that fades at both ends reads as
   though it failed to reach the edges. `inset-inline-end` puts it on the right
   in LTR and mirrors it to the left in RTL with no extra rule. */
.voops-open-edge {
  position: fixed; inset-block: 0; inset-inline-end: 0; width: 2px; z-index: 30;
  opacity: 0; pointer-events: none; transition: opacity .22s ease;
  background: var(--voops-accent);
  box-shadow: 0 0 12px var(--voops-accent-line), 0 0 30px var(--voops-accent-soft);
}
.voops-rail-zone:hover ~ .voops-open-edge,
.voops-rail-zone:focus-within ~ .voops-open-edge { opacity: .9; }

/* The persistent bar carries the wordmark alone (plus the menu button below the
   breakpoint), with a rule beneath it spanning the content column. Everything
   page-specific — the title, its controls, its primary action — sits below that
   rule, so what is always true of the product and what is true of this page are
   visibly separate. */
.voops-content__bar {
  display: flex; align-items: center; gap: 16px; padding-bottom: 18px;
  border-bottom: 1px solid var(--voops-border); margin-bottom: 24px;
}
.voops-content__brand { display: block; line-height: 0; flex: 0 0 auto; }
.voops-content__brand-logo { height: 22px; width: auto; max-width: 100%; }
.voops-content__head { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 12px 10px; margin-bottom: 28px; }
.voops-content__titles { flex: 1 1 auto; min-width: 0; }
.voops-content__actions { margin-inline-start: auto; display: flex; align-items: center; gap: 12px; flex-shrink: 0; flex-wrap: wrap; }
/* Controls for this page's own view, on the title row. */
/* Pinned to the title row and to its right edge. `margin-inline-start: auto`
   takes the free space after the title; because it is a sibling of the controls
   rather than a child, a page whose controls wrap onto their own full-width row
   leaves this behind on the title row where it belongs. */
.voops-content__quick { margin-inline-start: auto; align-self: center; flex-shrink: 0; }
/* The controls then need no auto margin of their own on such a page, or they
   would fight the pill for the same free space. */
.voops-content__head:has(.voops-content__quick) .voops-content__controls { margin-inline-start: 0; align-self: center; }

.voops-content__controls { margin-inline-start: auto; display: flex; align-items: stretch; gap: 10px; flex-shrink: 0; flex-wrap: wrap; }
.voops-content__controls > * { align-self: center; }
/* A page whose controls include the five-way filter gives them their own full
   width row under the title, filters starting at the left margin and the view
   switch alone on the right. Crammed into the title row they were all pushed
   right by `margin-inline-start: auto`, left a dead gap under the heading, and
   could not shrink (`flex-shrink: 0`), so a long customer name pushed the
   Customer field into Product. */
.voops-content__controls:has(.voops-gap-filter) {
  flex-basis: 100%; margin-inline-start: 0; align-items: flex-end;
}
.voops-content__controls:has(.voops-gap-filter) .voops-gap-filter {
  flex: 1 1 auto; min-width: 0; margin-bottom: 0;
}
.voops-content__controls:has(.voops-gap-filter) .voops-tabbar { margin-inline-start: auto; }
.voops-content__controls:has(.voops-gap-filter) > * { align-self: flex-end; }

/* The dashboard's controls stay on the title row, like every other page's do —
   Tickets and Client profiles both put their pill and primary action beside the
   heading, and a dashboard that dropped them onto a row of their own read as a
   different product.

   What actually broke here was internal wrapping, not lack of room: the
   customer filter carries `width: 100%`, which as a flex base claims the whole
   control group, so the Classic/Conversational switch — flex-shrink 1 by
   default — was squeezed under its own minimum and its second tab wrapped out
   of the pill. Give the filter a real width, let nothing on the row shrink, and
   all three sit on the title row on one baseline. */
.voops-content__head:has(.voops-dashboard-filter) .voops-content__controls {
  flex-wrap: nowrap; align-items: center;
}
.voops-content__head:has(.voops-dashboard-filter) .voops-content__controls > * {
  flex: 0 0 auto;
}
/* The filter is a form wrapping one select, and it carries
   `min-width: min(320px, 100%)` for the stacked layout. On this row that left a
   band of empty form between the dropdown and the switcher, so the three
   controls sat at visibly uneven gaps. The form hugs its select here and the
   width lives on the control itself. `min-width` beats `max-width` in CSS, so
   it has to be cleared rather than capped. */
.voops-content__head:has(.voops-dashboard-filter) .voops-dashboard-filter {
  width: auto; min-width: 0; max-width: none;
}
/* The quick-actions pill and the segmented control both declare an explicit
   40px so they cannot sit a pixel apart. The filter was still on the form
   default of 36px, which is exactly the kind of gap the comment on those two
   warns reads as crooked. Third control, same height. */
.voops-content__head:has(.voops-dashboard-filter) .voops-dashboard-filter .voops-input {
  width: 220px; height: 40px; min-height: 40px; border-radius: 999px;
}

/* Quick actions: a pill beside the view switch that drops a card of links.
   No clipping ancestor, so the card is never cut off; opens on hover, click and
   keyboard focus so it is not a pointer-only affordance. */
.voops-quick { position: relative; }
.voops-quick__pill {
  /* The shared 40px control height, same as the segmented control beside it. */
  display: inline-flex; align-items: center; gap: 8px; height: 40px; padding: 0 16px;
  border-radius: 999px; color: var(--voops-text);
  font: inherit; font-size: 13px; font-weight: 600; line-height: 1; cursor: pointer;
  /* Gradient outline. Two background layers rather than a pseudo-element: the
     fill is clipped to the padding box and the gradient to the border box, so the
     1px border becomes the gradient while the pill keeps its exact height and
     radius. A pseudo-element ring would need its own rounding and would sit
     outside the 40px control box. The border must be transparent for the
     border-box layer to show through. */
  border: 1px solid transparent;
  background:
    linear-gradient(var(--voops-surface-2), var(--voops-surface-2)) padding-box,
    var(--voops-warm-grad) border-box;
  transition: filter .15s, background .15s;
}
.voops-quick__pill:hover {
  background:
    linear-gradient(var(--voops-elevated), var(--voops-elevated)) padding-box,
    var(--voops-warm-grad-hover) border-box;
}
.voops-quick__pill:focus-visible { outline: 2px solid var(--voops-accent); outline-offset: 2px; }
.voops-quick__pill svg { transition: transform .18s; }
.voops-quick[data-open="true"] .voops-quick__pill svg { transform: rotate(180deg); }
.voops-quick__drop {
  position: absolute; inset-inline-end: 0; top: calc(100% + 8px); z-index: 60;
  min-width: 240px; padding: 8px; display: none; gap: 2px;
  border: 1px solid var(--voops-border); border-radius: var(--voops-radius-md, 14px);
  background: var(--voops-menu-bg); box-shadow: 0 20px 50px var(--voops-shadow-deep);
}
/* Visibility is driven by one attribute, set in JS. CSS `:hover` alone cannot
   express "Escape closed this, keep it closed while the pointer is still on the
   pill" — the hover rule would reopen it on the very next frame. */
.voops-quick[data-open="true"] .voops-quick__drop { display: grid; }
/* Bridge the 8px gap between pill and card. Without it the pointer passes over
   dead space on the way down, the wrapper sees a leave, and the card closes
   under the cursor — which is why it took several attempts to hit an item. */
.voops-quick__drop::before {
  content: ""; position: absolute; inset-inline: 0; top: -10px; height: 10px;
}
.voops-quick__rule {
  border: 0; border-top: 1px solid var(--voops-border); margin: 5px 6px;
}
.voops-quick__drop a {
  padding: 10px 12px; border-radius: 9px; color: var(--voops-muted);
  text-decoration: none; font-size: 13.5px; font-weight: 550; white-space: nowrap;
}
.voops-quick__drop a:hover, .voops-quick__drop a:focus-visible {
  background: var(--voops-elevated); color: var(--voops-text); outline: none;
}
.voops-content__titles h1 { font-size: 26px; font-weight: 700; margin: 0 0 4px; }
.voops-content__sub { font-size: 14px; color: var(--voops-muted); margin: 0; }
.voops-content__body { width: 100%; min-width: 0; overflow-x: auto; }

/* Below the breakpoint there is no ridge, no hot zone and no reveal: hover does
   not exist on touch, so the whole mechanism is switched off rather than left as
   a gesture nobody can discover. Navigation becomes the drawer. */
@media (max-width: 720px) {
  .voops-rail-zone { display: none; }
  .voops-content {
    width: 100%; margin-inline-start: 0; transform: none;
    padding: 20px 18px 48px;
  }
  .voops-rail-zone:hover ~ .voops-content,
  .voops-rail-zone:focus-within ~ .voops-content { transform: none; }
  .voops-open-edge { display: none; }
  .voops-content__menu { display: inline-flex; }
  .voops-content__bar { flex-wrap: wrap; padding-bottom: 14px; margin-bottom: 18px; }
  .voops-content__brand { flex: 1 1 auto; }
  .voops-content__brand-logo { height: 20px; max-width: 70%; }
  .voops-content__actions { flex-basis: 100%; margin-inline-start: 0; }
  .voops-content__controls { flex-basis: 100%; margin-inline-start: 0; }
  /* The one-row dashboard toolbar is a desktop arrangement: on a phone the three
     groups cannot share a line without the filter shrinking to nothing, so they
     stack again. */
  .voops-content__head:has(.voops-dashboard-filter) .voops-content__controls {
    flex-wrap: wrap;
  }
  .voops-content__head:has(.voops-dashboard-filter) .voops-content__quick {
    margin-inline-start: 0;
  }
  .voops-content__head:has(.voops-dashboard-filter) .voops-dashboard-filter,
  .voops-content__head:has(.voops-dashboard-filter) .voops-dashboard-filter .voops-input {
    width: 100%; max-width: none;
  }
  .voops-subtabs { flex-wrap: wrap; }
  .voops-subtabs__link { padding: 8px 10px; }
}
/* Above it there is no drawer: the rail is the navigation, and a second copy of
   every destination sitting in the DOM is a second thing to keep in step. */
@media (min-width: 721px) { .voops-drawer { display: none !important; } }

/* avatar as a link + in-page section sub-nav */
.voops-rail__avatar:hover { background: var(--voops-accent-soft); color: var(--voops-accent); }

.voops-subtabs { display: flex; gap: 4px; margin-bottom: 24px; border-bottom: 1px solid var(--voops-border); }
.voops-subtabs--raised { margin-top: -8px; }
.voops-subtabs__link { font-size: 14px; font-weight: 600; color: var(--voops-muted); text-decoration: none; padding: 10px 16px; border-bottom: 2px solid transparent; margin-bottom: -1px; transition: color .15s, border-color .15s; }
.voops-subtabs__link:hover { color: var(--voops-text); }
.voops-subtabs__link.is-active { color: var(--voops-accent); border-bottom-color: var(--voops-accent); }
.voops-subtabs--scroll { flex-wrap: nowrap; max-width: 100%; overflow-x: auto; overflow-y: hidden; scrollbar-width: thin; }
.voops-subtabs--scroll .voops-subtabs__link { flex: 0 0 auto; white-space: nowrap; }

/* profile page */
.voops-profile { display: flex; flex-direction: column; gap: 20px; max-width: 640px; }
.voops-card__h { font-size: 16px; font-weight: 700; margin: 0 0 18px; }
.voops-profile__row { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 14px 0; border-top: 1px solid var(--voops-border); }
.voops-profile__row:first-of-type { border-top: 0; }
.voops-profile__row-title { font-size: 14px; font-weight: 600; color: var(--voops-text); }
.voops-profile__row-sub { font-size: 13px; color: var(--voops-muted); margin-top: 2px; }

/* section menu cards (e.g. Platform management landing) */
/* Platform dashboard stat tiles (§11). */
.voops-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 14px; width: 100%; margin-bottom: 28px; }
.voops-stat { display: flex; flex-direction: column; gap: 4px; padding: 16px 18px; background: var(--voops-surface); border: 1px solid var(--voops-border); border-radius: var(--voops-radius); text-decoration: none; }
a.voops-stat:hover { border-color: var(--voops-accent); background: var(--voops-elevated); }
.voops-stat__label { font-size: 12px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--voops-muted); }
.voops-stat__value { font-size: 28px; font-weight: 700; line-height: 1.1; color: var(--voops-text); }
.voops-stat__value--alert { color: var(--voops-danger); }
.voops-stat__sub { font-size: 12px; color: var(--voops-faint); }
.voops-credit-summary { display: grid; grid-template-columns: repeat(3, minmax(120px, 1fr)) minmax(210px, 1.4fr); gap: 22px; margin-bottom: 22px; }
.voops-credit-summary > div { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.voops-credit-summary span { color: var(--voops-muted); font-size: 12px; font-weight: 600; text-transform: uppercase; }
.voops-credit-summary strong { color: var(--voops-text); font-size: 24px; line-height: 1.2; }
.voops-credit-summary__date strong { font-size: 17px; }
.voops-credit-allocation { width: 76px; min-width: 76px; }
.voops-credit-adjustment { display: grid; grid-template-columns: minmax(220px, .85fr) minmax(320px, 1.4fr) auto;
  gap: 12px; align-items: end; margin-top: 20px; }
.voops-credit-adjustment__action { display: flex; align-items: flex-end; }
.voops-credit-adjustment__hint { grid-column: 1 / -1; margin-top: -4px; }
.voops-partners-table { table-layout: fixed; }
.voops-partners-table__name-col { width: 32%; }
.voops-partners-table__credit-col { width: 130px; }
.voops-partners-table__status-col { width: 120px; }
.voops-partners-table__actions-col { width: 168px; }
.voops-partners-table__credit-head { display: inline-block; max-width: 62px; line-height: 1.2; white-space: normal; }
.voops-partners-table .voops-table__actions { flex-wrap: nowrap; }
.voops-table--clients .voops-table__actions { flex-wrap: nowrap; }
.voops-table--clients .voops-table__actions .voops-btn { white-space: nowrap; }
.voops-partners-table__name, .voops-partners-table__domains { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.voops-partners-table__name .voops-link {
  align-items: center; display: flex; min-width: 0; overflow: hidden; white-space: nowrap; width: 100%;
}
@media (max-width: 900px) {
  .voops-credit-summary { grid-template-columns: 1fr 1fr; }
  .voops-credit-adjustment { grid-template-columns: 1fr; align-items: stretch; }
  .voops-credit-adjustment__hint { grid-column: 1; margin-top: 0; }
}
.voops-dashboard-grid { display: grid; gap: 16px; width: 100%; }
.voops-dashboard-grid--platform { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.voops-dashboard-grid--partner { grid-template-columns: minmax(0, 1.4fr) minmax(320px, .8fr); align-items: start; }
.voops-dashboard-panel { padding: 20px; background: var(--voops-surface); border: 1px solid var(--voops-border); border-radius: var(--voops-radius); }
.voops-dashboard-panel__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 18px; padding-bottom: 16px; border-bottom: 1px solid var(--voops-border); color: var(--voops-accent); }
.voops-dashboard-panel__head h2 { margin: 0 0 4px; font-size: 16px; color: var(--voops-text); }
.voops-dashboard-panel__head p { margin: 0; color: var(--voops-muted); font-size: 12px; line-height: 1.45; }
.voops-dashboard-rows { display: flex; flex-direction: column; }
.voops-dashboard-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; min-height: 47px; padding: 11px 0; border-bottom: 1px solid var(--voops-border); color: var(--voops-muted); font-size: 13px; }
.voops-dashboard-row:last-child { border-bottom: 0; }
a.voops-dashboard-row:hover { color: var(--voops-accent); }
.voops-dashboard-row strong { color: var(--voops-text); font-size: 14px; white-space: nowrap; }
.voops-dashboard-row strong.is-alert { color: var(--voops-danger); }
.voops-dashboard-links { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; padding-top: 14px; }
.voops-dashboard-links a { display: flex; align-items: center; gap: 9px; min-height: 42px; padding: 10px 12px; border: 1px solid var(--voops-border); border-radius: var(--voops-radius-sm); color: var(--voops-muted); font-size: 13px; font-weight: 600; }
.voops-dashboard-links a:hover { border-color: var(--voops-accent); color: var(--voops-text); background: var(--voops-elevated); }
.voops-dashboard-estates__head { padding-bottom: 16px; border-bottom: 1px solid var(--voops-border); }
.voops-dashboard-clients .voops-table { margin-top: 12px; }
@media (max-width: 1180px) {
  .voops-dashboard-grid--platform { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .voops-dashboard-panel--actions { grid-column: 1 / -1; }
  .voops-dashboard-grid--partner { grid-template-columns: 1fr; }
}
@media (max-width: 720px) {
  .voops-dashboard-grid--platform { grid-template-columns: 1fr; }
  .voops-dashboard-panel--actions { grid-column: auto; }
  .voops-dashboard-links { grid-template-columns: 1fr; }
}

/* Customer-facing partner dashboard. Dense, operational, and built only from
   tenant-scoped facts already available to the signed-in partner. */
.voops-partner-kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; margin-bottom: 18px; }
.voops-partner-kpi { position: relative; display: flex; flex-direction: column; min-width: 0; min-height: 124px; padding: 18px 20px; color: var(--voops-text); background: var(--voops-surface); border: 1px solid var(--voops-border); border-radius: var(--voops-radius); }
a.voops-partner-kpi:hover { color: var(--voops-text); border-color: var(--voops-accent); background: var(--voops-elevated); }
.voops-partner-kpi__icon { position: absolute; top: 16px; inset-inline-end: 16px; display: grid; place-items: center; width: 34px; height: 34px; color: var(--voops-accent); background: var(--voops-accent-soft); border-radius: var(--voops-radius-xs); }
.voops-partner-kpi__label { max-width: calc(100% - 42px); color: var(--voops-muted); font-size: 12px; font-weight: 600; text-transform: uppercase; }
.voops-partner-kpi strong { margin-top: 13px; font-size: 30px; line-height: 1; }
.voops-partner-kpi small { margin-top: 9px; overflow: hidden; color: var(--voops-faint); font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }
.voops-partner-kpi.is-alert strong, .voops-partner-kpi.is-alert .voops-partner-kpi__icon { color: var(--voops-error); }

.voops-customer-dashboard { display: grid; grid-template-columns: minmax(0, 1.65fr) minmax(320px, .75fr); gap: 14px; }
.voops-customer-panel { min-width: 0; overflow: hidden; background: var(--voops-surface); border: 1px solid var(--voops-border); border-radius: var(--voops-radius); }
.voops-customer-panel__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 18px; min-height: 70px; padding: 17px 20px; border-bottom: 1px solid var(--voops-border); }
.voops-customer-panel--health .voops-customer-panel__head {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(220px, 360px);
}
.voops-customer-panel__head > div { min-width: 0; }
.voops-customer-panel__head h2 { margin: 0 0 5px; font-size: 16px; }
.voops-customer-panel__head p { margin: 0; color: var(--voops-muted); font-size: 12px; }
.voops-customer-panel__head > a { flex: none; margin-top: 3px; font-size: 12px; font-weight: 600; }
.voops-dashboard-filter { width: 100%; max-width: 360px; min-width: 0; }
.voops-dashboard-filter .voops-input { max-width: 100%; min-width: 0; min-height: 36px; padding: 8px 34px 8px 11px; overflow: hidden; font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }

/* The state column is `minmax(0, auto)`, not `auto`. A bare `auto` track sizes
   to max-content, so a long state label — "Entitlement expired" is the longest —
   widened the row past its card, and because the card is inside the page grid
   the overflow became a horizontal scrollbar on the whole dashboard. Every child
   also gets `min-width: 0`, since a grid item's default `auto` minimum is its
   content and would push the track open again from the inside. */
.voops-estate-health__row { display: grid; grid-template-columns: minmax(180px, 1.3fr) minmax(115px, .7fr) minmax(115px, .7fr) minmax(135px, .8fr) minmax(0, auto); align-items: center; gap: 15px; min-height: 76px; padding: 13px 20px; color: var(--voops-text); border-bottom: 1px solid var(--voops-border); }
.voops-estate-health__row > * { min-width: 0; }
.voops-estate-health__row:last-child { border-bottom: 0; }
.voops-estate-health__row:hover { color: var(--voops-text); background: var(--voops-elevated); }
.voops-estate-health__identity, .voops-estate-health__lanes, .voops-estate-health__sync { display: flex; flex-direction: column; min-width: 0; gap: 5px; font-size: 12px; }
.voops-estate-health__identity strong, .voops-estate-health__identity small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.voops-estate-health__identity small, .voops-estate-health__lanes small, .voops-estate-health__sync small { color: var(--voops-faint); }
.voops-estate-health__lanes { display: grid; grid-template-columns: 8px 1fr; align-items: center; gap: 5px 7px; color: var(--voops-muted); }
.voops-estate-health__lanes small { grid-column: 1 / -1; }
.voops-health-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--voops-faint); }
.voops-health-dot.is-healthy { background: var(--voops-success); box-shadow: 0 0 0 3px var(--voops-success-soft); }
.voops-health-dot.is-degraded, .voops-health-dot.is-rate_limited, .voops-health-dot.is-stale { background: var(--voops-warning); }
.voops-health-dot.is-unreachable, .voops-health-dot.is-authentication_failed, .voops-health-dot.is-permission_changed { background: var(--voops-error); }
/* `width: max-content` with `max-width: 100%` lets the pill shrink; the label
   then wraps at a space rather than spilling. `break-word` and not `anywhere`,
   so a two-word state breaks between the words instead of mid-word. */
.voops-health-state { display: inline-flex; align-items: center; justify-content: center; width: max-content; max-width: 100%; padding: 4px 8px; border-radius: 999px; color: var(--voops-muted); background: var(--voops-elevated); font-size: 11px; font-weight: 600; text-align: center; line-height: 1.3; overflow-wrap: break-word; }
.voops-health-state.is-healthy { color: var(--voops-success); background: var(--voops-success-soft); }
.voops-health-state.is-attention { color: var(--voops-warning); background: var(--voops-warning-soft); }
.voops-health-state.is-disabled { color: var(--voops-faint); }

.voops-activity-list { display: flex; flex-direction: column; }
.voops-activity-item { display: grid; grid-template-columns: 34px minmax(0, 1fr) auto; align-items: center; gap: 11px; min-height: 68px; padding: 11px 18px; border-bottom: 1px solid var(--voops-border); }
.voops-activity-item:last-child { border-bottom: 0; }
.voops-activity-item__icon { display: grid; place-items: center; width: 32px; height: 32px; color: var(--voops-warning); background: var(--voops-warning-soft); border-radius: 50%; }
.voops-activity-item > span:nth-child(2) { display: flex; flex-direction: column; min-width: 0; gap: 4px; }
.voops-activity-item strong, .voops-activity-item small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.voops-activity-item strong { font-size: 12px; }
.voops-activity-item small, .voops-activity-item time { color: var(--voops-muted); font-size: 11px; }
.voops-customer-empty { display: flex; align-items: center; justify-content: center; gap: 9px; min-height: 160px; padding: 24px; color: var(--voops-muted); text-align: center; }
.voops-customer-empty .voops-ico { color: var(--voops-success); }

.voops-integration-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.voops-integration-tile { display: flex; flex-direction: column; align-items: flex-start; min-width: 0; min-height: 155px; padding: 18px; color: var(--voops-text); border-inline-end: 1px solid var(--voops-border); border-bottom: 1px solid var(--voops-border); }
.voops-integration-tile:hover { color: var(--voops-text); background: var(--voops-elevated); }
.voops-integration-tile__mark { display: grid; place-items: center; width: 36px; height: 36px; margin-bottom: 13px; color: var(--voops-on-accent); background: var(--voops-accent); border-radius: var(--voops-radius-xs); font-size: 17px; font-weight: 800; }
.voops-integration-tile strong, .voops-integration-tile small { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.voops-integration-tile strong { font-size: 13px; }
.voops-integration-tile small { margin: 5px 0 13px; color: var(--voops-muted); font-size: 11px; }

.voops-sync-summary { display: flex; align-items: center; justify-content: center; gap: 26px; min-height: 210px; padding: 22px; }
.voops-sync-ring { display: grid; place-items: center; width: 126px; height: 126px; flex: none; }
.voops-sync-ring__chart { grid-area: 1 / 1; width: 126px; height: 126px; transform: rotate(-90deg); }
.voops-sync-ring__chart circle { fill: none; stroke-width: 7; }
.voops-sync-ring__base { stroke: var(--voops-border-2); }
.voops-sync-ring__healthy { stroke: var(--voops-success); }
.voops-sync-ring__attention { stroke: var(--voops-warning); }
.voops-sync-ring__unverified { stroke: var(--voops-faint); }
.voops-sync-ring > span { z-index: 1; grid-area: 1 / 1; display: flex; flex-direction: column; align-items: center; color: var(--voops-muted); font-size: 10px; }
.voops-sync-ring strong { color: var(--voops-text); font-size: 25px; }
.voops-sync-ring__label { display: block; max-width: 84px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.voops-sync-legend { display: flex; flex-direction: column; width: min(170px, 100%); }
.voops-sync-legend > div { display: grid; grid-template-columns: 8px 1fr auto; align-items: center; gap: 8px; min-height: 34px; color: var(--voops-muted); font-size: 11px; border-bottom: 1px solid var(--voops-border); }
.voops-sync-legend > div:last-child { border-bottom: 0; }
.voops-sync-legend span { width: 7px; height: 7px; border-radius: 50%; background: var(--voops-faint); }
.voops-sync-legend span.is-healthy { background: var(--voops-success); }
.voops-sync-legend span.is-attention { background: var(--voops-warning); }
.voops-sync-legend span.is-disabled { background: var(--voops-border-2); }
.voops-sync-legend strong { color: var(--voops-text); }

@media (max-width: 1180px) {
  .voops-partner-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .voops-customer-dashboard { grid-template-columns: 1fr; }
}
@media (max-width: 780px) {
  .voops-customer-panel__head { flex-wrap: wrap; }
  .voops-customer-panel--health .voops-customer-panel__head { grid-template-columns: 1fr; }
  .voops-dashboard-filter { max-width: none; }
  .voops-estate-health__row { grid-template-columns: minmax(0, 1fr) auto; gap: 12px 16px; padding-block: 16px; }
  .voops-estate-health__identity { grid-column: 1; grid-row: 1; }
  .voops-estate-health__lanes--posture { grid-column: 1; grid-row: 2; }
  .voops-estate-health__lanes--inventory { grid-column: 2; grid-row: 2; }
  .voops-estate-health__sync { grid-column: 1 / -1; grid-row: 3; }
  .voops-estate-health__row > .voops-health-state { grid-column: 2; grid-row: 1; }
}
@media (max-width: 560px) {
  .voops-partner-kpis { grid-template-columns: 1fr 1fr; gap: 9px; }
  .voops-partner-kpi { min-height: 126px; padding: 15px; }
  .voops-partner-kpi__icon { top: 13px; inset-inline-end: 13px; width: 30px; height: 30px; }
  .voops-partner-kpi strong { font-size: 26px; }
  .voops-partner-kpi small { overflow: visible; line-height: 1.35; text-overflow: clip; white-space: normal; }
  .voops-customer-panel__head { flex-direction: column; }
  .voops-dashboard-filter { width: 100%; }
  .voops-sync-summary { flex-direction: column; }
}
.voops-menu { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; max-width: 720px; }
.voops-menu__card { display: flex; align-items: flex-start; gap: 14px; padding: 20px; background: var(--voops-surface); border: 1px solid var(--voops-border); border-radius: var(--voops-radius); text-decoration: none; transition: border-color .15s, background .15s; }
.voops-menu__card:hover { border-color: var(--voops-accent); background: var(--voops-elevated); }
.voops-menu__icon { display: inline-flex; align-items: center; justify-content: center; width: 42px; height: 42px; border-radius: var(--voops-radius-sm); background: var(--voops-accent-soft); color: var(--voops-accent); flex-shrink: 0; }
.voops-menu__body { display: flex; flex-direction: column; gap: 3px; }
.voops-menu__title { font-size: 15px; font-weight: 700; color: var(--voops-text); }
.voops-menu__desc { font-size: 13px; color: var(--voops-muted); line-height: 1.45; }

/* tab panels (profile Account | Security, etc.) */
.voops-tabpanel { display: none; }
.voops-tabpanel.is-active { display: block; }

/* MFA enrollment + recovery (profile Security tab) */
.voops-mfa-panel { margin: 6px 0 4px; }
.voops-mfa-actions { display: flex; flex-direction: column; }
.voops-mfa-enroll__step { font-size: 13px; color: var(--voops-muted); margin: 10px 0 8px; }
/* White in BOTH themes on purpose: a QR code needs a white quiet zone to scan. */
.voops-mfa-enroll__qr { display: inline-block; padding: 10px; background: #fff; border-radius: var(--voops-radius-sm); }
.voops-mfa-enroll__qr svg { display: block; }
.voops-mfa-enroll__key { font-size: 13px; color: var(--voops-muted); margin: 12px 0; }
.voops-mfa-enroll__key code, .voops-mfa-recovery__list code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--voops-text); background: var(--voops-surface-2); border: 1px solid var(--voops-border); border-radius: 6px; padding: 2px 6px; letter-spacing: .06em; }
.voops-mfa-recovery__note { font-size: 13px; color: var(--voops-warning); margin: 4px 0 12px; }
.voops-mfa-recovery__list { list-style: none; padding: 0; margin: 0 0 16px; display: grid; grid-template-columns: repeat(2, max-content); gap: 8px 20px; }

/* login MFA: back link under the form */
.voops-auth__alt { margin: 18px 0 0; font-size: 13px; color: var(--voops-muted); }

/* Security tab: clean rows with action on the right */
.voops-seclist { padding: 8px 4px; }
.voops-secrow { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 18px 16px; border-top: 1px solid var(--voops-border); }
.voops-secrow:first-child { border-top: 0; }
.voops-secrow__info { min-width: 0; }
.voops-secrow__title { font-size: 15px; font-weight: 600; color: var(--voops-text); display: flex; align-items: center; gap: 10px; }
.voops-secrow__sub { font-size: 13px; color: var(--voops-muted); margin-top: 3px; }
.voops-secrow__list { padding: 0 16px 14px; display: flex; flex-direction: column; gap: 8px; }

/* a registered passkey chip-row */
.voops-pk { display: flex; align-items: center; gap: 10px; padding: 10px 14px; background: var(--voops-surface-2); border: 1px solid var(--voops-border); border-radius: var(--voops-radius-sm); }
.voops-pk__icon { color: var(--voops-accent); display: inline-flex; }
.voops-pk__name { flex: 1; font-size: 14px; color: var(--voops-text); }
.voops-pk__del { border: 0; background: transparent; color: var(--voops-faint); cursor: pointer; padding: 4px; border-radius: var(--voops-radius-xs); display: inline-flex; }
.voops-pk__del:hover { color: var(--voops-error); background: var(--voops-error-soft); }

/* modal lead text */
.voops-modal__lead { font-size: 13px; color: var(--voops-muted); margin: 0 0 16px; line-height: 1.5; }

/* DKIM generate result */
.voops-dkim-result { padding: 12px 14px; background: var(--voops-accent-soft); border: 1px solid var(--voops-border-2); border-inline-start: 3px solid var(--voops-accent); border-radius: var(--voops-radius-sm); }
.voops-dkim-result__ok { font-size: 13px; color: var(--voops-success); margin: 0 0 10px; }
.voops-dkim-result__code { display: block; word-break: break-all; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; color: var(--voops-text); background: var(--voops-surface-2); border: 1px solid var(--voops-border); border-radius: 6px; padding: 8px 10px; }

/* DKIM section + publishable DNS record */
.ob-dkim { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--voops-border); }
.ob-dkim__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.ob-dkim__title { font-size: 14px; font-weight: 700; color: var(--voops-text); display: flex; align-items: center; gap: 10px; }
.ob-dkim__sub { font-size: 13px; color: var(--voops-muted); margin-top: 3px; max-width: 520px; line-height: 1.5; }
.voops-dnsrec { margin-top: 14px; padding: 14px 16px; background: var(--voops-surface-2); border: 1px solid var(--voops-border); border-radius: var(--voops-radius-sm); }
.voops-dnsrec__ok { font-size: 13px; color: var(--voops-success); margin: 0 0 8px; font-weight: 600; }
.voops-dnsrec__lead { font-size: 13px; color: var(--voops-muted); margin: 0 0 12px; }
.voops-dnsrec__row { display: grid; grid-template-columns: 120px 1fr; gap: 12px; align-items: center; padding: 6px 0; }
.voops-dnsrec__label { font-size: 12px; font-weight: 600; color: var(--voops-faint); text-transform: uppercase; letter-spacing: .04em; }
.voops-dnsrec__val { display: flex; align-items: center; gap: 8px; min-width: 0; }
.voops-dnsrec__code { flex: 1; min-width: 0; word-break: break-all; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; color: var(--voops-text); background: var(--voops-bg); border: 1px solid var(--voops-border); border-radius: 6px; padding: 6px 9px; }
.voops-dnsrec__copy { flex: none; border: 1px solid var(--voops-border-2); background: transparent; color: var(--voops-muted); cursor: pointer; padding: 6px; border-radius: var(--voops-radius-xs); display: inline-flex; }
.voops-dnsrec__copy:hover { color: var(--voops-accent); border-color: var(--voops-accent); }
.voops-dnsrec__copy.is-copied { color: var(--voops-success); border-color: var(--voops-success); }

/* pager (paginated tables) */
.voops-pager { display: flex; align-items: center; justify-content: center; gap: 14px; margin-top: 18px; }
.voops-pager__info { font-size: 13px; color: var(--voops-muted); }
.voops-btn[aria-disabled="true"] { opacity: .5; pointer-events: none; }

/* ─── Branded error pages (centered card, no sidebar) ─────────────────────── */
.voops-error { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 24px; }
.voops-error__card { max-width: 440px; width: 100%; text-align: center; background: var(--voops-surface); border: 1px solid var(--voops-border); border-radius: var(--voops-radius); padding: 44px 40px; box-shadow: 0 30px 80px var(--voops-shadow-mid); }
.voops-error__logo { width: 112px; height: auto; margin: 0 auto 20px; }
.voops-error__code { font-size: 56px; font-weight: 800; line-height: 1; color: var(--voops-accent); letter-spacing: 0; }
.voops-error__title { font-size: 20px; font-weight: 700; margin: 14px 0 8px; }
.voops-error__msg { font-size: 14px; color: var(--voops-muted); line-height: 1.5; margin: 0 0 26px; }
.voops-error__card .voops-btn { width: auto; }

/* ── WYSIWYG editor (Tiptap; editor.js) + rendered prose ─────────────────── */
.voops-ed {
  border: 1px solid var(--voops-border);
  border-radius: 10px;
  background: var(--voops-surface-2);
  overflow: hidden;
}
.voops-ed.focused { border-color: var(--voops-accent); box-shadow: 0 0 0 3px var(--voops-accent-soft); }
.voops-ed-toolbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 2px;
  padding: 6px 8px; border-bottom: 1px solid var(--voops-border);
  background: var(--voops-tint-weak);
}
.voops-ed-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 28px; padding: 0; border: 0; border-radius: 6px;
  background: none; color: var(--voops-muted); cursor: pointer;
}
.voops-ed-btn:hover { background: var(--voops-tint); color: var(--voops-text); }
.voops-ed-btn.active { background: var(--voops-accent-soft); color: var(--voops-accent); }
.voops-ed-sep { width: 1px; height: 18px; background: var(--voops-border); margin: 0 4px; }
.voops-ed-select {
  height: 28px; border: 1px solid var(--voops-border); border-radius: 6px;
  background: var(--voops-surface-2); color: var(--voops-text);
  font-size: 12.5px; padding: 0 6px; cursor: pointer;
}
.voops-ed-content { min-height: 90px; padding: 10px 12px; overflow-y: auto; }
.voops-ed-content--compact { height: 90px; }
.voops-ed-content--comment { height: 150px; }
.voops-ed-content--full { height: 220px; }

/* Rendered rich content (both inside the editor and in the thread). */
.voops-prose { outline: none; color: var(--voops-text); font-size: 14px; line-height: 1.55; }
.voops-prose p { margin: 0 0 .5em; }
.voops-prose p:last-child { margin-bottom: 0; }
.voops-prose h1 { font-size: 1.4em; font-weight: 700; margin: .7em 0 .35em; }
.voops-prose h2 { font-size: 1.2em; font-weight: 600; margin: .6em 0 .3em; }
.voops-prose h3 { font-size: 1.08em; font-weight: 600; margin: .5em 0 .25em; }
.voops-prose ul, .voops-prose ol { padding-inline-start: 1.4em; margin: .4em 0; }
.voops-prose li { margin: .12em 0; }
.voops-prose blockquote {
  border-inline-start: 3px solid var(--voops-border-2); margin: .5em 0; padding-block: .1em; padding-inline-start: .8em;
  color: var(--voops-muted);
}
.voops-prose code {
  background: var(--voops-tint); border-radius: 4px; padding: 1px 5px;
  font-size: 13px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.voops-prose pre {
  background: var(--voops-tint); border: 1px solid var(--voops-border);
  border-radius: 8px; padding: 10px 12px; overflow-x: auto; margin: .5em 0;
}
.voops-prose pre code { background: none; padding: 0; }
.voops-prose hr { border: 0; border-top: 1px solid var(--voops-border); margin: 1em 0; }
.voops-prose a { color: var(--voops-accent); text-decoration: underline; }
.voops-prose img { max-width: 100%; height: auto; border-radius: 8px; margin: .5em 0; }
.voops-prose mark { background: var(--voops-warning-line); border-radius: 2px; padding: 1px 2px; color: inherit; }
.voops-prose table { border-collapse: collapse; width: 100%; margin: .5em 0; }
.voops-prose th, .voops-prose td { border: 1px solid var(--voops-border); padding: 4px 8px; text-align: start; }
.voops-prose th { background: var(--voops-tint-weak); font-weight: 600; font-size: 12.5px; }
.voops-prose p.is-editor-empty:first-child::before {
  content: attr(data-placeholder); color: var(--voops-faint); float: left; pointer-events: none; height: 0;
}

/* ── Ticket attachments ──────────────────────────────────────────────────── */
.voops-attach { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.voops-attach__chip {
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--voops-border); border-radius: 999px;
  padding: 3px 6px 3px 10px; font-size: 12.5px; color: var(--voops-text);
  background: var(--voops-tint-weak);
}
.voops-attach__chip a { color: var(--voops-text); text-decoration: none; }
.voops-attach__chip a:hover { text-decoration: underline; }
.voops-attach__size { color: var(--voops-muted); font-size: 11.5px; }
.voops-attach__x { border: 0; background: none; color: var(--voops-muted); font-size: 15px; line-height: 1; cursor: pointer; padding: 0 2px; }
.voops-attach__x:hover { color: var(--voops-danger); }
.voops-attach-add { display: inline-flex; align-items: center; gap: 6px; margin-top: 8px; }
.voops-attach-add input[type="file"] { font-size: 12.5px; color: var(--voops-muted); }

/* ── Per-integration dashboard (step 11) ─────────────────────────────────── */
.voops-dash__sec { margin: 0 0 34px; }
.voops-dash__h3 { font-size: 13px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase;
  color: var(--voops-muted); margin: 22px 0 10px; }
.voops-dash__lanes { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 14px; max-width: 980px; }
.voops-dash__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 14px; align-items: start; }
.voops-lane { padding: 16px 18px; background: var(--voops-surface); border: 1px solid var(--voops-border); border-radius: var(--voops-radius); }
.voops-lane__head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
.voops-lane__name { font-size: 13px; font-weight: 600; color: var(--voops-text); }

/* Provenance lines. Every panel states where its numbers came from, and a gap says
   which kind of gap it is — these are the styles that carry that distinction. */
.voops-prov { font-size: 12.5px; color: var(--voops-muted); margin: 6px 0; display: flex;
  align-items: center; flex-wrap: wrap; gap: 8px; }
.voops-prov__detail { color: var(--voops-faint); }
.voops-prov--ok { color: var(--voops-success); }
.voops-prov--warn { color: var(--voops-warning); }
.voops-prov--bad { color: var(--voops-danger); }
.voops-prov--foot { margin-top: 30px; padding-top: 16px; border-top: 1px solid var(--voops-border); color: var(--voops-faint); }

/* An absent figure must never look like a number. */
.voops-stat__value--absent { font-size: 15px; font-weight: 500; color: var(--voops-faint); font-style: italic; }

.voops-table--compact td, .voops-table--compact th { padding: 8px 12px; }
.voops-num { text-align: right; font-variant-numeric: tabular-nums; }

.voops-linklist__item { display: block; font-size: 13px; color: var(--voops-accent); text-decoration: none; }
.voops-linklist__item:hover { text-decoration: underline; }
/* The client-profile integration links carry BOTH classes. `display: block`
   above is declared later than `.voops-inline-action`'s `inline-flex` and at
   equal specificity, so it silently won and the trailing "open" icon wrapped
   onto its own line under the name. Name the pair so the row cannot break:
   the name truncates, the icon never leaves it. */
.voops-linklist__item.voops-inline-action { display: flex; align-items: center; gap: 6px; }
.voops-linklist__item.voops-inline-action > span {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}

.voops-badge--muted { color: var(--voops-muted); background: var(--voops-tint); border-color: var(--voops-border-2); }
.voops-badge--health-healthy { color: var(--voops-success); background: var(--voops-success-soft); border-color: var(--voops-success-line); }
.voops-badge--health-degraded,
.voops-badge--health-rate_limited,
.voops-badge--health-stale { color: var(--voops-warning); background: var(--voops-warning-soft); border-color: var(--voops-warning-line); }
.voops-badge--health-unreachable,
.voops-badge--health-authentication_failed,
.voops-badge--health-permission_changed { color: var(--voops-danger); background: var(--voops-error-soft); border-color: var(--voops-error-line); }
.voops-badge--health-unverified { color: var(--voops-faint); background: var(--voops-tint); border-color: var(--voops-border-2); }
.voops-badge--risk-high,
.voops-badge--risk-critical { color: var(--voops-danger); background: var(--voops-error-soft); border-color: var(--voops-error-line); }
.voops-badge--risk-medium { color: var(--voops-warning); background: var(--voops-warning-soft); border-color: var(--voops-warning-line); }
.voops-badge--risk-low { color: var(--voops-success); background: var(--voops-success-soft); border-color: var(--voops-success-line); }

/* ── Trends (step 11, increment 2) ───────────────────────────────────────── */
.voops-trend__windows { display: flex; gap: 6px; margin: 0 0 14px; }
.voops-trend__windows .is-active { border-color: var(--voops-accent); color: var(--voops-accent); }
.voops-trend__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 18px; }
.voops-trend { margin: 0; padding: 16px 18px; background: var(--voops-surface);
  border: 1px solid var(--voops-border); border-radius: var(--voops-radius); }
.voops-trend__cap { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.voops-trend__name { font-size: 13px; font-weight: 600; color: var(--voops-text); }
.voops-trend__dir { font-size: 11.5px; color: var(--voops-faint); }
.voops-trend__svg { width: 100%; height: 90px; display: block; overflow: visible; }
.voops-trend__line { fill: none; stroke: var(--voops-accent); stroke-width: 1.5;
  vector-effect: non-scaling-stroke; stroke-linejoin: round; stroke-linecap: round; }
.voops-trend__dot { fill: var(--voops-accent); }
/* A generation boundary is a discontinuity, not a gridline — dashed and muted so it reads
   as "something changed here", never as part of the series. */
.voops-trend__gen { stroke: var(--voops-warning); stroke-width: 1; stroke-dasharray: 3 3;
  vector-effect: non-scaling-stroke; opacity: .7; }
.voops-trend__axis { display: flex; justify-content: space-between; gap: 10px; margin-top: 6px;
  font-size: 11.5px; color: var(--voops-faint); font-variant-numeric: tabular-nums; }
.voops-trend__warn { color: var(--voops-warning); }
.voops-prov--foot-sm { font-size: 11.5px; margin: 4px 0 0; }

/* ── CSV export links ────────────────────────────────────────────────────── */
.voops-export { float: right; font-size: 12px; font-weight: 500; color: var(--voops-muted);
  text-decoration: none; border: 1px solid var(--voops-border-2); border-radius: 999px;
  padding: 3px 12px; }
.voops-export:hover { color: var(--voops-accent); border-color: var(--voops-accent); }


/* Requirement checklist under a password field. Kept tight against the hint text
   it belongs to rather than carrying the browser's default list indent. */
.voops-hint__list { margin: 4px 0 0; padding-inline-start: 18px; }

/* Arabic layout follows document direction while technical values above stay LTR.
   "Geist Mono" stays at the head of this stack for the same reason it heads the
   default one: it declares only U+0030-0039, so it claims the digits and lets
   Noto Sans Arabic draw the script. Dropping it here would have made Arabic the
   one locale whose numbers were not on the numeral face. */
html[dir="rtl"] body {
  font-family: "Geist Mono", "Noto Sans Arabic", "Segoe UI", Tahoma, sans-serif;
}
html[dir="rtl"] .voops-toggle__thumb { left: auto; right: 2px; transition: right .2s; }
html[dir="rtl"] .voops-toggle input:checked + .voops-toggle__track .voops-toggle__thumb { left: auto; right: 19px; }

@media (max-width: 720px) {
  .voops-content__actions { width: 100%; }
  .voops-content__actions .voops-btn { max-width: 100%; white-space: normal; }
}
.voops-hint__list li { margin: 0; line-height: 1.5; }


/* Actions live inside a normal table cell. The colgroup owns the width; the inner
   flex row owns alignment and spacing. Putting flex directly on a td removes it
   from table-cell layout and lets controls escape the table boundary. */
.voops-table__action-cell > .voops-table__actions { width: 100%; }

/* A disabled action stays a button — same box, same alignment — so an unavailable
   control reads as unavailable rather than as a rendering fault. Client-profile
   Enable at quota used to be bare muted text sitting beside real buttons. */
.voops-table__actions .voops-btn[disabled],
.voops-table__actions .voops-btn[aria-disabled="true"] {
  opacity: .45; cursor: not-allowed; pointer-events: none;
}

/* Confirmation dialog body: prose, not a control label. */
.voops-confirm__body { margin: 0; line-height: 1.6; }

/* Type-to-confirm. Only rendered for actions that opt in, so the default
   confirmation keeps its two-button shape. */
.voops-confirm__phrase { display: grid; gap: 8px; margin-top: 16px; }
.voops-confirm__phrase[hidden] { display: none; }
.voops-confirm__phrase-chip {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 8px 10px; border: 1px solid var(--voops-border-2);
  border-radius: 8px; background: var(--voops-surface-2);
}
/* The name is the thing being copied, so it wraps rather than truncating: a
   clipped name is one the reader cannot check against what they typed. */
.voops-confirm__phrase-chip code {
  font-family: var(--voops-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 12.5px; overflow-wrap: anywhere;
}

/* "The audit log could not be read" — deliberately NOT the tampered styling.
   Tampered is a finding; unavailable is an absence of evidence, and an operator
   must be able to tell them apart without reading the tooltip. */
.voops-badge--unavailable { color: var(--voops-muted); background: var(--voops-tint); border-color: var(--voops-border-2); }

/* Integrations are grouped by purpose. Each provider owns its status and action so
   adding a destination never starts from an ambiguous global "Add" command. */
.voops-integrations__group { margin: 0 0 34px; }
.voops-integrations__heading { display: flex; align-items: flex-start; gap: 10px; margin-bottom: 12px; }
.voops-integrations__heading-icon { display: grid; place-items: center; width: 30px; height: 30px;
  color: var(--voops-accent); border: 1px solid var(--voops-border-2); border-radius: 6px; }
.voops-integrations__heading h2 { margin: 0; font-size: 17px; line-height: 1.35; }
.voops-integrations__heading p { margin: 2px 0 0; color: var(--voops-muted); font-size: 13px; }
.voops-provider-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.voops-provider { border: 1px solid var(--voops-border); border-radius: var(--voops-radius);
  background: var(--voops-surface); overflow: hidden; }
.voops-provider--compact { min-height: 190px; display: flex; flex-direction: column; }
.voops-provider__head { display: flex; align-items: flex-start; justify-content: space-between;
  gap: 16px; padding: 16px 18px 13px; }
.voops-provider__head h3 { margin: 0; font-size: 14px; line-height: 1.35; }
.voops-provider__head p { margin: 5px 0 0; color: var(--voops-muted); font-size: 12.5px; line-height: 1.45; }
.voops-provider__mark { flex: 0 0 auto; display: grid; place-items: center; width: 34px; height: 34px;
  border-radius: 6px; color: var(--voops-on-accent); background: var(--voops-series-5); font-size: 10px; font-weight: 700; }
.voops-provider__mark--trend { background: #d71920; }
.voops-provider__mark--slack { background: #4a154b; }
.voops-provider__mark--microsoft_teams { background: #6264a7; }
.voops-provider__mark--google_chat { background: #137333; }
.voops-provider__mark--whatsapp { background: #0b7a47; }
.voops-provider__table { border-top: 1px solid var(--voops-border); }
.voops-provider__table .voops-table { margin: 0; }
.voops-provider__empty { padding: 15px 18px; border-top: 1px solid var(--voops-border);
  color: var(--voops-muted); font-size: 13px; }
.voops-provider__state { padding: 0 18px 14px; }
.voops-provider__actions { margin-top: auto; padding: 11px 18px;
  border-top: 1px solid var(--voops-border); }
@media (max-width: 920px) { .voops-provider-grid { grid-template-columns: 1fr; } }

/* Compact client grants. The scope is one decision; the client list appears only
   when it is relevant and remains searchable as an estate grows. */
/* Partner invite: client reach on its own row, then email and role. */
.voops-invite .voops-inline-form:has(.voops-client-access) {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto;
  gap: 14px; align-items: end;
}
.voops-invite .voops-inline-form:has(.voops-client-access) .voops-client-access {
  grid-column: 1 / -1; order: -1; min-width: 0; width: 100%;
}
.voops-invite .voops-inline-form:has(.voops-client-access) > .voops-input,
.voops-invite .voops-inline-form:has(.voops-client-access) > .voops-select { min-width: 0; width: 100%; }
.voops-invite .voops-inline-form:has(.voops-client-access) #invite-result { grid-column: 1 / -1; }
@media (max-width: 760px) {
  .voops-invite .voops-inline-form:has(.voops-client-access) { grid-template-columns: 1fr; }
}

.voops-client-access { min-width: min(100%, 360px); }
.voops-client-access > .voops-label { display: block; margin-bottom: 6px; }
.voops-client-access > .voops-select { width: 100%; }
.voops-multiselect { position: relative; margin-top: 8px; }
.voops-multiselect__toggle { width: 100%; min-height: 40px; padding: 10px 38px 10px 12px;
  text-align: start; color: var(--voops-text); background: var(--voops-surface-2);
  border: 1px solid var(--voops-border); border-radius: var(--voops-radius-sm); cursor: pointer; }
.voops-multiselect__toggle::after { content: "⌄"; position: absolute; inset-inline-end: 13px; color: var(--voops-muted); }
.voops-multiselect__toggle:focus-visible { outline: 2px solid var(--voops-accent); outline-offset: 2px; }
.voops-multiselect__menu { position: absolute; z-index: 30; inset-inline: 0; top: calc(100% + 5px);
  padding: 8px; background: var(--voops-surface); border: 1px solid var(--voops-border-2);
  border-radius: var(--voops-radius-sm); box-shadow: 0 12px 30px var(--voops-shadow-soft); }
.voops-multiselect.is-open-up .voops-multiselect__menu { bottom: calc(100% + 5px); top: auto; }
.voops-multiselect__menu[hidden] { display: none; }
.voops-multiselect__search { width: 100%; margin-bottom: 7px; }
.voops-multiselect__options { max-height: 230px; overflow-y: auto; overscroll-behavior: contain; }
.voops-picker-empty { color: var(--voops-muted); padding: 13px 10px; text-align: center; }
.voops-picker-empty[hidden] { display: none; }
.voops-modal .voops-multiselect__menu {
  position: static; margin-top: 5px;
}
.voops-modal .voops-multiselect.is-open-up .voops-multiselect__menu {
  inset: auto;
}
.voops-modal .voops-multiselect__options { max-height: min(230px, 35vh); }
.voops-multiselect__group { padding: 10px 8px 5px; color: var(--voops-muted); font-size: 12px; font-weight: 700; text-transform: uppercase; }
.voops-multiselect__option { display: flex; align-items: center; gap: 9px; padding: 9px 8px;
  border-radius: 4px; cursor: pointer; color: var(--voops-text); line-height: 1.35; }
.voops-multiselect__option[hidden] { display: none; }
.voops-multiselect__option:hover { background: var(--voops-tint); }
.voops-multiselect__option input { position: absolute; width: 1px; height: 1px; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); clip-path: inset(50%); white-space: nowrap; }
.voops-multiselect__indicator { border: solid var(--voops-accent); border-width: 0 2px 2px 0;
  box-sizing: border-box; flex: 0 0 7px; height: 12px; margin: 0 5px 3px 4px;
  opacity: 0; transform: rotate(45deg) scale(.8);
  transition: opacity 120ms ease, transform 120ms ease; }
.voops-multiselect__label { flex: 1 1 auto; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.voops-multiselect__option:has(input:checked) { background: var(--voops-accent-soft); }
.voops-multiselect__option input:checked + .voops-multiselect__indicator {
  opacity: 1; transform: rotate(45deg) scale(1); }
.voops-multiselect__option:focus-within { background: var(--voops-tint); outline: 2px solid var(--voops-accent); outline-offset: -2px; }
.voops-multiselect__option:has(input:disabled) { background: transparent; color: var(--voops-muted);
  cursor: not-allowed; opacity: .38; }
.voops-multiselect__option:has(input:disabled):hover { background: transparent; }
.voops-multiselect__pills { display: flex; flex-wrap: nowrap; gap: 6px; margin-top: 8px; min-width: 0; overflow: hidden; }
.voops-multiselect__pills .voops-tag { min-width: 0; }
.voops-multiselect__pills .voops-tag__label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.voops-multiselect__more { color: var(--voops-muted); flex: 0 0 auto; font-size: 12px; font-weight: 700; }
.voops-multiselect--inline-pills .voops-multiselect__control {
  align-items: center; background: var(--voops-surface-2); border: 1px solid var(--voops-border);
  border-radius: var(--voops-radius-sm); display: flex; min-height: 40px; padding-inline-start: 8px;
}
.voops-multiselect--inline-pills .voops-multiselect__control:focus-within {
  outline: 2px solid var(--voops-accent); outline-offset: 2px;
}
.voops-multiselect--inline-pills .voops-multiselect__pills {
  align-items: center; flex: 0 1 auto; margin: 0; min-width: 0; padding-block: 6px;
}
.voops-multiselect--inline-pills .voops-multiselect__toggle {
  align-self: stretch; background: transparent; border: 0; flex: 1 1 80px; min-width: 44px;
  outline: 0; padding: 0 8px;
}
.voops-multiselect--inline-pills .voops-multiselect__toggle::after { content: none; }
.voops-multiselect--inline-pills .voops-multiselect__toggle:focus-visible { outline: 0; }
.voops-single-select { position: relative; width: min(100%, 520px); }
.voops-single-select__toggle {
  align-items: center; background: var(--voops-surface-2); border: 1px solid var(--voops-border);
  border-radius: var(--voops-radius-sm); color: var(--voops-text); cursor: pointer; display: flex;
  min-height: 40px; padding: 10px 38px 10px 12px; position: relative; text-align: start; width: 100%;
}
.voops-single-select__toggle::after {
  border: solid currentColor; border-width: 0 1.5px 1.5px 0; content: ""; height: 7px;
  inset-inline-end: 15px; position: absolute; top: 16px; transform: rotate(45deg); width: 7px;
}
.voops-single-select__toggle:focus-visible { outline: 2px solid var(--voops-accent); outline-offset: 2px; }
.voops-single-select__toggle:disabled {
  cursor: not-allowed; opacity: .45; background: var(--voops-surface);
}
.voops-single-select__toggle span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.voops-single-select__menu {
  background: var(--voops-surface); border: 1px solid var(--voops-border-2);
  border-radius: var(--voops-radius-sm); box-shadow: 0 12px 30px var(--voops-shadow-soft);
  inset-inline: 0; padding: 8px; position: absolute; top: calc(100% + 5px); z-index: 80;
}
.voops-single-select__menu[hidden] { display: none; }
.voops-single-select__search { margin-bottom: 7px; width: 100%; }
.voops-single-select__options { max-height: 280px; overflow-y: auto; overscroll-behavior: contain; }
.voops-single-select__option {
  align-items: center; background: transparent; border: 0; border-radius: 4px; color: var(--voops-text);
  cursor: pointer; display: flex; gap: 10px; min-height: 40px; padding: 9px 8px; text-align: start; width: 100%;
}
.voops-single-select__option[hidden] { display: none; }
.voops-single-select__option:hover { background: var(--voops-tint); }
.voops-single-select__option:focus-visible { outline: 2px solid var(--voops-accent); outline-offset: -2px; }
.voops-single-select__check { color: transparent; flex: 0 0 16px; font-weight: 800; }
.voops-single-select__option.is-selected { background: var(--voops-accent-soft); color: var(--voops-accent); font-weight: 700; }
.voops-single-select__option.is-selected .voops-single-select__check { color: var(--voops-accent); }
.voops-single-select__option-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 820px) {
  .voops-inline-form { align-items: stretch; }
  .voops-client-access { width: 100%; }
}

/* Scheduled TrendAI reports: one deliberate workflow, followed by saved schedules and
   history. Controls share a baseline so a long label never makes the row look accidental. */
.voops-reports__overview { display: flex; align-items: flex-start; justify-content: space-between;
  gap: 28px; padding: 0 0 22px; margin-bottom: 24px; border-bottom: 1px solid var(--voops-border); }
.voops-reports__overview h2 { margin: 0 0 5px; font-size: 17px; }
.voops-reports__overview p { max-width: 680px; margin: 0; color: var(--voops-muted); line-height: 1.55; }
.voops-reports__contents { display: grid; grid-template-columns: repeat(2, minmax(130px, 1fr));
  gap: 7px 18px; margin: 0; padding: 0; list-style: none; color: var(--voops-text); font-size: 13px; }
.voops-reports__contents li::before { content: "✓"; margin-inline-end: 7px; color: var(--voops-success); }
.voops-reports__builder, .voops-reports__saved { padding: 26px 0 30px; border-bottom: 1px solid var(--voops-border); }
.voops-reports__saved--last { border-bottom: 0; }
.voops-reports__section-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 20px; margin-bottom: 22px; }
.voops-reports__section-head h2 { margin: 0 0 5px; font-size: 18px; }
.voops-reports__section-head p { margin: 0; color: var(--voops-muted); }
.voops-reset-fieldset { min-width: 0; margin: 0; padding: 0; border: 0; }
.voops-report-steps { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0;
  margin: 0; padding: 0; list-style: none; border: 1px solid var(--voops-border); border-radius: var(--voops-radius-sm); }
.voops-report-step { display: flex; gap: 13px; min-width: 0; padding: 20px; align-items: flex-start; }
.voops-report-step + .voops-report-step { border-inline-start: 1px solid var(--voops-border); }
.voops-report-step__number { display: grid; place-items: center; flex: 0 0 27px; width: 27px; height: 27px;
  border-radius: 50%; background: var(--voops-accent); color: var(--voops-on-accent); font-weight: 750; font-size: 12px; }
.voops-report-step__body { flex: 1 1 auto; min-width: 0; }
.voops-report-step__grid { display: grid; grid-template-columns: 1fr; gap: 14px; }
.voops-report-type-picker { display: grid; gap: 8px; margin-top: 8px; }
.voops-report-type-option { display: flex; align-items: flex-start; gap: 9px; padding: 10px;
  border: 1px solid var(--voops-border); border-radius: 6px; cursor: pointer; }
.voops-report-type-option:has(input:checked) { border-color: var(--voops-accent); background: var(--voops-accent-soft); }
.voops-report-type-option input { margin-top: 3px; accent-color: var(--voops-accent); }
.voops-report-type-option strong, .voops-report-type-option small { display: block; }
.voops-report-type-option small { margin-top: 3px; color: var(--voops-muted); line-height: 1.35; }
.voops-reports__recipients { width: 100%; }
.voops-form-actions, .voops-form__actions {
  display: flex; align-items: center; gap: 10px; margin-top: 18px; flex-wrap: wrap;
}
.voops-form-actions .voops-btn, .voops-form__actions .voops-btn { width: auto; }
.voops-form-grid { display: grid; gap: 16px; min-width: 0; }
.voops-form-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.voops-form-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.voops-form-grid--actions { align-items: end; grid-template-columns: minmax(0, 1fr) auto; }
.voops-form-grid__wide { grid-column: 1 / -1; }
.voops-form-grid__action { align-self: end; }
.voops-table-wrap { width: 100%; overflow-x: auto; border-radius: var(--voops-radius); }
.voops-table__sub { display: block; margin-top: 3px; color: var(--voops-muted); font-size: 12px; }
.voops-table--actions td { vertical-align: middle; }
.voops-actions { display: flex; justify-content: flex-end; align-items: center; gap: 8px; white-space: nowrap; }
.voops-btn--icon { display: inline-grid; place-items: center; width: 38px; min-width: 38px; height: 38px; padding: 0; }
/* ── Split button ─────────────────────────────────────────────────────────────
   One continuous control, not two buttons touching. The halves share a radius
   at the outer edges and meet on a seam; the seam is a dark hairline because a
   bright one on an orange gradient reads as a crack between two objects rather
   than a division within one.

   Height comes from the button contract rather than a literal, so this sits on
   the same baseline as the controls beside it. It was 38px against everything
   else's 40px, which is why it never quite lined up. */
.voops-split-button {
  display: inline-flex; flex: 0 0 auto; align-items: stretch;
  min-height: 40px; border-radius: var(--voops-radius-sm);
  box-shadow: var(--voops-btn-highlight);
}
.voops-split-button__main {
  flex: 0 0 auto; min-width: max-content; white-space: nowrap;
  border-start-end-radius: 0; border-end-end-radius: 0;
  box-shadow: none;
}
.voops-split-button__menu { position: relative; flex: 0 0 auto; display: flex; }
.voops-split-button__menu > summary {
  display: grid; place-items: center; list-style: none; height: 100%;
}
.voops-split-button__menu > summary::-webkit-details-marker { display: none; }
.voops-split-button__toggle {
  width: 40px; min-width: 40px; height: 100%; min-height: 40px; padding: 0;
  color: var(--voops-on-accent); box-shadow: none;
  border-inline-start: 1px solid var(--voops-split-seam);
  border-start-start-radius: 0; border-end-start-radius: 0;
}
.voops-split-button__toggle svg { display: block; transition: transform .18s; }
/* The caret points at the menu it opened. */
.voops-split-button__menu[open] .voops-split-button__toggle svg { transform: rotate(180deg); }

/* Same card as the quick-actions menu: a page should not have two shapes of
   dropdown. Positioned in script, which is why it is `fixed`. */
.voops-split-button__popover {
  display: none; position: fixed; z-index: 950; min-width: 224px; padding: 8px;
  background: var(--voops-menu-bg); border: 1px solid var(--voops-border);
  border-radius: var(--voops-radius); box-shadow: 0 20px 50px var(--voops-shadow-deep);
}
.voops-split-button__popover.is-open { display: grid; gap: 2px; }
.voops-split-button__popover a,
.voops-split-button__option {
  display: block; width: 100%; text-align: start; padding: 10px 12px;
  border-radius: 9px; color: var(--voops-muted); text-decoration: none;
  font-size: 13.5px; font-weight: 550; white-space: nowrap;
  background: transparent; border: 0; cursor: pointer; font-family: inherit;
}
/* `--voops-text`, not `--voops-on-accent`: the ground here is a neutral tint,
   not the accent. My token sweep turned this white, which on a light theme is
   white text on a pale hover — invisible. */
.voops-split-button__popover a:hover,
.voops-split-button__popover a:focus-visible,
.voops-split-button__option:hover,
.voops-split-button__option:focus-visible {
  background: var(--voops-elevated); color: var(--voops-text); outline: none;
}

.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
.voops-reports__types {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 18px 28px;
}
.voops-reports__types h3 {
  margin: 0 0 8px; font-size: 12px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--voops-muted);
}

.voops-reports__history { margin-top: 34px; padding-top: 0; }
@media (max-width: 900px) {
  .voops-reports__overview { display: block; }
  .voops-reports__contents { margin-top: 16px; }
  .voops-report-steps { grid-template-columns: 1fr; }
  .voops-report-step + .voops-report-step { border-inline-start: 0; border-top: 1px solid var(--voops-border); }
  .voops-actions { justify-content: flex-start; }
  .voops-form-grid--2, .voops-form-grid--3, .voops-form-grid--actions { grid-template-columns: 1fr; }
}
.voops-brand-logo {
  align-items: center; background: var(--voops-surface-2); border: 1px solid var(--voops-border-2);
  border-radius: 6px; color: var(--voops-text); display: inline-flex; flex: 0 0 auto;
  font-size: 11px; font-weight: 700; height: 32px; justify-content: center;
  overflow: hidden; position: relative; width: 32px;
}
.voops-brand-logo--lg { height: 48px; width: 48px; font-size: 14px; }
.voops-brand-logo--sm { height: 26px; width: 26px; font-size: 9px; }
.voops-brand-logo__fallback { align-items: center; display: flex; inset: 0; justify-content: center; position: absolute; }
.voops-brand-logo__fallback svg { height: 55%; width: 55%; }
/* White in BOTH themes on purpose: customer logos are drawn for a white ground
   and a dark plate behind them makes half of them unreadable. */
.voops-brand-logo__image { background: #fff; height: 100%; object-fit: contain; padding: 4px; position: relative; width: 100%; z-index: 1; }
.voops-brand-identity { align-items: center; display: flex; gap: 10px; min-width: 0; }
.voops-brand-identity > span:last-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.voops-partner-heading { align-items: center; display: grid; gap: 14px; grid-template-columns: 48px minmax(0, 1fr); min-width: 0; }
.voops-partner-heading__copy { display: grid; gap: 7px; min-width: 0; }
.voops-partner-heading__name { line-height: 1.1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.voops-partner-heading__meta { align-items: center; color: var(--voops-muted); display: flex; flex-wrap: wrap; font-size: 14px; font-weight: 400; gap: 6px; line-height: 1.35; min-width: 0; }
.voops-partner-heading__domains { min-width: 0; overflow-wrap: anywhere; }
.voops-brand-settings { align-items: center; display: flex; gap: 24px; justify-content: space-between; margin-block: 4px 18px; }
/* The identity block is a logo beside a two-line stack, so the logo aligns to
   the top of that stack rather than to the centre of a block whose height
   depends on how long the hint wraps. */
.voops-brand-settings .voops-brand-identity { align-items: flex-start; gap: 14px; }
.voops-brand-settings .voops-brand-identity > div { display: grid; gap: 4px; min-width: 0; }
.voops-brand-settings .voops-brand-identity .voops-card__h { margin: 0; line-height: 1.25; }
.voops-brand-settings .voops-brand-identity .voops-hint { margin: 0; }
.voops-brand-settings__controls { margin-top: 18px !important; padding-top: 18px !important;
  border-top: 1px solid var(--voops-border) !important; }
.voops-brand-preview {
  align-items: center; background: var(--voops-surface); border: 1px solid var(--voops-border);
  border-radius: 6px; display: flex; gap: 14px; margin-top: 16px; padding: 12px 14px;
}
.voops-brand-preview__copy { display: grid; gap: 3px; min-width: 0; }
.voops-brand-preview__copy strong { color: var(--voops-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.voops-brand-preview__copy span { color: var(--voops-muted); font-size: 13px; }
.voops-brand-settings__controls { align-items: end; border: 0; display: flex; gap: 12px; margin: 0; padding: 0; }
.voops-brand-settings__controls form { align-items: end; display: grid; gap: 10px; grid-template-columns: minmax(260px, 520px) auto; }
.voops-brand-settings__controls form .voops-label { grid-column: 1 / -1; }
.voops-partner-regions { align-items: end; display: grid; gap: 24px; grid-template-columns: minmax(240px, .7fr) minmax(420px, 1.3fr); }
.voops-partner-regions form { align-items: end; display: grid; gap: 12px; grid-template-columns: minmax(320px, 1fr) auto; }
.voops-settings-row { align-items: center; display: grid; gap: 32px; grid-template-columns: minmax(260px, .75fr) minmax(520px, 1.25fr); }
.voops-settings-row__controls { align-items: end; display: flex; gap: 12px; justify-content: flex-end; min-width: 0; }
.voops-settings-row__controls > .voops-multiselect { flex: 1 1 420px; min-width: 0; }
.voops-settings-row__controls > form { align-items: end; display: grid; flex: 1 1 560px; gap: 12px; grid-template-columns: minmax(260px, 1fr) auto; min-width: 0; }
.voops-settings-row__controls > form .voops-label { grid-column: 1 / -1; }
.voops-settings-row__form { display: grid; gap: 12px; min-width: 0; }
.voops-settings-row__form > .voops-multiselect { margin-top: 0; }
.voops-settings-row__form > .voops-form-actions { justify-content: flex-start; margin: 0; }
.voops-instance-add { display: grid; grid-template-columns: minmax(180px, .7fr) minmax(300px, 1.3fr) auto; }
.voops-instances-table__name { width: 20%; }
.voops-instances-table__address { width: 27%; }
.voops-instances-table__release { width: 13%; }
.voops-instances-table__health { width: 12%; }
.voops-instances-table__checked { width: 18%; }
.voops-instances-table__actions { width: 10%; }
.voops-health-count--good { color: var(--voops-success); }
.voops-health-count--bad { color: var(--voops-danger); }
.voops-btn--nowrap { white-space: nowrap; }
.voops-policy-summary { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px;
  margin-bottom: 24px; overflow: hidden; border: 1px solid var(--voops-border); border-radius: var(--voops-radius-sm); background: var(--voops-border); }
.voops-policy-summary > div { display: grid; gap: 7px; padding: 18px 20px; background: var(--voops-surface); }
.voops-policy-summary span { color: var(--voops-faint); font-size: 11px; font-weight: 700; text-transform: uppercase; }
.voops-policy-summary strong { font-size: 21px; }
.voops-policy-summary .voops-policy-approved { color: var(--voops-success); }
.voops-quick-filter { align-items: center; display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 30px; }
.voops-quick-filter__pill { align-items: center; background: transparent; border: 1px solid var(--voops-border);
  border-radius: 5px; color: var(--voops-muted); cursor: pointer; display: inline-flex; font: inherit;
  font-size: 13px; font-weight: 600; gap: 7px; min-height: 34px; padding: 6px 12px; text-decoration: none; }
.voops-quick-filter__pill:hover { border-color: var(--voops-muted); color: var(--voops-text); }
.voops-quick-filter__pill.is-active { border-color: var(--voops-accent); color: var(--voops-accent); }
.voops-quick-filter__remove { font-size: 17px; line-height: 1; opacity: .7; }
.voops-quick-filter__picker { position: relative; }
.voops-quick-filter__trigger { align-items: center; background: transparent; border: 1px solid var(--voops-border);
  border-radius: 5px; color: var(--voops-accent); cursor: pointer; display: inline-flex; height: 34px;
  justify-content: center; padding: 0; width: 36px; }
.voops-quick-filter__trigger:hover { background: var(--voops-tint); border-color: var(--voops-muted); }
.voops-quick-filter__trigger:focus-visible, .voops-quick-filter__pill:focus-visible {
  outline: 2px solid var(--voops-accent); outline-offset: 2px; }
.voops-quick-filter__menu { background: var(--voops-surface); border: 1px solid var(--voops-border);
  border-radius: var(--voops-radius-sm); box-shadow: 0 12px 30px var(--voops-shadow-soft); inset-inline-start: 0;
  min-width: min(360px, calc(100vw - 40px)); padding: 10px; position: absolute; top: calc(100% + 7px); z-index: 40; }
.voops-quick-filter__menu[hidden] { display: none; }
.voops-quick-filter__search { margin-bottom: 8px; width: 100%; }
.voops-quick-filter__options { max-height: 280px; overflow-y: auto; }
.voops-quick-filter__option { align-items: center; border-radius: 4px; cursor: pointer; display: flex;
  gap: 9px; padding: 9px 8px; }
.voops-quick-filter__option[hidden] { display: none; }
.voops-quick-filter__option:hover { background: var(--voops-tint); }
.voops-quick-filter__option:has(input:disabled) { cursor: not-allowed; opacity: .45; }
.voops-quick-filter__option input { height: 1px; opacity: 0; overflow: hidden; pointer-events: none;
  position: absolute; width: 1px; }
.voops-quick-filter__check { color: transparent; flex: 0 0 16px; font-size: 14px; font-weight: 800; }
.voops-quick-filter__option:has(input:checked) { color: var(--voops-accent); font-weight: 700; }
.voops-quick-filter__option:has(input:checked) .voops-quick-filter__check { color: var(--voops-accent); }
.voops-quick-filter__option:has(input:focus-visible) { outline: 2px solid var(--voops-accent); outline-offset: -2px; }
.voops-quick-filter__limit { border-top: 1px solid var(--voops-border); color: var(--voops-muted);
  font-size: 12px; margin: 8px -2px -2px; padding: 9px 2px 2px; }
.voops-policy-product { margin-top: 34px; }
.voops-policy-product > header { display: flex; align-items: end; justify-content: space-between; gap: 24px; margin-bottom: 12px; }
.voops-policy-product h2 { margin: 0 0 4px; font-size: 18px; }
.voops-policy-product header p { margin: 0; color: var(--voops-muted); font-size: 13px; }
.voops-policy-table { table-layout: fixed; min-width: 900px; }
.voops-policy-table__policy-col { width: 25%; }
.voops-policy-table__category-col { width: 16%; }
.voops-policy-table__priority-col { width: 12%; }
.voops-policy-table__state-col { width: 47%; }
.voops-policy-instances { table-layout: fixed; min-width: 720px; }
.voops-policy-instances__name-col { width: 35%; }
.voops-policy-instances__role-col { width: 15%; }
.voops-policy-instances__version-col, .voops-policy-instances__seen-col { width: 25%; }
.voops-policy-table td { vertical-align: top; line-height: 1.5; }
.voops-policy-table td small, .voops-policy-instances td small { display: block; margin-top: 5px; color: var(--voops-muted); }
/* `minmax(0, 1fr)`, not `minmax(160px, 1fr)`. Five tracks with a 160px floor
   plus the gaps need ~856px before anything can shrink, so on a narrower column
   the grid overflowed its container instead of compressing — which is what made
   the filters appear to overlap and pushed the section below them out of line.
   At zero minimum the tracks compress and the toggle's inner span truncates,
   which it was already styled to do. The narrow breakpoint below still drops
   this to two columns. */
.voops-gap-filter { display: grid; gap: 14px; grid-template-columns: repeat(5, minmax(0, 1fr)); margin-bottom: 18px; }
.voops-gap-filter > label { display: grid; gap: 7px; min-width: 0; }
.voops-gap-filter .voops-single-select { width: 100%; }
.voops-gap-chart { display: grid; gap: 10px; margin-bottom: 16px; }
.voops-gap-notice { align-items: flex-start; display: grid; gap: 4px; margin-bottom: 18px; }
.voops-gap-notice span { color: var(--voops-muted); line-height: 1.45; }
.voops-gap-kpis { margin-bottom: 28px; }
.voops-gap-kpi-date { font-size: 17px !important; }
.voops-gap-section { border-top: 1px solid var(--voops-border); padding: 26px 0 30px; }
.voops-disclosure > summary { cursor: pointer; list-style: none; }
.voops-disclosure > summary::-webkit-details-marker { display: none; }
.voops-disclosure__summary { align-items: flex-start; display: flex; gap: 20px; justify-content: space-between; }
.voops-disclosure__copy { display: grid; gap: 5px; min-width: 0; }
.voops-disclosure__title { color: var(--voops-text); font-size: 18px; font-weight: 700; }
.voops-disclosure__body { color: var(--voops-muted); line-height: 1.5; }
.voops-disclosure__meta { align-items: center; display: flex; flex: none; gap: 10px; }
.voops-disclosure__chevron { display: inline-flex; transition: transform 150ms ease; }
.voops-disclosure[open] .voops-disclosure__chevron { transform: rotate(180deg); }
.voops-disclosure__content { margin-top: 16px; }
.voops-gap-section__head { align-items: flex-start; display: flex; gap: 20px; justify-content: space-between; margin-bottom: 16px; }
.voops-gap-section__head h2 { font-size: 18px; margin: 0 0 5px; }
.voops-gap-section__head p { color: var(--voops-muted); margin: 0; }
.voops-gap-comparison-table,
.voops-gap-product-table,
.voops-gap-detail-table { table-layout: fixed; width: 100%; }
.voops-gap-product-table { min-width: 620px; }
.voops-gap-detail-table { min-width: 1120px; }
.voops-gap-detail-table td { vertical-align: top; }
.voops-gap-state-cell { display: grid; gap: 6px; min-width: 0; }
.voops-gap-row-actions { align-items: stretch; display: flex; flex-direction: column; gap: 8px; }
.voops-gap-row-actions .voops-btn { white-space: nowrap; width: 100%; }
.voops-gap-row-actions .voops-btn--icon { align-self: flex-start; width: 36px; }
.voops-gap-col--customer { width: 14%; }
.voops-gap-col--product { width: 16%; }
.voops-gap-col--policy { width: 22%; }
.voops-gap-col--priority { width: 10%; }
.voops-gap-col--state { width: 18%; }
.voops-gap-col--expected { width: 24%; }
.voops-gap-col--actions { width: 184px; }
.voops-gap-history-table { min-width: 680px; }
.voops-ticket__creation { color: var(--voops-muted); }
.voops-ticket__creation--auto { color: var(--voops-accent); }
.voops-gap-state--compliant { color: var(--voops-success); }
.voops-gap-state--gap { color: var(--voops-danger); }
.voops-gap-state--manual_review { color: var(--voops-warning); }
/* GAP-01: an accepted risk is still not compliant, and reads apart from an open gap. */
.voops-gap-state--accepted_risk { color: var(--voops-series-3); }
.voops-gap-state--not_observed,
.voops-gap-state--not_applicable,
.voops-gap-state--retired { color: var(--voops-muted); }
.voops-gap-product-status { white-space: normal; }
.voops-gap-recurring { display: grid; gap: 1px; overflow: hidden; border: 1px solid var(--voops-border); border-radius: var(--voops-radius-sm); background: var(--voops-border); }
.voops-gap-recurring > div { align-items: center; background: var(--voops-surface); display: flex; gap: 20px; justify-content: space-between; padding: 13px 16px; }
.voops-gap-recurring span { color: var(--voops-muted); white-space: nowrap; }
@media (max-width: 1180px) {
  .voops-gap-filter { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 760px) {
  .voops-brand-settings, .voops-brand-settings__controls { align-items: stretch; flex-direction: column; }
  .voops-brand-settings__controls form { grid-template-columns: 1fr; }
  .voops-partner-regions, .voops-partner-regions form { grid-template-columns: 1fr; }
  .voops-settings-row { align-items: stretch; grid-template-columns: 1fr; }
  .voops-settings-row__controls { align-items: stretch; flex-direction: column; }
  .voops-settings-row__controls > .voops-multiselect { flex-basis: auto; width: 100%; }
  .voops-settings-row__controls > form { flex-basis: auto; grid-template-columns: 1fr; }
  .voops-instance-add { grid-template-columns: 1fr; }
  .voops-policy-summary { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .voops-policy-product > header { align-items: flex-start; flex-direction: column; }
  .voops-quick-filter__menu { inset-inline-end: 0; inset-inline-start: auto; }
  .voops-gap-filter { grid-template-columns: 1fr; }
  .voops-gap-section__head { flex-direction: column; }
}

/* Decorative section marker. Never the only carrier of meaning: uppercase is a
   no-op in Japanese and Chinese, and the tracking harms Arabic. */
.voops-eyebrow {
  font-size: 11px; font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase; color: var(--voops-faint);
}
/* Any figure a reader scans. Tabular numerals stop a column of counts shifting
   when 9 becomes 10. */
/* Figures set size and weight only. The numeral FACE is not chosen here — the
   digit-scoped @font-face at the top of this file applies it to every 0-9 in the
   product, so a figure never has to opt in and a table cell is never left out.
   tabular-nums still matters: it keeps the separators Inter renders aligned. */
.voops-figure, .voops-kpi__value {
  font-weight: 500;
  letter-spacing: -.01em;
  font-variant-numeric: tabular-nums;
}
.voops-stat__value, .voops-num { font-variant-numeric: tabular-nums; }

/* ═══ Dashboard primitives (phase 1) ═══════════════════════════════════════ */

/* ── KPI tile: an eyebrow caption, one figure, one supporting line. ── */
.voops-kpi {
  position: relative; display: flex; flex-direction: column; gap: 4px;
  padding: 14px 16px; background: var(--voops-card-bg);
  border: 1px solid var(--voops-border); border-radius: var(--voops-radius-lg);
  box-shadow: var(--voops-card-shadow); color: inherit; text-decoration: none;
}
a.voops-kpi:hover { border-color: var(--voops-border-2); }
.voops-kpi {
  /* A flex item's automatic minimum is its content, so a long value widened the
     tile from the inside and pushed it past its grid track. */
  min-width: 0;
}
/* Sized for a figure. Gap Analysis puts a full timestamp in one — "Last
   assessment" — which at 28px is far wider than the tile, so it broke out of it.
   The value wraps at a boundary and steps down a little where it has to, rather
   than overflowing. */
.voops-kpi__value {
  font-size: clamp(20px, 2.2vw, 28px); font-weight: 700; letter-spacing: -.02em;
  line-height: 1.15; font-variant-numeric: tabular-nums;
  min-width: 0; overflow-wrap: break-word;
}
.voops-kpi__value--alert { color: var(--voops-error); }
/* One line, truncated. DESIGN.md states the supporting line "truncates rather
   than wraps, so a long string cannot change a tile's height and break the row
   it sits in" — and a two-line clamp does change the height, by exactly one
   line, which is the thing the rule exists to prevent. */
.voops-kpi__sub {
  font-size: 11.5px; color: var(--voops-muted); line-height: 1.35;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ── Donut. Proportions come from stroke-dasharray, computed by the handler
      from real counts, so the template performs no arithmetic and cannot
      invent a proportion. Scales identically at 2 instances or 240. ── */
.voops-donut { position: relative; width: 132px; height: 132px; flex: none; }
/* Stroke width is in viewBox units now (42 wide), not pixels. */
.voops-donut__track { fill: none; stroke: var(--voops-surface-2); stroke-width: 5; }
.voops-donut__arc { fill: none; stroke-width: 5; transform: rotate(-90deg); transform-origin: 50% 50%; }
.voops-donut__arc.is-series-1 { stroke: var(--voops-series-1); }
.voops-donut__arc.is-series-2 { stroke: var(--voops-series-2); }
.voops-donut__arc.is-series-3 { stroke: var(--voops-series-3); }
.voops-donut__arc.is-series-4 { stroke: var(--voops-series-4); }
.voops-donut__arc.is-series-5 { stroke: var(--voops-series-5); }
.voops-donut__arc.is-series-6 { stroke: var(--voops-border-2); }
.voops-donut__arc.is-healthy    { stroke: var(--voops-success); }
.voops-donut__arc.is-attention  { stroke: var(--voops-warning); }
.voops-donut__arc.is-unverified { stroke: var(--voops-border-2); }
.voops-donut__arc.is-bad        { stroke: var(--voops-error); }
.voops-donut__arc.is-disabled   { stroke: var(--voops-faint); }
.voops-donut__mid {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center;
}
/* The label must stay inside the ring's hole, not spill across the arc.
   The hole is the ring's inner diameter: r 15.9155 less half of the 5-unit
   stroke, doubled, scaled from the 42-unit viewBox to the rendered 132px —
   about 84px.

   Size and tracking come down with it, because a label that fits only by
   breaking mid-word ("CONNECTIO / NS") is no more readable than one that
   overflowed. Wrapping is therefore at word boundaries only; a label too long
   for the hole in one line takes two, and a single word too long for the hole
   is a label the caller must shorten. */
.voops-donut__mid .voops-eyebrow {
  max-width: 84px; text-align: center; line-height: 1.3;
  font-size: 9px; letter-spacing: .04em;
  overflow-wrap: normal; word-break: normal; hyphens: none;
}

/* ── Chart row: label, stacked track, total. ── */
.voops-chartrow {
  display: grid; grid-template-columns: 150px 1fr 44px; align-items: center; gap: 12px;
}
.voops-chartrow__label {
  font-size: 12.5px; color: var(--voops-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.voops-chartrow__track {
  display: block; width: 100%; height: 20px; border-radius: 6px;
  background: var(--voops-surface-2); overflow: hidden;
}
.voops-chartrow__total {
  font-size: 13px; font-weight: 650; text-align: end; font-variant-numeric: tabular-nums;
}

/* Deliberate exception to the digit face: technical strings — audit targets,
   ticket references, DKIM and DNS records, invite links, recovery keys — set an
   explicit monospace family, so their digits come from that face rather than
   Geist Mono. That is intended. An identifier is read as one opaque token, and a
   token drawn from two faces is harder to compare character by character than one
   drawn from a single face. See `.voops-meta dd`, `.voops-badge--action`,
   `.voops-tickets__ref`, `.voops-audit__target` and the `code` rules. */

/* Categorical series for stacked breakdowns. These colour SVG rects, so they set
   `fill`, not `background`: a segment's width is a geometry attribute rather than
   an inline style, which is what keeps the row inside the content security policy.
   Five is the cap — the fifth is an aggregated remainder, so a legend cannot grow
   without bound. */
.voops-series-1 { fill: var(--voops-series-1); }
.voops-series-2 { fill: var(--voops-series-2); }
.voops-series-3 { fill: var(--voops-series-3); }
.voops-series-4 { fill: var(--voops-series-4); }
.voops-series-5 { fill: var(--voops-series-5); }

/* ── Masonry field: row spans, not column packing, so reading order stays
      left-to-right. The server tags each tile from what it is rendering. ── */
.voops-masonry {
  display: grid; gap: 0 14px;
  grid-template-columns: repeat(auto-fit, minmax(272px, 1fr)); grid-auto-rows: 8px;
}
.voops-masonry > * { margin-bottom: 14px; }
.voops-masonry__item--sm { grid-row: span 19; }
.voops-masonry__item--md { grid-row: span 24; }
.voops-masonry__item--lg { grid-row: span 30; }
@media (max-width: 720px) { .voops-masonry { grid-template-columns: 1fr; } }

/* ═══ Platform dashboard (phase 4) ═════════════════════════════════════════ */

.voops-kpis { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 12px; margin-bottom: 16px; }

/* The strip is sized to its own tile count rather than to one house number:
   seven on the platform dashboard and on gap analysis, five on the partner
   portal — four when the viewer is not a partner admin and the credits tile is
   not rendered, which is why that case has its own modifier rather than an
   empty trailing column. `auto-fit` is deliberately not used: the tile count is
   known at author time, and letting it reflow mid-row makes two dashboards line
   up differently at the same width. */
.voops-kpis--gaps { grid-template-columns: repeat(7, minmax(0, 1fr)); }
.voops-kpis--partner { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.voops-kpis--partner-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* Operational problems carry the strongest weight on the page, and sit directly
   below the KPI strip in BOTH modes — rendered once, above either panel. */
.voops-attention {
  border-color: var(--voops-error-line); margin-bottom: 16px;
  background: linear-gradient(180deg, var(--voops-attention-bg), var(--voops-surface));
}
.voops-attention::before {
  background: linear-gradient(90deg, transparent, var(--voops-error-line) 22%,
                              var(--voops-error-line) 78%, transparent);
}
/* Nothing is hit: drop the alarm entirely. A red border over four zeros reads
   as a fault the page cannot point at. */
.voops-attention.is-clear {
  border-color: var(--voops-border);
  background: var(--voops-card-bg);
}
.voops-attention.is-clear::before { background: none; }

.voops-attention__grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
.voops-attention__item {
  display: flex; flex-direction: column; gap: 5px; padding: 13px 15px;
  border: 1px solid var(--voops-border); border-radius: var(--voops-radius-md, 14px);
  background: var(--voops-shadow-soft); color: inherit; text-decoration: none;
}
a.voops-attention__item:hover { border-color: var(--voops-border-2); }
.voops-attention__item.is-hit { border-color: var(--voops-error-line); }
.voops-attention__item.is-hit .voops-kpi__value { color: var(--voops-error); }
.voops-attention__label { font-size: 12px; color: var(--voops-muted); }

.voops-bento { display: grid; grid-template-columns: repeat(12, 1fr); gap: 16px; }
.voops-bento__5 { grid-column: span 5; }
.voops-bento__7 { grid-column: span 7; }
.voops-bento__12 { grid-column: span 12; }

.voops-rows { display: flex; flex-direction: column; }
.voops-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 9px 0; border-bottom: 1px solid var(--voops-border); font-size: 13.5px;
}
.voops-row:last-child { border-bottom: 0; }
.voops-row span { color: var(--voops-muted); min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.voops-row strong { font-weight: 650; flex: none; font-variant-numeric: tabular-nums; }

.voops-chart { display: flex; flex-direction: column; gap: 12px; }
.voops-chartrows { display: grid; gap: 10px; margin-bottom: 14px; }
.voops-chart__key { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 14px;
  font-size: 12px; color: var(--voops-muted); }
.voops-chart__key span { display: inline-flex; align-items: center; gap: 6px; }
.voops-key { width: 10px; height: 10px; border-radius: 3px; flex: none; }
/* The series classes colour SVG rects via `fill`; a legend swatch is a div, so
   it needs the same colours as a background. Kept adjacent so they cannot drift. */
.voops-key.voops-series-1 { background: var(--voops-series-1); }
.voops-key.voops-series-2 { background: var(--voops-series-2); }
.voops-key.voops-series-3 { background: var(--voops-series-3); }
.voops-key.voops-series-4 { background: var(--voops-series-4); }
.voops-key.voops-series-5 { background: var(--voops-series-5); }

.voops-activity { display: flex; flex-direction: column; }
.voops-activity__row {
  display: flex; gap: 12px; align-items: baseline; padding: 10px 0;
  border-bottom: 1px solid var(--voops-border); font-size: 13px;
}
.voops-activity__row:last-child { border-bottom: 0; }
.voops-activity__row time { flex: none; width: 150px; color: var(--voops-faint); font-size: 12px; }
.voops-activity__action { flex: 1 1 auto; min-width: 0; font-weight: 600; }
.voops-activity__actor { color: var(--voops-muted); flex: none; }

.voops-audience { display: flex; justify-content: flex-end; margin-bottom: 16px; }
.voops-actions-row { display: flex; flex-wrap: wrap; gap: 10px; }

/* The briefing. A fixed narrative rail beside its evidence, sticky while the
   evidence scrolls; the alternative — alternating sides — goes ragged as soon as
   the two columns differ in height, and has nowhere to put a second widget. */
.voops-beats { display: flex; flex-direction: column; gap: 26px; margin-bottom: 22px; }
.voops-beat { display: grid; grid-template-columns: 340px 1fr; gap: 30px; align-items: start; }
.voops-narrate { position: sticky; top: 18px; }
.voops-narrate h3 {
  margin: 0 0 10px; font-size: 11px; font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase; color: var(--voops-faint);
}
.voops-narrate p { margin: 0; font-size: 14.5px; line-height: 1.75;
  color: var(--voops-muted); max-width: 56ch; }
.voops-beat__evidence {
  padding: 18px 20px; border: 1px solid var(--voops-border);
  border-radius: var(--voops-radius-lg); background: var(--voops-card-bg);
  box-shadow: var(--voops-card-shadow);
}

@media (max-width: 1180px) {
  .voops-kpis { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .voops-kpis--gaps, .voops-kpis--partner, .voops-kpis--partner-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .voops-bento__5, .voops-bento__7 { grid-column: span 12; }
}
@media (max-width: 720px) {
  .voops-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .voops-kpis--gaps, .voops-kpis--partner, .voops-kpis--partner-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .voops-attention__grid { grid-template-columns: 1fr 1fr; }
  .voops-beat { grid-template-columns: 1fr; gap: 14px; }
  .voops-narrate { position: static; }
  .voops-activity__row { flex-wrap: wrap; }
  .voops-activity__row time { width: 100%; }
}

/* Card heading block. This existed only in the mockups: the templates used
   `voops-card__head` from the start, so every card title was falling back to the
   browser's default h2 — roughly 24px with no layout — instead of the 15px the
   design specifies. */
.voops-card__head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 12px; margin-bottom: 16px;
}
.voops-card__head h2 { margin: 0; font-size: 15px; font-weight: 650; letter-spacing: -.01em; }
.voops-card__head p { margin: 3px 0 0; font-size: 12px; color: var(--voops-faint); }

/* The opening summary of a conversational view. Its title is a tracked label
   rather than a heading — the paragraph is the content, and a second large
   heading directly under the page title just competes with it. */
/* Gradient edge as a utility. Same two-layer technique as the summary card:
   the fill is clipped to the padding box and the gradient to the border box, so
   a 1px border becomes the gradient with no ring pseudo-element and no size
   change. Used by the cards that ask for attention on an otherwise flat page. */
.voops-card--edge {
  border: 1px solid transparent;
  background:
    var(--voops-card-bg) padding-box,
    var(--voops-warm-grad) border-box;
}
.voops-card--edge::before { display: none; }

.voops-summary {
  margin-bottom: 22px;
  /* Gradient edge, same technique as the quick-actions pill: the fill is clipped
     to the padding box and the gradient to the border box, so the 1px border
     becomes the gradient without a ring pseudo-element or a size change. */
  border: 1px solid transparent;
  background:
    var(--voops-card-bg) padding-box,
    var(--voops-warm-grad) border-box;
}
/* The top highlight would sit on the gradient edge and mute it. */
.voops-summary::before { display: none; }
.voops-summary .voops-card__head { margin-bottom: 12px; }
.voops-summary__title {
  font-size: 11px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: var(--voops-faint); margin: 0;
}
.voops-summary__sub { margin: 4px 0 0; font-size: 12px; color: var(--voops-faint); }
/* Full measure: the summary is one paragraph across the card, not a column. */
.voops-summary__lede { margin: 0; font-size: 16.5px; line-height: 1.65; color: var(--voops-text); }
.voops-summary__lede b { font-weight: 650; }
.voops-summary__filter { margin: 10px 0 0; font-size: 13px; color: var(--voops-muted); }

/* Generated briefing sections: prose in one column, at the same measure as the
   deterministic beats so the two read as the same page. */
.voops-brief-sections { display: flex; flex-direction: column; gap: 14px; }
.voops-brief-section h3 {
  margin: 0 0 8px; font-size: 11px; font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase; color: var(--voops-faint);
}
.voops-brief-section p { margin: 0; font-size: 14.5px; line-height: 1.75; color: var(--voops-muted); }

/* ── Explained figures (dashboard/report evidence parity, 2026-10-02) ─────────
   One card per figure: name, value and evidence state on one line, then what it
   counts, its limits, its scope and time, and the member groups behind it. Text
   wraps rather than truncating: an explanation cut short is a different claim. */
.voops-metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: 14px; margin: 0 0 24px; }
.voops-metric { display: flex; flex-direction: column; gap: 8px; min-width: 0; padding: 16px 18px;
  background: var(--voops-surface); border: 1px solid var(--voops-border); border-radius: var(--voops-radius); }
.voops-metric__head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px 10px; }
.voops-metric__label { margin: 0; font-size: 13px; font-weight: 600; color: var(--voops-text);
  overflow-wrap: anywhere; flex: 1 1 160px; min-width: 0; }
.voops-metric__value { font-size: 22px; font-weight: 700; line-height: 1.1; color: var(--voops-text);
  font-variant-numeric: tabular-nums; }
.voops-metric__state { font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 999px;
  border: 1px solid var(--voops-border-2); color: var(--voops-muted); background: var(--voops-tint); }
.voops-metric__state--complete { color: var(--voops-success); background: var(--voops-success-soft); border-color: var(--voops-success-line); }
.voops-metric__state--partial { color: var(--voops-warning); background: var(--voops-warning-soft); border-color: var(--voops-warning-line); }
.voops-metric__state--unavailable { color: var(--voops-danger); background: var(--voops-error-soft); border-color: var(--voops-error-line); }
.voops-metric__explain, .voops-metric__note, .voops-metric__meta { margin: 0; font-size: 12.5px;
  line-height: 1.5; overflow-wrap: anywhere; }
.voops-metric__explain { color: var(--voops-text); }
.voops-metric__note { color: var(--voops-warning); }
.voops-metric__meta { color: var(--voops-faint); }
.voops-metric__selections { list-style: none; margin: 4px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.voops-metric__selection { display: inline-flex; align-items: center; gap: 6px; min-width: 0; max-width: 100%;
  font-size: 12.5px; color: var(--voops-muted); border: 1px solid var(--voops-border-2);
  border-radius: 999px; padding: 3px 4px 3px 12px; }
.voops-metric__selection > a, .voops-metric__selection > span { color: inherit; text-decoration: none;
  overflow-wrap: anywhere; min-width: 0; }
.voops-metric__selection > span { padding-right: 8px; }
.voops-metric__selection > a:hover { color: var(--voops-accent); }
.voops-metric__selection strong { color: var(--voops-text); font-variant-numeric: tabular-nums; }
.voops-metric__export { font-size: 11px; font-weight: 600; color: var(--voops-muted); text-decoration: none;
  border-left: 1px solid var(--voops-border-2); padding: 0 8px; white-space: nowrap; }
.voops-metric__export:hover { color: var(--voops-accent); }
/* One figure's members, listed in full above both dashboard modes. */
.voops-dashboard-selection { margin-bottom: 18px; }
.voops-dashboard-selection .voops-card__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
