/* ═══════════════════════════════════════════════════════════════════════════
   nx-ui.css — NEXUS shared UI shell (Blueprint, Autopilot, Launchpad, Backseat, Handshake, Wingman, Workbench, Homebase, Deepdive, Settings, Calendar, contact drawer + Portal sheet, leader views incl. Pipeline + MCR, Admin, Booking page builder converted)

   One stylesheet defines what a NEXUS module header, tab, rail, body, button,
   chip, segmented control and toggle look like, in both themes. Later batches
   move each module onto these classes and delete their local styles.

   Rules of the road
   - Pure CSS. No JS. Every class is prefixed nx-.
   - Tokens live on :root (dark) and body.light-mode (light): the app's one
     light-mode hook (index.html + nx-icons.js both key off body.light-mode).
   - Reuses the app's own text / muted / panel variables by their current names:
       --text   body text         --text2  muted text        --card   panel fill
       --font-body  Plus Jakarta Sans
     and the per-module accents --nx-<module> that nx-icons.js injects for both
     themes (autopilot, blueprint, handshake, workbench, homebase, deepdive,
     backseat, launchpad, wingman).
   - Module color appears ONLY on the header icon, title and the active tab
     underline (via --nx-module). Never on a button, chip, toggle or segment.
   - No class hard-codes a color that does not switch with the theme; anything
     theme-dependent goes through a token below.
   - Bump ?v= in index.html on every edit.

   Batch 9 (Settings) additions, all token-driven, dark + light:
     .nx-rail__group     caps label row inside a rail (ACCOUNT / WORKSPACE / SYSTEM): 11/700 on --nx-text-dim,
                         a --nx-hairline rule above every group but the first
     .nx-rail__item      36px nav row, 14/600 in --text, radius 10; .is-active = 18% teal fill + 50% teal border
                         (the .nx-chip active recipe); .nx-rail__glyph = a 16px glyph before the label
     .nx-rail__count     count pill at the row's right end, hidden until .is-visible
     .nx-rail__foot      bottom-pinned block of a .nx-rail--stack rail: spacer, 1px line, rows
     .nx-center--narrow  the 900px card stack (948 with its gutters)
     .nx-card__sub       12px muted subtitle under .nx-card__title (title is a flex row now)
     .nx-card__rows      stacked rows with 1px inner dividers: .nx-card__row + __row-text / __row-label /
                         __row-desc / __row-ctl
     .nx-form            220px label / field grid (.nx-form__label, .nx-form__hint, .nx-form__full)
     .nx-card__foot      right-aligned footer: --ghost then ONE --primary
     .nx-tiles / .nx-tile  3-column tile grid: bare 26px icon + 15/700 title + 13px muted text
     .nx-banner          one tinted banner card (icon, title, sub, one action)
     .nx-btn__dot        an 8px status dot inside .nx-btn__icon (its color is painted by the module)
     .nx-sr-only         visually hidden text

   Batch 15a (button sweep: orphans, raw controls) additions, all token-driven, dark + light:
     .nx-check           the one checkbox: a real <input type="checkbox" class="nx-check"> drawn by CSS (appearance
                         none), 18px, radius 5, field fill + field line; checked = action teal + a white check;
                         hover = teal line; focus-visible ring; disabled .4. .nx-checklist__row boxes use the same rules.
     .nx-check--radio    the same box as a radio: <input type="radio" class="nx-check nx-check--radio"> (round, teal
                         ring + dot)
     .nx-check-label     an inline row for one .nx-check and its text:
                         <label class="nx-check-label"><input type="checkbox" class="nx-check"> Text</label>
                         (13px --text, 8px gap); a disabled box dims the whole row once (.45)
     .nx-btn.is-editing  a button whose form holds an edit in progress (Handshake "Save Edit"): amber hold tint
     .nx-label--section  the section-heading label (--nx-text-dim, wide tracking): <div class="nx-label nx-label--section">.
                         .nx-section-label is an alias of it until later batches swap its call sites

   Batch 15b (button sweep: Org / Settings / Admin leftovers) additions, all token-driven, dark + light:
     input.nx-field      a bare <input class="nx-field"> takes the box itself (like select.nx-field): focus line,
                         theme color-scheme for number / month pickers
     .nx-field--auto     a bare field sized by its content / min-width instead of the row (width auto)
     .nx-toggle.on       legacy state alias of .is-on (class-form toggles whose JS toggles `on`)
     .nx-seg__item.on    legacy state alias of .is-active (segments whose JS toggles `on`)
     .nx-choice          a pick-one card: <label class="nx-choice"><input type="radio" …><span class="nx-choice__title">
                         Title</span><span class="nx-choice__desc">One line</span></label>; the radio is visually
                         hidden, the checked card is tinted like an active chip (never solid), focus ring on keyboard
     .nx-sortable        opt-in root for the .nx-table sort indicator on a plain <table>: th.is-sorted (+ .is-desc)
     .nx-tag--tint       the action-tinted small tag (Locked, a gate)

   Batch 15b-2 (button sweep: Settings pill follow-up) additions, all token-driven, dark + light:
     .nx-tag--ok / --warn / --danger
                         tone modifiers for .nx-tag (the .nx-status tones on a static tag): fill, line and text from
                         --nx-up / --nx-hold / --nx-urgent (+ -fill / -line). People Active / Not activated / Suspended,
                         2FA Active / Not Set Up, Integrations Connected / Active / Paused ride them; role, MCR state
                         code, Campaigns visibility and "Not set up" stay neutral

   Batch 15d-1 (button sweep: Handshake / Homebase / Launchpad / Deepdive leftovers) additions, dark + light:
     --nx-active-fill / --nx-active-line
                         the "tinted = selected" recipe as tokens (18% teal fill, 60% teal line): .nx-chip.is-active rides
                         them, and so does any local selected-row rule (the campaign dropdown's .selected), so a later
                         company-accent tint moves every selected state together
     .nx-field:has(:disabled)
                         a field whose control is disabled dims as one (opacity .4, like every disabled control); a bare
                         select.nx-field / input.nx-field does the same on :disabled. The chevron never takes the click.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Tokens ─────────────────────────────────────────────────────────────── */
:root {
  --nx-action: #0F766E;                 /* primary teal, same in both themes */
  --nx-action-hover: #13877E;
  --nx-action-press: #0A5A53;
  --nx-focus: #2DD4BF;

  --nx-line: rgba(255,255,255,.08);
  --nx-line-strong: rgba(255,255,255,.14);
  --nx-hover-fill: rgba(255,255,255,.06);
  --nx-press-fill: rgba(255,255,255,.10);
  --nx-row-alt: rgba(255,255,255,.025);      /* .nx-table: even-row tint */
  --nx-row-hover: rgba(255,255,255,.05);     /* .nx-table: hovered row */

  --nx-text-link: #2DD4BF;
  --nx-text-dim: rgba(232,232,240,.55);     /* one step dimmer than --text2: rail group labels */
  --nx-hairline: rgba(255,255,255,.06);     /* the rule above a rail group */
  --nx-danger: #EF4444;
  --nx-danger-text: #F87171;

  --nx-chip-active-text: #5EEAD4;       /* tinted = selected (solid teal is the primary button only) */
  --nx-active-fill: rgba(15,118,110,.18); /* the tinted-selected ground (.nx-chip.is-active, a selected menu row) */
  --nx-active-line: rgba(20,184,166,.6);  /* its line */
  --nx-secondary-fill: transparent;     /* secondary button ground: transparent on dark, panel on light */
  --nx-field-fill: var(--card);         /* text field ground (.nx-search); light mode matches index.html's input rule */
  --nx-field-line: var(--nx-line-strong);

  /* Fixed back button zone: .back-btn is 40px wide at right:20px (index.html).
     Headers pad right by 20 + 40 + 20 so no module hand-clears it again. */
  --nx-backbtn-zone: 80px;
}

body.light-mode {
  --nx-action-hover: #0B5D57;

  --nx-line: rgba(0,0,0,.08);
  --nx-line-strong: rgba(0,0,0,.16);
  --nx-hover-fill: rgba(0,0,0,.05);
  --nx-press-fill: rgba(0,0,0,.08);
  --nx-row-alt: rgba(0,0,0,.025);
  --nx-row-hover: rgba(0,0,0,.05);

  --nx-text-link: #0F766E;
  --nx-text-dim: rgba(26,26,46,.55);
  --nx-hairline: rgba(0,0,0,.06);
  --nx-danger-text: #B91C1C;

  --nx-chip-active-text: #0B5D57;       /* 4.5:1+ over the tinted fill on the light ground */
  --nx-secondary-fill: var(--card);
  --nx-field-fill: #f5f6f8;             /* = body.light-mode input[type=text] in index.html, so the inner input is seamless */
  --nx-field-line: #d1d5db;
}

/* index.html carries `body.light-mode button { color: inherit }` (0,1,1), which would
   beat every single-class color below. These element-qualified rules keep the shell's
   control colors authoritative in light mode; they repeat the values, not new ones. */
body.light-mode button.nx-btn { color: var(--text); }
body.light-mode button.nx-btn--primary { color: #fff; }
body.light-mode button.nx-btn--ghost { color: var(--text2); }
body.light-mode button.nx-btn--ghost:hover,
body.light-mode button.nx-btn--ghost:active { color: var(--text); }
body.light-mode button.nx-btn--text { color: var(--nx-text-link); }
body.light-mode button.nx-btn--danger { color: var(--nx-danger-text); }
body.light-mode button.nx-btn--danger:hover,
body.light-mode button.nx-btn--danger:active { color: #fff; }
body.light-mode button.nx-chip { color: var(--text2); }
body.light-mode button.nx-chip:hover { color: var(--text); }
body.light-mode button.nx-chip.is-active { color: var(--nx-chip-active-text); }
body.light-mode button.nx-seg__item { color: var(--text2); }
body.light-mode button.nx-seg__item:hover { color: var(--text); }
body.light-mode button.nx-seg__item.is-active,
body.light-mode button.nx-seg__item.on,
body.light-mode button.nx-seg__item[aria-checked="true"] { color: #fff; }
body.light-mode button.nx-btn--secondary[aria-pressed="true"] { color: var(--nx-chip-active-text); }
body.light-mode button.nx-tab { color: var(--text2); }
body.light-mode button.nx-tab:hover,
body.light-mode button.nx-tab.is-active { color: var(--text); }
body.light-mode button.nx-header__help { color: var(--muted); }
body.light-mode button.nx-header__help:hover { color: var(--text2); }
body.light-mode button.nx-rail__item,
body.light-mode a.nx-rail__item { color: var(--text); }
body.light-mode button.nx-rail__item.is-active,
body.light-mode a.nx-rail__item.is-active { color: var(--nx-chip-active-text); }
body.light-mode button.nx-tile { color: var(--text); }

/* --nx-module per module section: the accent the header icon, title and active
   tab underline use. Values come from nx-icons.js (--nx-<module>), so they
   follow the theme automatically. Custom-property only: no visual effect until
   a section is moved onto the nx- classes. Settings has no module accent and
   falls back to body text. */
#autopilot-section { --nx-module: var(--nx-autopilot); }
#blueprint-section { --nx-module: var(--nx-blueprint); }
#handshake-section { --nx-module: var(--nx-handshake); }
#workbench-section { --nx-module: var(--nx-workbench); }
#homebase-section  { --nx-module: var(--nx-homebase); }
#deepdive-section  { --nx-module: var(--nx-deepdive); }
#backseat-section  { --nx-module: var(--nx-backseat); }
#launchpad-section { --nx-module: var(--nx-launchpad); }
#wingman-section   { --nx-module: var(--nx-wingman); }

/* ── Header (variant B: tabs inline) ───────────────────────────────────── */
.nx-header {
  box-sizing: border-box;
  display: flex;
  align-items: stretch;
  height: 72px;                         /* border included: content box is 71px */
  flex-shrink: 0;
  gap: 12px;
  padding: 0 var(--nx-backbtn-zone) 0 24px;
  border-bottom: 1px solid var(--nx-line);
  background: transparent;              /* page ground shows through */
  font-family: var(--font-body);
  color: var(--text);
}
.nx-header__brand {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}
.nx-header__icon {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.nx-header__icon > svg { width: 32px; height: 32px; display: block; }  /* NxIcons art, full color */
.nx-header__text { display: flex; flex-direction: column; justify-content: center; min-width: 0; }
.nx-header__title {
  margin: 0;
  font-size: 24px;
  font-weight: 800;
  letter-spacing: -0.01em;
  line-height: 1;
  color: var(--nx-module, var(--text));
  white-space: nowrap;
}
.nx-header__subtitle {
  margin: 3px 0 0;
  font-size: 12px;
  font-weight: 500;
  line-height: 1.2;
  color: var(--text2);
  white-space: nowrap;
}
/* .section-help look, re-homed */
.nx-header__help {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 1.5px solid var(--muted);
  background: transparent;
  padding: 0;
  color: var(--muted);
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
  cursor: help;
  transition: border-color 120ms ease, color 120ms ease;
}
.nx-header__help:hover { border-color: var(--text2); color: var(--text2); }
.nx-header__help:focus-visible { outline: 2px solid var(--nx-focus); outline-offset: 2px; }

.nx-header__divider {
  width: 1px;
  flex-shrink: 0;
  margin: 22px 20px;
  background: var(--nx-line-strong);
}

.nx-header__tabs {
  display: flex;
  align-items: stretch;
  gap: 28px;
  min-width: 0;
}
.nx-tab {
  display: inline-flex;
  align-items: center;
  box-sizing: border-box;
  margin: 0 0 -1px;                     /* the 2px underline sits ON the bar's 1px line */
  padding: 0;
  border: 0;
  border-bottom: 2px solid transparent;
  background: none;
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  color: var(--text2);
  white-space: nowrap;
  cursor: pointer;
  text-decoration: none;
  transition: color 120ms ease, border-color 120ms ease;
}
.nx-tab:hover { color: var(--text); }
.nx-tab:focus-visible { outline: 2px solid var(--nx-focus); outline-offset: -2px; }
.nx-tab.is-active { color: var(--text); border-bottom-color: var(--nx-module, var(--text)); }
/* Count bubble on a tab (entries the view holds, e.g. Radar's watching count): hidden until .is-visible.
   Module JS sets the text and toggles the class; no inline display. */
.nx-tab__count {
  box-sizing: border-box;
  display: none;
  align-items: center;
  justify-content: center;
  height: 18px;
  min-width: 18px;
  margin-left: 8px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--nx-press-fill);
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  color: var(--text2);
}
.nx-tab__count.is-visible { display: inline-flex; }
.nx-tab.is-active .nx-tab__count { color: var(--text); }

.nx-header__spacer { flex: 1 1 auto; }

.nx-header__actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

/* ── Body templates ────────────────────────────────────────────────────────
   The overlay never scrolls; exactly one element per template scrolls.
   Gutters are 24 everywhere. */
.nx-body {
  display: flex;
  flex: 1 1 auto;
  min-height: 0;
  min-width: 0;
  font-family: var(--font-body);
  color: var(--text);
}

/* Rail + canvas: the rail and the canvas each scroll on their own.
   Widths are viewport-proportional with caps: unchanged at a normal desktop window (the caps),
   but under browser zoom they hold their on-screen size and the canvas absorbs the difference. */
.nx-rail {
  box-sizing: border-box;
  flex-shrink: 0;
  min-height: 0;
  padding: 24px;
  background: var(--card);
  border-right: 1px solid var(--nx-line);
  overflow-y: auto;
  overflow-x: hidden;
}
.nx-rail--nav  { width: clamp(220px, 15vw, 280px); }
.nx-rail--pane { width: clamp(380px, 24vw, 460px); }
.nx-canvas {
  box-sizing: border-box;
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  padding: 24px;
  overflow-y: auto;
}

/* Stacked rail / canvas: the column itself does not scroll; its .nx-scroll child does, so
   whatever sits above or below it stays put (a search box over a list, a compose bar under
   a thread). The rail keeps its 24px gutter; the stacked canvas has none, its children pad. */
.nx-rail--stack,
.nx-canvas--stack { display: flex; flex-direction: column; overflow: hidden; }
.nx-canvas--stack { padding: 0; }
.nx-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; }

/* Rail navigation (Settings): group labels, 36px rows, a count pill, a bottom-pinned block.
   <div class="nx-rail__group">ACCOUNT</div>
   <button class="nx-rail__item is-active">Profile<span class="nx-rail__count is-visible">3</span></button>
   <div class="nx-rail__foot">…rows…</div>  (inside a .nx-rail--stack rail, after its .nx-scroll) */
.nx-rail__group {
  padding: 20px 12px 6px;
  border-top: 1px solid var(--nx-hairline);   /* groups read as blocks: a hairline above every label but the first */
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .12em;
  line-height: 1.2;
  text-transform: uppercase;
  color: var(--nx-text-dim);
  user-select: none;
}
.nx-rail > .nx-rail__group:first-child,
.nx-rail > .nx-scroll > .nx-rail__group:first-child { padding-top: 6px; border-top: 0; }   /* the rail's first label */
.nx-rail__item {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  height: 36px;
  margin: 0 0 2px;
  padding: 0 12px;
  border-radius: 10px;
  border: 1px solid transparent;
  background: transparent;
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  color: var(--text);
  text-align: left;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}
.nx-rail__item:hover { background: var(--nx-hover-fill); }
.nx-rail__item:focus-visible { outline: 2px solid var(--nx-focus); outline-offset: 2px; }
.nx-rail__item.is-active {
  background: rgba(15,118,110,.18);
  border-color: rgba(20,184,166,.5);
  color: var(--nx-chip-active-text);
}
.nx-rail__item.is-active:hover { background: rgba(15,118,110,.26); }
.nx-rail__glyph { display: inline-flex; flex-shrink: 0; line-height: 0; color: currentColor; }
.nx-rail__glyph > svg,
svg.nx-rail__glyph { width: 16px; height: 16px; display: block; flex-shrink: 0; }
.nx-rail__glyph.nx-icon-slot > svg { width: 18px; height: 18px; }   /* NxIcons art keeps its 18px */
.nx-rail__count {
  box-sizing: border-box;
  display: none;
  align-items: center;
  justify-content: center;
  height: 18px;
  min-width: 18px;
  margin-left: auto;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--nx-press-fill);
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  color: var(--text2);
}
.nx-rail__count.is-visible { display: inline-flex; }
.nx-rail__item.is-active .nx-rail__count { background: rgba(20,184,166,.22); color: inherit; }
.nx-rail__foot {
  flex-shrink: 0;
  margin-top: auto;
  padding-top: 12px;
  border-top: 1px solid var(--nx-line);
}
.nx-rail--stack > .nx-scroll + .nx-rail__foot { margin-top: 12px; }

/* Aside: a third column on the right (details, properties). Own scroller, no gutter: its
   sections draw their own edge-to-edge rules. */
.nx-aside {
  box-sizing: border-box;
  width: clamp(280px, 19vw, 360px);
  flex-shrink: 0;
  min-height: 0;
  background: var(--card);
  border-left: 1px solid var(--nx-line);
  overflow-y: auto;
  overflow-x: hidden;
}
/* Centered: the body itself scrolls at full width (scrollbar at the window edge). */
.nx-body--center {
  display: block;
  overflow-y: auto;
}
.nx-center {
  box-sizing: border-box;
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
  padding: 24px;
}
.nx-center--narrow { max-width: 948px; }   /* a 900px card stack between its 24px gutters */

/* Full bleed: the body itself scrolls. */
.nx-body--bleed {
  display: block;
  box-sizing: border-box;
  padding: 24px;
  overflow-y: auto;
}

/* ── Buttons ──────────────────────────────────────────────────────────── */
/* ── Toolbar row ──────────────────────────────────────────────────────────
   One 64px row under the header: search left, filter chips, spacer, a segmented control right.
   .nx-selectbar is the same row in a selection mode (count · chips · actions); a module swaps the two. */
.nx-toolbar,
.nx-selectbar {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: 12px;
  height: 64px;
  flex-shrink: 0;
  padding: 0 24px;
  border-bottom: 1px solid var(--nx-line);
  font-family: var(--font-body);
  color: var(--text);
}
.nx-selectbar { background: var(--nx-hover-fill); }
.nx-selectbar__count { font-size: 14px; font-weight: 700; white-space: nowrap; }
.nx-toolbar__spacer { flex: 1 1 auto; }

/* ── Search field ─────────────────────────────────────────────────────────
   <label class="nx-search"><svg …/><input type="text" …></label>: the glyph left, the input fills. */
.nx-search {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  width: 280px;
  max-width: 100%;
  height: 40px;
  padding: 0 14px;
  border-radius: 999px;
  border: 1px solid var(--nx-field-line);
  background: var(--nx-field-fill);
  color: var(--text2);
  font-family: var(--font-body);
  transition: border-color 120ms ease;
}
.nx-search:focus-within { border-color: var(--nx-focus); }
.nx-search > svg { width: 16px; height: 16px; flex-shrink: 0; color: var(--text2); }
.nx-search > input {
  flex: 1 1 auto;
  min-width: 0;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  outline: none;
  font: inherit;
  font-size: 14px;
  color: var(--text);
}
.nx-search > input::placeholder { color: var(--text2); }

/* ── Popover ──────────────────────────────────────────────────────────────
   A panel anchored under a button (position set by the module from the button's rect: top / right). */
.nx-popover {
  position: fixed;
  z-index: 2000;
  box-sizing: border-box;
  padding: 12px 14px;
  border-radius: 12px;
  border: 1px solid var(--nx-line-strong);
  background: var(--card);
  color: var(--text);
  font-family: var(--font-body);
  box-shadow: 0 12px 32px rgba(0,0,0,.35);
  max-height: 70vh;
  overflow-y: auto;
}
.nx-popover__title { font-size: 13px; font-weight: 700; }
.nx-popover__label { margin: 12px 0 6px; font-size: 10px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase; color: var(--text2); }
.nx-popover__row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 5px 0; font-size: 13px; }

.nx-btn {
  position: relative;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 40px;
  padding: 0 18px;
  border-radius: 999px;
  border: 1px solid transparent;
  background: transparent;
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}
.nx-btn > svg { width: 16px; height: 16px; flex-shrink: 0; color: currentColor; }

.nx-btn--primary { background: var(--nx-action); border-color: var(--nx-action); color: #fff; }
.nx-btn--primary:hover  { background: var(--nx-action-hover); border-color: var(--nx-action-hover); }
.nx-btn--primary:active { background: var(--nx-action-press); border-color: var(--nx-action-press); }

.nx-btn--secondary { background: var(--nx-secondary-fill); border-color: var(--nx-line-strong); color: var(--text); }
.nx-btn--secondary:hover  { background: var(--nx-hover-fill); }
.nx-btn--secondary:active { background: var(--nx-press-fill); }

.nx-btn--ghost { background: transparent; border-color: transparent; color: var(--text2); }
.nx-btn--ghost:hover  { background: var(--nx-hover-fill); color: var(--text); }
.nx-btn--ghost:active { background: var(--nx-press-fill); color: var(--text); }

.nx-btn--text { background: none; border: 0; padding: 0 6px; color: var(--nx-text-link); }
.nx-btn--text:hover { text-decoration: underline; text-underline-offset: 3px; }

.nx-btn--danger { background: transparent; border-color: rgba(239,68,68,.45); color: var(--nx-danger-text); }
.nx-btn--danger:hover,
.nx-btn--danger:active { background: var(--nx-danger); border-color: var(--nx-danger); color: #fff; }

/* Icon-only: perfectly round; must carry aria-label. */
.nx-btn--icon { width: 40px; padding: 0; border-radius: 50%; }
.nx-btn--icon > svg { width: 18px; height: 18px; }
.nx-glyph-x { font-size: 18px; line-height: 1; }   /* a text × inside an icon button */

/* Block: fills its row (list "add" actions). */
.nx-btn--block { display: flex; width: 100%; }

/* Count badge on an icon button (pending drafts, unread): hidden until .is-visible.
   Sits on the button's top-right corner; .nx-btn is the positioning context. */
.nx-btn__badge {
  position: absolute;
  top: -4px;
  right: -4px;
  box-sizing: border-box;
  display: none;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--nx-danger);
  color: #fff;
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  pointer-events: none;
}
.nx-btn__badge.is-visible { display: inline-flex; }

/* Pressed secondary (a stateful button such as a card's Hold): the chip's tinted "selected" look */
.nx-btn--secondary[aria-pressed="true"] {
  background: var(--nx-active-fill);
  border-color: var(--nx-active-line);
  color: var(--nx-chip-active-text);
}
.nx-btn--secondary[aria-pressed="true"]:hover { background: rgba(15,118,110,.26); }

/* Icon art rendered into a slot inside a button: <span class="nx-btn__icon nx-icon-slot" data-nx-icon=…> or
   <span class="nx-btn__icon" data-nx-glyph=…>. NxIcons / nx-glyphs fill the span; it sizes like a direct svg.
   Opt-in by class, so slots already inside buttons elsewhere keep their own geometry. */
.nx-btn > .nx-btn__icon { display: inline-flex; align-items: center; line-height: 0; flex-shrink: 0; }
.nx-btn > .nx-btn__icon > svg { width: 16px; height: 16px; display: block; }
.nx-btn--icon > .nx-btn__icon > svg { width: 18px; height: 18px; }
/* A live status dot inside the icon slot (Settings › Status): the module paints its color. */
.nx-btn__dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; background: var(--text2); }
.nx-sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* Sizes */
.nx-btn--sm { height: 32px; padding: 0 14px; font-size: 13px; }
.nx-btn--sm.nx-btn--icon { width: 32px; padding: 0; }
.nx-btn--sm.nx-btn--text { padding: 0 6px; }
.nx-btn--lg { height: 48px; padding: 0 22px; font-size: 15px; }
.nx-btn--lg.nx-btn--icon { width: 48px; padding: 0; }
.nx-btn--lg.nx-btn--text { padding: 0 6px; }

/* States */
.nx-btn:focus-visible { outline: 2px solid var(--nx-focus); outline-offset: 2px; }
.nx-btn:disabled,
.nx-btn[aria-disabled="true"] { opacity: .4; pointer-events: none; }  /* never a recolor */

.nx-btn.is-loading { pointer-events: none; }
.nx-btn.is-loading::before {
  content: '';
  box-sizing: border-box;
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-right-color: transparent;
  opacity: .9;
  animation: nx-spin 700ms linear infinite;
}
.nx-btn--icon.is-loading > svg { display: none; }   /* the ring takes the glyph's place */
@keyframes nx-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .nx-btn.is-loading::before { animation: none; }   /* static ring still signals "busy" */
}

/* ── Inline text link ───────────────────────────────────────────────── */
.nx-link { color: var(--nx-text-link); text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
.nx-link:hover { text-decoration: none; }
.nx-link:focus-visible { outline: 2px solid var(--nx-focus); outline-offset: 2px; border-radius: 2px; }

/* ── Disclosure ───────────────────────────────────────────────────────────
   A titled row that opens a panel under it (an activity feed under a list).
   <button type="button" class="nx-disclosure" aria-expanded="false" aria-controls="id">
     <span class="nx-disclosure__chevron" data-nx-glyph="chevron-right" data-nx-size="18"></span>Title
   </button>
   <div class="nx-disclosure__panel" id="id">…</div>
   .is-open on both (the module's JS toggles it, with aria-expanded). */
.nx-disclosure {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  margin: 20px 0 0;
  padding: 12px 0;
  border: 0;
  border-top: 1px solid var(--nx-line);
  background: none;
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  color: var(--text);
  text-align: left;
  cursor: pointer;
  user-select: none;
}
.nx-disclosure:focus-visible { outline: 2px solid var(--nx-focus); outline-offset: 2px; border-radius: 4px; }
.nx-disclosure__chevron { display: inline-flex; flex-shrink: 0; line-height: 0; color: var(--text2); transition: transform 120ms ease; }
.nx-disclosure.is-open .nx-disclosure__chevron { transform: rotate(90deg); }
.nx-disclosure__panel { display: none; max-height: 400px; overflow-y: auto; padding-bottom: 20px; }
.nx-disclosure__panel.is-open { display: block; }
body.light-mode button.nx-disclosure { color: var(--text); }
@media (prefers-reduced-motion: reduce) { .nx-disclosure__chevron { transition: none; } }

/* ── Chips ────────────────────────────────────────────────────────────── */
.nx-chips { display: flex; flex-wrap: wrap; gap: 8px; }   /* a chip group */
.nx-chip {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 32px;
  padding: 0 14px;
  border-radius: 999px;
  border: 1px solid var(--nx-line-strong);
  background: transparent;
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
  color: var(--text2);
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}
.nx-chip:hover { background: var(--nx-hover-fill); color: var(--text); }
.nx-chip:focus-visible { outline: 2px solid var(--nx-focus); outline-offset: 2px; }
.nx-chip.is-active {
  background: var(--nx-active-fill);
  border-color: var(--nx-active-line);
  color: var(--nx-chip-active-text);
}
.nx-chip.is-active:hover { background: rgba(15,118,110,.26); }
.nx-chip:disabled,
.nx-chip[aria-disabled="true"],
.nx-chip.is-disabled { opacity: .4; pointer-events: none; }
.nx-chip__count {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 18px;
  min-width: 18px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--nx-press-fill);
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  color: inherit;
}
.nx-chip.is-active .nx-chip__count { background: rgba(20,184,166,.22); }

/* ── Segmented control ────────────────────────────────────────────────── */
.nx-seg {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border-radius: 999px;
  border: 1px solid var(--nx-line);
  background: var(--nx-hover-fill);
}
.nx-seg__item {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 34px;
  padding: 0 18px;
  border-radius: 999px;
  border: 0;
  background: transparent;
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  color: var(--text2);
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  transition: background-color 120ms ease, color 120ms ease;
}
.nx-seg__item:hover { color: var(--text); }
.nx-seg__item:focus-visible { outline: 2px solid var(--nx-focus); outline-offset: 2px; }
.nx-seg__item.is-active,
.nx-seg__item.on,
.nx-seg__item[aria-checked="true"] { background: var(--nx-action); color: #fff; }
.nx-seg__item:disabled,
.nx-seg__item[aria-disabled="true"] { opacity: .4; pointer-events: none; }
/* Dense: inline choices inside a form row or a narrow rail card */
.nx-seg--sm { padding: 2px; }
.nx-seg--sm .nx-seg__item { height: 28px; padding: 0 10px; font-size: 12px; }

/* ── Toggle ───────────────────────────────────────────────────────────────
   Checkbox form:  <label class="nx-toggle"><input type="checkbox"><span class="nx-toggle__track"></span></label>
   Class form:     <button type="button" class="nx-toggle is-on"><span class="nx-toggle__track"></span></button>
   (.is-on is the on state for modules whose JS keeps toggle state as a class) */
.nx-toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  box-sizing: border-box;
  width: 44px;
  height: 24px;
  flex-shrink: 0;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  vertical-align: middle;
}
.nx-toggle > input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}
.nx-toggle__track {
  position: absolute;
  inset: 0;
  box-sizing: border-box;
  border-radius: 999px;
  background: var(--card);
  border: 1px solid var(--nx-line);
  transition: background-color 120ms ease, border-color 120ms ease;
  pointer-events: none;
}
.nx-toggle__track::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--text2);
  transition: transform 120ms ease, background-color 120ms ease;
}
.nx-toggle > input:checked ~ .nx-toggle__track,
.nx-toggle.is-on > .nx-toggle__track,
.nx-toggle.on > .nx-toggle__track { background: var(--nx-action); border-color: var(--nx-action); }
.nx-toggle > input:checked ~ .nx-toggle__track::after,
.nx-toggle.is-on > .nx-toggle__track::after,
.nx-toggle.on > .nx-toggle__track::after { background: #fff; transform: translateX(20px); }
.nx-toggle > input:focus-visible ~ .nx-toggle__track,
.nx-toggle:focus-visible { outline: 2px solid var(--nx-focus); outline-offset: 2px; }
.nx-toggle:focus-visible { border-radius: 999px; }
.nx-toggle > input:disabled { cursor: default; }
.nx-toggle > input:disabled ~ .nx-toggle__track,
.nx-toggle:disabled > .nx-toggle__track,
.nx-toggle[aria-disabled="true"] > .nx-toggle__track { opacity: .4; }
.nx-toggle:disabled,
.nx-toggle[aria-disabled="true"] { cursor: default; pointer-events: none; }

@media (prefers-reduced-motion: reduce) {
  .nx-toggle__track,
  .nx-toggle__track::after { transition: none; }
}

/* ── Data card ────────────────────────────────────────────────────────────
   One read-only panel of partner facts (TELI details, Property Intelligence; any
   future integration renders the same card). The whole head row is the toggle.
   <section class="nx-datacard is-collapsed" id="x">
     <button type="button" class="nx-datacard__head" aria-expanded="false" aria-controls="x-body">
       <span class="nx-datacard__icon">18px mark</span>
       <span class="nx-datacard__titles">
         <span class="nx-datacard__title">Title</span><span class="nx-datacard__source">Source · updated</span>
         <span class="nx-datacard__strip"><span class="nx-datacard__strip-item"><span class="nx-datacard__strip-value">730</span> <span class="nx-datacard__strip-label">credit</span></span>…</span>
       </span>
       <span class="nx-datacard__chevron">chevron-down glyph</span>
     </button>
     <div class="nx-datacard__body" id="x-body">
       <div class="nx-datacard__facts"><div class="nx-datacard__fact">label / value / sub</div>…</div>
       <div class="nx-datacard__groups"><div class="nx-datacard__group"><div class="nx-datacard__group-label">…</div><div class="nx-datacard__cells"><div class="nx-datacard__cell">label value</div>…</div></div>…</div>
     </div>
   </section>
   .is-collapsed hides the body, turns the chevron and shows the facts strip (up to five facts
   inline after the source line); .is-empty (header only) hides the chevron. Fact tiles are fixed:
   a missing value is a muted dash (.is-empty on the value), never a gap. A cell is label then
   value; a long value drops under the label and wraps (never truncated); .nx-datacard__cell--span
   is a full-row cell (notes). Groups sit side by side; --span2 / --span3 widen a long group so its cells
   flow in two or three columns. Group labels never carry a module or partner color; only
   .nx-link text carries the link color. */
.nx-datacard {
  box-sizing: border-box;
  background: var(--card);
  border: 1px solid var(--nx-line);
  border-radius: 14px;
  overflow: hidden;
  font-family: var(--font-body);
  color: var(--text);
}
.nx-datacard__head {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  height: 44px;
  margin: 0;
  padding: 0 16px;
  border: 0;
  background: none;
  font-family: var(--font-body);
  color: var(--text);
  text-align: left;
  cursor: pointer;
  user-select: none;
}
.nx-datacard__head:hover { background: var(--nx-hover-fill); }
.nx-datacard__head:focus-visible { outline: 2px solid var(--nx-focus); outline-offset: -2px; border-radius: 14px; }
body.light-mode button.nx-datacard__head { color: var(--text); }
.nx-datacard__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  line-height: 0;
  color: var(--text2);
}
.nx-datacard__icon > img,
.nx-datacard__icon > svg { width: 18px; height: 18px; }
.nx-datacard__icon > img { border-radius: 4px; object-fit: contain; }
.nx-datacard__titles { display: flex; align-items: baseline; gap: 10px; flex: 1 1 auto; min-width: 0; white-space: nowrap; }
.nx-datacard__title { font-size: 13px; font-weight: 700; line-height: 1.2; color: var(--text); flex-shrink: 0; }
.nx-datacard__source { font-size: 12px; font-weight: 500; line-height: 1.2; color: var(--text2); flex: 0 1 auto; min-width: 80px; overflow: hidden; text-overflow: ellipsis; }
/* Facts strip: collapsed only — "value short · value short …", ellipsis when the row is narrow */
.nx-datacard__strip { display: none; flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; line-height: 1.2; color: var(--text); }
.nx-datacard.is-collapsed .nx-datacard__strip { display: block; }
.nx-datacard__strip-item { display: inline; }
.nx-datacard__strip-item + .nx-datacard__strip-item::before { content: '\00b7'; margin: 0 6px; color: var(--text2); }
.nx-datacard__strip-value { font-weight: 700; }
.nx-datacard__strip-label { font-size: 11px; color: var(--text2); }
.nx-datacard__chevron { display: inline-flex; flex-shrink: 0; line-height: 0; color: var(--text2); transition: transform 120ms ease; }
.nx-datacard.is-collapsed .nx-datacard__chevron { transform: rotate(-90deg); }
.nx-datacard.is-empty .nx-datacard__chevron { display: none; }
.nx-datacard.is-empty .nx-datacard__head { cursor: default; }
.nx-datacard.is-empty .nx-datacard__head:hover { background: none; }
.nx-datacard__body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 12px 16px;
  border-top: 1px solid var(--nx-line);
}
.nx-datacard.is-collapsed .nx-datacard__body,
.nx-datacard.is-empty .nx-datacard__body { display: none; }
/* Facts: fixed tiles on the page ground, left-aligned, never stretched */
.nx-datacard__facts { display: flex; flex-wrap: wrap; justify-content: flex-start; gap: 8px; max-width: 1600px; }
.nx-datacard__fact {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1 1 150px;
  max-width: 200px;
  min-width: 0;
  padding: 8px 12px;
  border: 1px solid var(--nx-line);
  border-radius: 10px;
  background: var(--bg);
}
.nx-datacard__fact-label { font-size: 10px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase; color: var(--text2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nx-datacard__fact-value { font-size: 16px; font-weight: 700; line-height: 1.15; color: var(--text); overflow-wrap: anywhere; }
.nx-datacard__fact-value.is-empty { color: var(--muted); }
.nx-datacard__fact-sub { font-size: 11px; line-height: 1.3; color: var(--text2); overflow-wrap: anywhere; }
.nx-datacard__fact-sub:empty { display: none; }
/* Groups side by side (200px min, 14px gap: the module fit pass reads these); a long group spans two or
   three columns and its cells flow in as many */
.nx-datacard__groups { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px 14px; max-width: 1600px; }
.nx-datacard__group { min-width: 0; }
.nx-datacard__group--span2 { grid-column: span 2; }
.nx-datacard__group--span3 { grid-column: span 3; }
.nx-datacard__group-label { margin: 0 0 4px; font-size: 10px; font-weight: 700; letter-spacing: .5px; line-height: 1.2; text-transform: uppercase; color: var(--text2); }
.nx-datacard__cells { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr)); gap: 4px 24px; }
.nx-datacard__group--span2 > .nx-datacard__cells { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.nx-datacard__group--span3 > .nx-datacard__cells { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* Cell: label, then the value on the same line while it fits; a long value drops under the label and
   wraps. Nothing is ever cut off: no ellipsis, no clamp, rows size to content. */
.nx-datacard__cell { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 6px; min-width: 0; line-height: 1.3; }
.nx-datacard__cell-label { flex-shrink: 0; font-size: 12px; color: var(--text2); white-space: nowrap; }
.nx-datacard__cell-value { flex: 1 1 auto; min-width: 0; font-size: 13px; color: var(--text); overflow-wrap: anywhere; }
.nx-datacard__cell--span { grid-column: 1 / -1; }
@media (max-width: 900px) {
  .nx-datacard__group--span2, .nx-datacard__group--span3 { grid-column: auto; }
  .nx-datacard__group--span2 > .nx-datacard__cells, .nx-datacard__group--span3 > .nx-datacard__cells { grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr)); }
}
@media (prefers-reduced-motion: reduce) { .nx-datacard__chevron { transition: none; } }

/* ── Tag ──────────────────────────────────────────────────────────────────
   A static neutral pill for a state word inside data (not a control: chips are buttons). */
.nx-tag {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  height: 24px;
  padding: 0 10px;
  border-radius: 999px;
  border: 1px solid var(--nx-line-strong);
  background: var(--nx-hover-fill);
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  line-height: 1;
  color: var(--text);
  white-space: nowrap;
  vertical-align: middle;
}

/* ── Card ─────────────────────────────────────────────────────────────────
   A panel in a centered column (Wingman's two step cards). Head = an optional step badge + a title;
   the badge is the one place the module color sits in a body (a number, not a control). */
.nx-card {
  box-sizing: border-box;
  padding: 24px;
  border-radius: 14px;
  border: 1px solid var(--nx-line);
  background: var(--card);
  color: var(--text);
  font-family: var(--font-body);
}
.nx-card + .nx-card { margin-top: 20px; }
.nx-card__head { display: flex; align-items: center; gap: 12px; margin: 0 0 20px; }
.nx-card__title { display: flex; align-items: center; gap: 10px; margin: 0; font-size: 16px; font-weight: 700; line-height: 1.2; color: var(--text); }
/* Settings card grammar: a 12px muted subtitle under the title, stacked rows with 1px dividers
   (label + description left, the control right), a 220px label / field grid, a right-aligned footer. */
.nx-card__sub { margin: 4px 0 0; font-size: 12px; line-height: 1.35; color: var(--text2); }
.nx-card__rows { display: flex; flex-direction: column; }
.nx-card__row { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 14px 0; }
.nx-card__rows > * + .nx-card__row { border-top: 1px solid var(--nx-line); }
.nx-card__row-text { min-width: 0; }
.nx-card__row-label { font-size: 13px; font-weight: 600; line-height: 1.3; color: var(--text); }
.nx-card__row-desc { margin-top: 2px; font-size: 12px; line-height: 1.4; color: var(--text2); }
.nx-card__row-ctl { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.nx-form { display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: 14px 16px; align-items: center; margin-top: 16px; }
.nx-form__label { font-size: 13px; font-weight: 600; line-height: 1.3; color: var(--text); }
.nx-form__hint { display: block; margin-top: 2px; font-size: 12px; font-weight: 400; line-height: 1.4; color: var(--text2); }
.nx-form__full { grid-column: 1 / -1; }
.nx-form__row { display: contents; }   /* label + field pair a module can hide as one (role gates) */
@media (max-width: 720px) { .nx-form { grid-template-columns: minmax(0, 1fr); } }
.nx-card__foot { display: flex; align-items: center; justify-content: flex-end; gap: 8px; margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--nx-line); }
.nx-step {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--nx-module, var(--text2));
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
}

/* ── Field group + label ──────────────────────────────────────────────────
   .nx-group stacks a label over its row; .nx-label is 11px caps, muted, 8px above the row. The label is a
   flex row so a small control (an .nx-seg--sm, a text button) can sit at its right end. */
.nx-group { margin: 0 0 16px; }
.nx-group:last-child { margin-bottom: 0; }
.nx-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 0 0 8px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .5px;
  line-height: 1.2;
  text-transform: uppercase;
  color: var(--text2);
}
.nx-label > .nx-seg,
.nx-label > .nx-btn { text-transform: none; letter-spacing: 0; }

/* ── Text field ───────────────────────────────────────────────────────────
   <label class="nx-field"><span class="nx-field__affix">$</span><input …></label>: the same ground, line
   and radius as .nx-search, with an optional affix ($, %) on either side. A bare <select class="nx-field">
   takes the box itself. --area = a textarea that grows. .nx-range = a min–max pair with a dash between. */
.nx-field {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  height: 40px;
  padding: 0 12px;
  border-radius: 10px;
  border: 1px solid var(--nx-field-line);
  background: var(--nx-field-fill);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 14px;
}
.nx-field:focus-within { border-color: var(--nx-focus); }
.nx-field > input,
.nx-field > select,
.nx-field > textarea {
  flex: 1 1 auto;
  min-width: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  outline: none;
  font: inherit;
  font-size: 14px;
  color: var(--text);
}
.nx-field > input::placeholder,
.nx-field > textarea::placeholder { color: var(--text2); }
.nx-field > input:read-only { color: var(--text2); }
/* Native pickers and select lists follow the theme: dark by default, light under body.light-mode; options carry
   explicit token colors for the browsers that paint them from the page. */
.nx-field > input[type="month"],
.nx-field > input[type="date"],
.nx-field > input[type="time"],
.nx-field > input[type="datetime-local"],
.nx-field > select,
select.nx-field,
input.nx-field { color-scheme: dark; }
.nx-field > select > option,
select.nx-field > option { background: var(--card); color: var(--text); }
body.light-mode .nx-field > input[type="month"],
body.light-mode .nx-field > input[type="date"],
body.light-mode .nx-field > input[type="time"],
body.light-mode .nx-field > input[type="datetime-local"],
body.light-mode .nx-field > select,
body.light-mode select.nx-field,
body.light-mode input.nx-field { color-scheme: light; }
select.nx-field { display: block; cursor: pointer; }
select.nx-field:focus-visible { outline: none; border-color: var(--nx-focus); }
input.nx-field:focus { outline: none; border-color: var(--nx-focus); }
.nx-field--auto { width: auto; }
.nx-field--area { height: auto; padding: 10px 12px; align-items: stretch; }
.nx-field--area > textarea { height: auto; min-height: 96px; resize: vertical; line-height: 1.4; }
.nx-field__affix { flex-shrink: 0; font-size: 13px; font-weight: 600; color: var(--text2); }
.nx-range { display: flex; align-items: center; gap: 8px; }
.nx-range > .nx-field { flex: 1 1 0; min-width: 0; }
.nx-range__dash { flex-shrink: 0; color: var(--text2); font-size: 14px; }

/* ── Chip dot ─────────────────────────────────────────────────────────────
   A colored dot inside a chip (a tag's own color = data; the chip itself stays neutral). */
.nx-chip__dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }

/* ── Dropdown trigger ─────────────────────────────────────────────────────
   .nx-btn--select on an .nx-btn--secondary: label left, chevron at the right edge; the menu it opens is an
   .nx-popover--menu placed under it by the module. */
.nx-btn--select { justify-content: flex-start; text-align: left; }
.nx-btn--select > .nx-btn__icon:last-child { margin-left: auto; color: var(--text2); }
.nx-btn--select > .nx-btn__icon > svg { width: 18px; height: 18px; }

/* ── Popover menu ─────────────────────────────────────────────────────────
   .nx-popover--menu = a list of rows (icon 18 + label). A row with --sub opens its flyout (a nested
   .nx-popover--menu.nx-popover__sub) on hover or focus. */
.nx-popover--menu { padding: 6px; min-width: 220px; max-height: none; overflow: visible; }
.nx-popover__item {
  position: relative;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 36px;
  padding: 0 10px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 500;
  line-height: 1;
  text-align: left;
  color: var(--text);
  white-space: nowrap;
  cursor: pointer;
}
.nx-popover__item:hover,
.nx-popover__item:focus-visible,
.nx-popover__item:focus-within { background: var(--nx-hover-fill); outline: none; }
.nx-popover__item > svg { width: 18px; height: 18px; flex-shrink: 0; }
.nx-popover__chevron { display: inline-flex; margin-left: auto; line-height: 0; color: var(--text2); }
.nx-popover__chevron > svg { width: 18px; height: 18px; }
.nx-popover__sub { display: none; position: absolute; top: -7px; left: calc(100% + 2px); }
.nx-popover__item--sub:hover > .nx-popover__sub,
.nx-popover__item--sub:focus-within > .nx-popover__sub { display: block; }
body.light-mode button.nx-popover__item { color: var(--text); }

/* ── Card grid ────────────────────────────────────────────────────────────
   Equal cards side by side (stat cards): as many columns as fit --nx-card-min (220px), wrapping below that.
   The stacked-column margin between adjacent cards does not apply inside a grid. */
.nx-card-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(var(--nx-card-min, 220px), 1fr)); gap: 12px; }
.nx-card-grid > .nx-card { margin-top: 0; }

/* ── Tiles + banner (Settings › My Company home) ──────────────────────────
   <div class="nx-tiles"><button class="nx-tile"><span class="nx-tile__head"><span class="nx-tile__icon">svg</span>
   <span class="nx-tile__title">Comp</span></span><span class="nx-tile__desc">…</span></button></div>
   A fixed 3-column grid (2 / 1 at narrow widths). .nx-banner = one tinted full-width card above it. */
.nx-tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin: 0 0 24px; }
@media (max-width: 1100px) { .nx-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) { .nx-tiles { grid-template-columns: minmax(0, 1fr); } }
.nx-tile {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
  min-height: 112px;
  padding: 16px;
  border-radius: 14px;
  border: 1px solid var(--nx-line);
  background: var(--card);
  color: var(--text);
  font-family: var(--font-body);
  text-align: left;
  cursor: pointer;
  transition: border-color 120ms ease, background-color 120ms ease;
}
.nx-tile:hover { border-color: var(--nx-line-strong); background: var(--nx-hover-fill); }
.nx-tile:focus-visible { outline: 2px solid var(--nx-focus); outline-offset: 2px; }
.nx-tile__head { display: flex; align-items: center; gap: 10px; min-width: 0; }
.nx-tile__icon { display: flex; flex-shrink: 0; line-height: 0; }
.nx-tile__title { font-size: 15px; font-weight: 700; line-height: 1.2; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nx-tile__desc { font-size: 13px; line-height: 1.4; color: var(--text2); }
.nx-banner {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 0 0 24px;
  padding: 16px 20px;
  border-radius: 14px;
  border: 1px solid rgba(20,184,166,.35);
  background: rgba(15,118,110,.10);
  color: var(--text);
  font-family: var(--font-body);
}
.nx-banner__icon { display: flex; flex-shrink: 0; line-height: 0; }
.nx-banner__text { flex: 1 1 auto; min-width: 0; }
.nx-banner__title { font-size: 15px; font-weight: 700; line-height: 1.2; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nx-banner__sub { margin-top: 2px; font-size: 13px; line-height: 1.4; color: var(--text2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ── Chip toggle ──────────────────────────────────────────────────────────
   A small icon toggle at the trailing end of a chip (a favorite star): a span with role="button" and tabindex,
   never a nested button. Muted off; .is-on lights it in the amber token and fills the outline. The module's row
   handler checks it before the chip, so its click toggles without selecting. */
.nx-chip__toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  margin: 0 -4px 0 2px;
  flex-shrink: 0;
  border-radius: 50%;
  color: var(--muted);
  line-height: 0;
  cursor: pointer;
  transition: color 120ms ease;
}
.nx-chip__toggle > svg { width: 16px; height: 16px; display: block; }
.nx-chip__toggle:hover { color: var(--text2); }
.nx-chip__toggle:focus-visible { outline: 2px solid var(--nx-focus); outline-offset: 1px; }
.nx-chip__toggle.is-on { color: var(--amber); }
.nx-chip__toggle.is-on > svg { fill: currentColor; }

/* ── Table ────────────────────────────────────────────────────────────────
   A data table in a card (Homebase's month table first; Wingman's results and Workbench's comparison adopt it).
   <div class="nx-table-wrap"><table class="nx-table"><thead><tr><th class="nx-table__pin">#</th>…</tr></thead>
   <tbody><tr style="--nx-row-wash: …"><td class="nx-table__pin">…</td>…</tr></tbody></table>
   <div class="nx-table-foot">count · sort</div></div>
   The wrap is the card surface and the scroller for both axes; the head is sticky at the top, a .nx-table__pin
   column sticks left (--2 = the second pinned column, after --nx-pin-w of the first) with the row's background.
   Rows are 44px on a 1px line; even rows tint, hover tints more; a row may carry its own wash as --nx-row-wash
   (a status color: data). Cell types are classes: __muted, __num (right, tabular), __center, __link (600 + a glyph),
   __sep (a dashed left edge: the first custom column). A sorted head cell is .is-sorted (+ .is-desc) with the
   indicator drawn after its text. Controls inside cells are the shared ones: .nx-tag--sm, .nx-status,
   .nx-toggle--sm, .nx-field--sm. */
.nx-table-wrap {
  box-sizing: border-box;
  position: relative;
  border: 1px solid var(--nx-line);
  border-radius: 12px;
  background: var(--card);
  overflow: auto;
  font-family: var(--font-body);
  color: var(--text);
}
.nx-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.3;
  color: var(--text);
}
.nx-table > thead > tr > th {
  position: sticky;
  top: 0;
  z-index: 3;
  box-sizing: border-box;
  height: 40px;
  padding: 0 12px;
  background: var(--card);
  border-bottom: 1px solid var(--nx-line);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .5px;
  text-transform: uppercase;
  color: var(--text2);
  text-align: left;
  white-space: nowrap;
  vertical-align: middle;
}
.nx-table > tbody > tr > td {
  box-sizing: border-box;
  height: 44px;
  padding: 0 12px;
  border-bottom: 1px solid var(--nx-line);
  vertical-align: middle;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  background-color: transparent;
  background-image: linear-gradient(var(--nx-row-tint, transparent), var(--nx-row-tint, transparent)), linear-gradient(var(--nx-row-wash, transparent), var(--nx-row-wash, transparent));
}
.nx-table > tbody > tr:nth-child(even) { --nx-row-tint: var(--nx-row-alt); }
.nx-table > tbody > tr:hover { --nx-row-tint: var(--nx-row-hover); }
.nx-table > tbody > tr:last-child > td { border-bottom: 0; }
/* Pinned columns: opaque on the surface so scrolled cells never show through; the head stays above both. */
.nx-table .nx-table__pin { position: sticky; left: 0; z-index: 2; }
.nx-table .nx-table__pin--2 { position: sticky; left: var(--nx-pin-w, 56px); z-index: 2; box-shadow: 1px 0 0 var(--nx-line); }
.nx-table > thead > tr > th.nx-table__pin,
.nx-table > thead > tr > th.nx-table__pin--2 { z-index: 4; }
.nx-table > tbody > tr > td.nx-table__pin,
.nx-table > tbody > tr > td.nx-table__pin--2 { background-color: var(--card); }
.nx-table .nx-table__sep { border-left: 1px dashed var(--nx-line-strong); }
/* Sort indicator on the sorted head cell */
.nx-table > thead > tr > th.is-sorted,
.nx-sortable > thead > tr > th.is-sorted { color: var(--text); }
.nx-table > thead > tr > th.is-sorted::after,
.nx-sortable > thead > tr > th.is-sorted::after { content: '\25B2'; margin-left: 5px; font-size: 8px; vertical-align: 1px; }
.nx-table > thead > tr > th.is-sorted.is-desc::after,
.nx-sortable > thead > tr > th.is-sorted.is-desc::after { content: '\25BC'; }
/* Cell types */
.nx-table td.nx-table__muted,
.nx-table th.nx-table__muted { color: var(--text2); font-weight: 400; text-transform: none; letter-spacing: 0; }
.nx-table .nx-table__num { text-align: right; font-variant-numeric: tabular-nums; }
.nx-table .nx-table__center { text-align: center; }
.nx-table__link { display: inline-flex; align-items: center; gap: 4px; font-weight: 600; color: var(--text); }
/* Group label row — "Closed · 3" above a group of rows: 28px, 11px caps muted, one step darker than the rows, spans
   every column, scrolls with the rows (not sticky), never tinted, never focusable (aria-hidden on the row).
   <tr class="nx-table__group" aria-hidden="true"><td colspan="N">Closed · 3</td></tr> */
.nx-table > tbody > tr.nx-table__group,
.nx-table > tbody > tr.nx-table__group:hover { --nx-row-tint: transparent; --nx-row-wash: transparent; pointer-events: none; }
.nx-table > tbody > tr.nx-table__group > td {
  height: 28px;
  padding: 0 12px;
  background-color: var(--bg2);
  background-image: none;
  border-bottom: 1px solid var(--nx-line);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .5px;
  text-transform: uppercase;
  color: var(--text2);
  white-space: nowrap;
}
/* Footer row: count left, sort right (sticky at the bottom of the scroller) */
.nx-table-foot {
  position: sticky;
  bottom: 0;
  left: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  height: 32px;
  padding: 0 12px;
  border-top: 1px solid var(--nx-line);
  background: var(--card);
  font-size: 12px;
  color: var(--text2);
}

/* ── Status pill ──────────────────────────────────────────────────────────
   A 22px tinted pill with a 6px dot for a state inside data; its color is the status's own (a data class such
   as Homebase's vstatus-* that sets color + background). role="button" when it opens a menu. */
.nx-status {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 22px;
  padding: 0 9px;
  border-radius: 999px;
  background: var(--nx-hover-fill);
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
  vertical-align: middle;
  color: var(--text);
}
.nx-status::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex-shrink: 0; }
.nx-status[role="button"] { cursor: pointer; user-select: none; }
.nx-status[role="button"]:hover { filter: brightness(1.15); }
.nx-status[role="button"]:focus-visible { outline: 2px solid var(--nx-focus); outline-offset: 2px; }

/* ── Small tag ────────────────────────────────────────────────────────── */
.nx-tag--sm { height: 22px; padding: 0 8px; font-size: 11px; font-weight: 700; }
.nx-tag--tint { background: var(--nx-active-fill); border-color: var(--nx-active-line); color: var(--nx-chip-active-text); }
.nx-tag--ok     { background: var(--nx-up-fill);     border-color: color-mix(in srgb, var(--nx-up) 40%, transparent); color: var(--nx-up); }
.nx-tag--warn   { background: var(--nx-hold-fill);   border-color: var(--nx-hold-line);   color: var(--nx-hold); }
.nx-tag--danger { background: var(--nx-urgent-fill); border-color: var(--nx-urgent-line); color: var(--nx-urgent); }

/* ── Small field (table cells, toolbars): 30px; --num right-aligns the input; --select hides the native arrow
   and draws .nx-field__chevron (a chevron-down glyph) at the right. */
.nx-field--sm { height: 30px; padding: 0 8px; border-radius: 8px; font-size: 12px; }
.nx-field--sm > input,
.nx-field--sm > select,
.nx-field--sm > textarea { font-size: 12px; }
.nx-field--num > input { text-align: right; font-variant-numeric: tabular-nums; }
/* Inside a table cell a field never collapses with its column: text 120, number 72 (the column grows to fit). */
.nx-table .nx-field--sm { min-width: 120px; }
.nx-table .nx-field--sm.nx-field--num { min-width: 72px; }
/* --select: the select spans the whole field; the chevron is drawn over its right edge and never takes the click,
   so the native list opens from anywhere in the field. */
.nx-field--select { position: relative; }
.nx-field--select > select { appearance: none; -webkit-appearance: none; padding-right: 22px; cursor: pointer; }
.nx-field__chevron { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); line-height: 0; color: var(--text2); pointer-events: none; }
.nx-field--sm > .nx-field__chevron { right: 6px; }
.nx-field__chevron > svg { width: 18px; height: 18px; display: block; }
/* Disabled: the whole field dims as one (the control inside is what carries `disabled`); bare fields on :disabled. */
.nx-field:has(:disabled),
select.nx-field:disabled,
input.nx-field:disabled { opacity: .4; }

/* ── Small toggle: 36×20 (table cells) ── */
.nx-toggle--sm { width: 36px; height: 20px; }
.nx-toggle--sm .nx-toggle__track::after { width: 14px; height: 14px; }
.nx-toggle--sm > input:checked ~ .nx-toggle__track::after,
.nx-toggle--sm.is-on > .nx-toggle__track::after,
.nx-toggle--sm.on > .nx-toggle__track::after { transform: translateX(16px); }

/* ── Card spanning two grid columns (a double-width stat card) ── */
.nx-card--span2 { grid-column: span 2; }

/* A control hidden by the attribute stays hidden (the class display would otherwise win). */
.nx-btn[hidden],
.nx-chip[hidden],
.nx-tab[hidden],
.nx-rail__item[hidden],
.nx-body[hidden],
.nx-toggle[hidden] { display: none; }

/* ═══════════════════════════════════════════════════════════════════════════
   Batch 10 (Calendar) additions, all token-driven, dark + light.
   Shared:
     --nx-cal-cat-*      the six manual-event category colors (meeting, closing, rate_lock, follow_up, personal, other)
     html[data-nx-accent] body:not(.light-mode)
                         the company-theme hook: NxTheme.apply sets the attribute only when the company accent is
                         not the default; primaries, seg "on" and toggle "on" then follow --accent. Never on :root,
                         never in light mode (the company theme is cleared there).
     .nx-rail__toggle    36px label row inside a rail with a swatch (bar or dot) and a .nx-toggle at its right end
     .nx-countchip       20px count pill: a module-colored dot (--nx-chip-c) on a tinted fill; .is-open while its popover shows
   Namespaced (.nx-cal-*): the mini month, the event row block, the week grid (sticky day header + time gutter inside
   the one scroller), the count popover and the Appointments-tab row.
   ═══════════════════════════════════════════════════════════════════════════ */
:root {
  --nx-cal-cat-meeting: #2DD4BF;
  --nx-cal-cat-closing: #22C55E;
  --nx-cal-cat-rate_lock: #F59E0B;
  --nx-cal-cat-follow_up: #4A9EFF;
  --nx-cal-cat-personal: #A78BFA;
  --nx-cal-cat-other: #9CA3AF;
}
body.light-mode {
  --nx-cal-cat-meeting: #0F766E;
  --nx-cal-cat-closing: #15803D;
  --nx-cal-cat-rate_lock: #B45309;
  --nx-cal-cat-follow_up: #1D4ED8;
  --nx-cal-cat-personal: #6D28D9;
  --nx-cal-cat-other: #4B5563;
}
/* Company accent active (dark only): the action token follows the company accent and its derived shades. */
html[data-nx-accent] body:not(.light-mode) {
  --nx-action: var(--accent);
  --nx-action-hover: var(--accent-mid);
  --nx-action-press: var(--accent-deep);
}

/* ── Rail toggle row ──────────────────────────────────────────────────────
   <label class="nx-rail__toggle"><span class="nx-rail__swatch nx-rail__swatch--bar" style="--nx-swatch:…"></span>
     <span class="nx-rail__toggle-text">Events</span>
     <span class="nx-toggle nx-toggle--sm"><input type="checkbox"><span class="nx-toggle__track"></span></span></label>
   A disabled input (an always-on layer) dims the switch through .nx-toggle's own disabled rule. */
.nx-rail__toggle {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  height: 36px;
  margin: 0 0 2px;
  padding: 0 12px;
  border-radius: 10px;
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  color: var(--text);
  cursor: pointer;
  user-select: none;
}
.nx-rail__toggle:hover { background: var(--nx-hover-fill); }
.nx-rail__toggle-text { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nx-rail__swatch { flex-shrink: 0; background: var(--nx-swatch, var(--text2)); }
.nx-rail__swatch--bar { width: 4px; height: 16px; border-radius: 2px; }
.nx-rail__swatch--dot { width: 8px; height: 8px; border-radius: 50%; margin: 0 2px 0 -2px; }
.nx-rail__toggle > .nx-toggle { margin-left: auto; }

/* ── Count chip ───────────────────────────────────────────────────────────
   <button type="button" class="nx-countchip" style="--nx-chip-c: var(--nx-launchpad)"><span class="nx-countchip__dot"></span>14 emails</button> */
.nx-countchip {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  max-width: 100%;
  height: 20px;
  margin: 0 0 2px;
  padding: 0 8px 0 6px;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--nx-chip-c, var(--text2)) 40%, transparent);
  background: color-mix(in srgb, var(--nx-chip-c, var(--text2)) 14%, transparent);
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
  user-select: none;
  transition: background-color 120ms ease, border-color 120ms ease;
}
.nx-countchip:hover,
.nx-countchip.is-open { background: color-mix(in srgb, var(--nx-chip-c, var(--text2)) 26%, transparent); border-color: color-mix(in srgb, var(--nx-chip-c, var(--text2)) 70%, transparent); }
.nx-countchip:focus-visible { outline: 2px solid var(--nx-focus); outline-offset: 2px; }
.nx-countchip__dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; background: var(--nx-chip-c, var(--text2)); }
body.light-mode button.nx-countchip { color: var(--text); }

/* ── Calendar: mini month (rail) ───────────────────────────────────────── */
.nx-cal-mini__bar { display: flex; align-items: center; justify-content: space-between; gap: 6px; margin: 0 0 8px; }
.nx-cal-mini__label { font-size: 13px; font-weight: 700; color: var(--text); white-space: nowrap; }
.nx-cal-mini { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 2px 0; text-align: center; }
.nx-cal-mini__dow { padding: 2px 0 4px; font-size: 10px; font-weight: 700; letter-spacing: .06em; color: var(--nx-text-dim); }
.nx-cal-mini__day {
  position: relative;
  box-sizing: border-box;
  height: 28px;
  padding: 3px 0 0;
  border: 1px solid transparent;
  border-radius: 8px;
  font-size: 12px;
  font-weight: 500;
  line-height: 1.2;
  color: var(--text2);
  cursor: pointer;
  user-select: none;
}
.nx-cal-mini__day:hover { background: var(--nx-hover-fill); color: var(--text); }
.nx-cal-mini__day.is-week { background: color-mix(in srgb, var(--nx-action) 12%, transparent); color: var(--text); }
.nx-cal-mini__day.is-today { border-color: var(--nx-action); color: var(--text); font-weight: 700; }
.nx-cal-mini__day.is-selected,
.nx-cal-mini__day.is-selected:hover { background: var(--nx-action); border-color: var(--nx-action); color: #fff; font-weight: 700; }
.nx-cal-mini__dots { display: flex; justify-content: center; gap: 2px; height: 3px; margin-top: 1px; line-height: 0; }
.nx-cal-mini__dot { width: 3px; height: 3px; border-radius: 50%; background: var(--nx-dot, var(--text2)); }
.nx-cal-mini__day.is-selected .nx-cal-mini__dot { background: #fff; }

/* ── Calendar: week grid (the one scroller holds it; header row and gutter are sticky inside it) ── */
.nx-cal-toolbar { height: 56px; }
.nx-cal-toolbar__title { font-size: 18px; font-weight: 700; color: var(--text); white-space: nowrap; }
.nx-cal-grid { display: grid; grid-template-columns: 52px repeat(7, minmax(0, 1fr)); min-width: 0; }
.nx-cal-grid__corner,
.nx-cal-grid__dayhead { position: sticky; top: 0; z-index: 3; background: var(--bg); border-bottom: 1px solid var(--nx-line); }
.nx-cal-grid__corner { left: 0; z-index: 4; }
.nx-cal-grid__dayhead { padding: 8px 0 6px; text-align: center; cursor: pointer; user-select: none; }
.nx-cal-grid__dayhead:hover { background: var(--nx-hover-fill); }
.nx-cal-grid__dow { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--text2); }
.nx-cal-grid__num { margin-top: 2px; font-size: 16px; font-weight: 500; line-height: 1.1; color: var(--text); }
.nx-cal-grid__dayhead.is-today { background: color-mix(in srgb, var(--nx-action) 10%, var(--bg)); }
.nx-cal-grid__dayhead.is-today .nx-cal-grid__dow,
.nx-cal-grid__dayhead.is-today .nx-cal-grid__num { color: var(--nx-text-link); font-weight: 700; }
.nx-cal-grid__dayhead.is-selected { box-shadow: inset 0 -2px 0 var(--nx-action); }
.nx-cal-grid__gutter {
  position: sticky; left: 0; z-index: 2;
  box-sizing: border-box; min-height: 48px; padding: 2px 8px 0 0;
  background: var(--bg); border-top: 1px solid var(--nx-hairline);
  font-size: 10px; font-weight: 600; text-align: right; color: var(--text2);
}
.nx-cal-grid__cell {
  position: relative;
  box-sizing: border-box;
  min-height: 48px;
  padding: 2px;
  border-top: 1px solid var(--nx-hairline);
  border-left: 1px solid var(--nx-hairline);
  overflow: hidden;
}
.nx-cal-grid__cell.is-today { background: color-mix(in srgb, var(--nx-action) 5%, transparent); }
.nx-cal-grid__more { padding: 0 4px; font-size: 10px; color: var(--text2); }

/* ── Calendar: event row block (appointments, manual events, sends in Rows mode) ──
   <div class="nx-cal-evt" style="--nx-evt-c: var(--nx-cal-cat-meeting)" data-event="id"><span>title</span></div> */
.nx-cal-evt {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: 6px;
  height: 22px;
  margin: 0 0 2px;
  padding: 0 6px;
  border-left: 3px solid var(--nx-evt-c, var(--text2));
  border-radius: 6px;
  background: color-mix(in srgb, var(--nx-evt-c, var(--text2)) 14%, transparent);
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  cursor: pointer;
}
.nx-cal-evt:hover { background: color-mix(in srgb, var(--nx-evt-c, var(--text2)) 24%, transparent); }
.nx-cal-evt > span { overflow: hidden; text-overflow: ellipsis; }
.nx-cal-evt__time { flex-shrink: 0; font-weight: 500; color: var(--text2); }
.nx-cal-evt--send { cursor: default; font-weight: 500; }
.nx-cal-evt--span { position: absolute; top: 2px; left: 2px; right: 2px; z-index: 2; height: auto; align-items: flex-start; padding-top: 5px; }

/* ── Calendar: count popover ── */
.nx-cal-pop { min-width: 220px; max-width: 320px; padding: 10px 12px; }
.nx-cal-pop__item { display: flex; align-items: center; gap: 8px; padding: 4px 0; font-size: 12px; color: var(--text); }
.nx-cal-pop__item > .nx-countchip__dot { background: var(--nx-chip-c, var(--text2)); }

/* ── Calendar: Appointments-tab row ──
   <div class="nx-cal-row" data-appt="id" role="button" tabindex="0"> avatar · text · when · actions */
.nx-cal-rows { display: flex; flex-direction: column; }
.nx-cal-row {
  display: grid;
  grid-template-columns: 36px minmax(0, 1.4fr) minmax(0, 1fr) auto;
  align-items: center;
  gap: 14px;
  padding: 12px;
  margin: 0 -12px;
  border-radius: 10px;
  cursor: pointer;
}
.nx-cal-rows > .nx-cal-row + .nx-cal-row { border-top: 1px solid var(--nx-line); border-radius: 0 0 10px 10px; }
.nx-cal-row:hover { background: var(--nx-hover-fill); }
.nx-cal-row:focus-visible { outline: 2px solid var(--nx-focus); outline-offset: -2px; }
.nx-cal-row__avatar {
  display: flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: 50%;
  border: 1px solid var(--nx-av, var(--text2));
  background: color-mix(in srgb, var(--nx-av, var(--text2)) 16%, transparent);
  color: var(--nx-av, var(--text2));
  font-size: 12px; font-weight: 700; letter-spacing: .02em;
}
.nx-cal-row__text,
.nx-cal-row__when { min-width: 0; }
.nx-cal-row__name { font-size: 14px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nx-cal-row__meta { margin-top: 3px; display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--text2); white-space: nowrap; overflow: hidden; }
.nx-cal-row__meta > span { overflow: hidden; text-overflow: ellipsis; }
.nx-cal-row__date { font-size: 13px; font-weight: 600; color: var(--text); white-space: nowrap; }
.nx-cal-row__type { margin-top: 3px; font-size: 12px; color: var(--text2); white-space: nowrap; }
.nx-cal-row__actions { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.nx-cal-status--completed { color: var(--nx-text-link); }
.nx-cal-status--no_show { color: var(--nx-backseat); }
.nx-cal-status--cancelled { color: var(--nx-danger-text); }
.nx-cal-empty { padding: 24px 0; text-align: center; font-size: 13px; color: var(--text2); }

/* ── Calendar: modals (panel + fields on the shared tokens) ── */
.nx-cal-modal {
  box-sizing: border-box;
  position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
  z-index: 9999;
  width: 440px; max-width: 90vw; max-height: 90vh; overflow-y: auto;
  padding: 28px;
  border-radius: 14px;
  border: 1px solid var(--nx-line-strong);
  background: var(--card);
  color: var(--text);
  font-family: var(--font-body);
  box-shadow: 0 20px 60px rgba(0,0,0,.35);
}
.nx-cal-modal--narrow { width: 400px; }
.nx-cal-backdrop { position: fixed; inset: 0; z-index: 9998; background: rgba(0,0,0,.55); }
.nx-cal-modal__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 0 0 20px; }
.nx-cal-modal__title { margin: 0; font-size: 18px; font-weight: 700; line-height: 1.2; color: var(--text); }
.nx-cal-modal__grid { display: flex; flex-direction: column; gap: 14px; }
.nx-cal-modal__pair { display: flex; gap: 12px; }
.nx-cal-modal__pair > * { flex: 1 1 0; min-width: 0; }
.nx-cal-modal__foot { display: flex; align-items: center; gap: 8px; margin-top: 20px; }
.nx-cal-modal__foot > .nx-cal-modal__spacer { flex: 1 1 auto; }
.nx-cal-note { padding: 10px 12px; border: 1.5px solid var(--nx-action); border-radius: 10px; }
.nx-cal-note > .nx-label { color: var(--nx-text-link); }
.nx-cal-note__hint { margin: 6px 0 0; font-size: 11px; color: var(--nx-text-link); }
.nx-cal-modal__copy { margin: 14px 0 0; font-size: 11px; line-height: 1.4; color: var(--text2); }
.nx-cal-detail__row { display: flex; gap: 12px; padding: 8px 0; border-bottom: 1px solid var(--nx-hairline); font-size: 14px; color: var(--text); }
.nx-cal-detail__row:last-child { border-bottom: 0; }
.nx-cal-detail__key { flex-shrink: 0; width: 90px; padding-top: 2px; font-size: 11px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase; color: var(--text2); }
.nx-cal-detail__val { min-width: 0; word-break: break-word; }
/* The mini-month arrows are 32 square (the shared small icon button stays 40 wide); .nx-cal-flip mirrors a chevron glyph (prev = next flipped). */
.nx-cal-mini__bar > .nx-btn--icon { width: 32px; }
.nx-cal-flip > .nx-btn__icon > svg { transform: scaleX(-1); }
/* A no-show on the week grid stays visible, muted and struck through (cancelled ones are left off the grid). */
.nx-cal-evt--noshow { opacity: .55; }
.nx-cal-evt--noshow > span { text-decoration: line-through; }

/* ═══════════════════════════════════════════════════════════════════════════
   Batch 11 (contact drawer + Portal sheet) additions, all token-driven, dark + light.
     --nx-scrim          the dim behind a drawer (55% black dark, 35% light)
     --nx-ok             a "live / good" state color (portal Active, views seen, notifications on)
     .nx-drawer-backdrop + .nx-drawer
                         a right-docked drawer over the current screen: the backdrop dims and takes outside clicks,
                         the drawer is 600 wide, full height, and slides in from the right in 200ms (.is-open on the
                         backdrop; it slides back out when the class goes). Head + tabs stay put; __body is the one scroller.
       __head / __main / __title / __meta / __tags / __actions
                         the compact drawer header (NOT the shell header): avatar, a 20/800 title row, a meta row of
                         fields, a tag row, icon buttons at the right
       __tabs            shell tabs (.nx-tab) on a 44px bar under the head
     .nx-avatar          48px initials circle on the teal tint
     .nx-chip--sm        24px chip (header tag rows); .nx-chip--add = dashed "+ Tag" chip
     .nx-tab__dot        8px status dot inside a tab (.is-on = --nx-ok); .nx-tab__count--alert = a red count (unread)
     .nx-section-label   the rail group label (11/700 caps, --nx-text-dim) for a section outside a rail
     .nx-sheet           a full-screen sheet in its own fixed root above a drawer (z 9500: over the drawer's 9000, under
                         the 10003 modals); .is-open shows it, no animation. A .nx-header + .nx-body sit inside;
                         .nx-sheet__back is its back circle in the header's reserved right zone.
     .nx-card--tight     a card with a 16px gutter (inside a 600 drawer)
     .nx-stepper         a horizontal step track: buttons with a 28px dot (.is-done = filled + check, .is-current =
                         ringed) joined by a 2px line, a label under each
     .nx-thread / .nx-bubble (--out) / .nx-composer
                         a message thread (its own scroller), bubbles (incoming on the panel, outgoing on the teal tint)
                         and the field + Send row under it
     .nx-aside--wide     a 560 aside (clamped like the rails); --stack + __head + __frame = a label row with icon buttons
                         over a full-height embedded frame
   ═══════════════════════════════════════════════════════════════════════════ */
:root {
  --nx-scrim: rgba(0,0,0,.55);
  --nx-ok: #22C55E;
}
body.light-mode {
  --nx-scrim: rgba(0,0,0,.35);
  --nx-ok: #15803D;
}

/* ── Drawer ───────────────────────────────────────────────────────────── */
.nx-drawer-backdrop {
  position: fixed;
  inset: 0;
  z-index: 9000;
  background: var(--nx-scrim);
  opacity: 0;
  visibility: hidden;
  transition: opacity 200ms ease, visibility 0s linear 200ms;
}
.nx-drawer-backdrop.is-open { opacity: 1; visibility: visible; transition: opacity 200ms ease; }
.nx-drawer {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  width: 600px;
  max-width: 100vw;
  background: var(--bg);
  border-left: 1px solid var(--nx-line);
  box-shadow: -24px 0 64px rgba(0,0,0,.35);
  font-family: var(--font-body);
  color: var(--text);
  transform: translateX(100%);
  transition: transform 200ms ease;
}
.nx-drawer-backdrop.is-open > .nx-drawer { transform: none; }
@media (prefers-reduced-motion: reduce) {
  .nx-drawer-backdrop, .nx-drawer-backdrop.is-open, .nx-drawer { transition: none; }
}
.nx-drawer__head { display: flex; align-items: flex-start; gap: 14px; flex-shrink: 0; padding: 20px 20px 16px; }
.nx-drawer__main { flex: 1 1 auto; min-width: 0; }
.nx-drawer__title { display: flex; align-items: center; gap: 4px; min-width: 0; font-size: 20px; font-weight: 800; line-height: 1.2; color: var(--text); }
.nx-drawer__meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; margin-top: 6px; font-size: 13px; color: var(--text2); }
.nx-drawer__tags { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 10px; }
.nx-drawer__actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.nx-drawer__tabs { display: flex; align-items: stretch; gap: 28px; flex-shrink: 0; height: 44px; padding: 0 20px; border-bottom: 1px solid var(--nx-line); }
.nx-drawer__body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 20px; }

/* ── Avatar ───────────────────────────────────────────────────────────── */
.nx-avatar {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  flex-shrink: 0;
  border-radius: 50%;
  background: rgba(15,118,110,.18);
  border: 1px solid rgba(20,184,166,.35);
  font-family: var(--font-body);
  font-size: 16px;
  font-weight: 800;
  line-height: 1;
  color: var(--nx-chip-active-text);
  user-select: none;
}

/* ── Small chip + dashed add chip ─────────────────────────────────────── */
.nx-chip--sm { height: 24px; padding: 0 10px; gap: 6px; font-size: 12px; }
.nx-chip--add { border-style: dashed; background: transparent; }

/* ── Tab status dot + alert count ─────────────────────────────────────── */
.nx-tab__dot { width: 8px; height: 8px; margin-left: 8px; flex-shrink: 0; border-radius: 50%; background: var(--text2); }
.nx-tab__dot.is-on { background: var(--nx-ok); }
.nx-tab__count--alert,
.nx-tab.is-active .nx-tab__count--alert { background: var(--nx-danger); color: #fff; }

/* ── Section label (outside a rail) ───────────────────────────────────── */
.nx-label--section,
.nx-section-label {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  gap: 8px;
  margin: 0 0 10px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .12em;
  line-height: 1.2;
  text-transform: uppercase;
  color: var(--nx-text-dim);
  user-select: none;
}

/* ── Sheet ────────────────────────────────────────────────────────────── */
.nx-sheet {
  position: fixed;
  inset: 0;
  z-index: 9500;
  display: none;
  flex-direction: column;
  background: var(--bg);
  font-family: var(--font-body);
  color: var(--text);
}
.nx-sheet.is-open { display: flex; }
.nx-sheet__back { position: absolute; top: 16px; right: 20px; z-index: 1; }

/* ── Tight card ───────────────────────────────────────────────────────── */
.nx-card--tight { padding: 16px; }

/* ── Stepper ──────────────────────────────────────────────────────────── */
.nx-stepper { display: flex; align-items: flex-start; }
.nx-stepper__step {
  position: relative;
  box-sizing: border-box;
  display: flex;
  flex: 1 1 0;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  min-width: 0;
  margin: 0;
  padding: 0 2px;
  border: 0;
  background: none;
  font-family: var(--font-body);
  color: var(--text2);
  cursor: pointer;
}
.nx-stepper__step::before {                  /* the line from the previous step's dot to this one */
  content: '';
  position: absolute;
  top: 13px;
  right: 50%;
  width: 100%;
  height: 2px;
  background: var(--nx-line-strong);
}
.nx-stepper__step:first-child::before { display: none; }
.nx-stepper__step.is-done::before,
.nx-stepper__step.is-current::before { background: var(--nx-action); }
.nx-stepper__dot {
  position: relative;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 1px solid var(--nx-line-strong);
  background: var(--card);
  color: #fff;
}
.nx-stepper__dot > svg { width: 14px; height: 14px; }
.nx-stepper__step.is-done .nx-stepper__dot { background: var(--nx-action); border-color: var(--nx-action); }
.nx-stepper__step.is-current .nx-stepper__dot { border: 2px solid var(--nx-action); box-shadow: 0 0 0 4px rgba(15,118,110,.18); }
.nx-stepper__step.is-current .nx-stepper__dot::after { content: ''; width: 10px; height: 10px; border-radius: 50%; background: var(--nx-action); }
.nx-stepper__label { max-width: 96px; font-size: 11px; font-weight: 600; line-height: 1.25; text-align: center; }
.nx-stepper__step.is-current .nx-stepper__label { font-weight: 700; color: var(--text); }
.nx-stepper__step:hover .nx-stepper__dot { border-color: var(--nx-focus); }
.nx-stepper__step:focus-visible { outline: 2px solid var(--nx-focus); outline-offset: 2px; border-radius: 8px; }
body.light-mode button.nx-stepper__step { color: var(--text2); }

/* ── Message thread, bubbles, composer ────────────────────────────────── */
.nx-thread {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 320px;
  min-height: 80px;
  padding: 12px;
  overflow-y: auto;
  border-radius: 10px;
  border: 1px solid var(--nx-line);
  background: var(--bg);
}
.nx-thread__empty { margin: auto; padding: 12px; font-size: 12px; color: var(--text2); text-align: center; }
.nx-bubble {
  box-sizing: border-box;
  align-self: flex-start;
  max-width: 80%;
  padding: 8px 12px;
  border-radius: 14px 14px 14px 4px;
  border: 1px solid var(--nx-line);
  background: var(--card);
  font-size: 13px;
  line-height: 1.4;
  color: var(--text);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.nx-bubble--out { align-self: flex-end; border-radius: 14px 14px 4px 14px; border-color: rgba(20,184,166,.35); background: rgba(15,118,110,.18); }
.nx-bubble__meta { margin-top: 4px; font-size: 10px; color: var(--text2); white-space: normal; }
.nx-composer { display: flex; align-items: flex-end; gap: 8px; margin-top: 12px; }
.nx-composer > .nx-field { flex: 1 1 auto; }
.nx-composer > .nx-field--area > textarea { min-height: 44px; }

/* ── Wide aside with a label row over an embedded frame ───────────────── */
.nx-aside--wide { width: clamp(420px, 30vw, 560px); }
.nx-aside--stack { display: flex; flex-direction: column; overflow: hidden; }
.nx-aside__head { display: flex; align-items: center; gap: 4px; flex-shrink: 0; height: 56px; padding: 0 12px 0 20px; border-bottom: 1px solid var(--nx-line); }
.nx-aside__head > .nx-label--section,
.nx-aside__head > .nx-section-label { flex: 1 1 auto; margin: 0; }
.nx-aside__frame { flex: 1 1 auto; min-height: 0; margin: 16px; overflow: hidden; border-radius: 12px; border: 1px solid var(--nx-line); }
.nx-aside__frame > iframe { display: block; width: 100%; height: 100%; border: 0; }

/* ═══════════════════════════════════════════════════════════════════════════
   Batch 12a (leader views: Owner / Team Lead / Branch home screens) additions, all token-driven, dark + light.
     --nx-up / --nx-down   delta colors (text) and their tinted fills (--nx-up-fill / --nx-down-fill)
     .nx-center--wide      the 1400px dashboard column (1448 with its 24px gutters)
     .nx-stat              a stat card: __label (11px caps) · __value (24/800 tabular) · __units · __split · __foot
                           (delta pills); position:relative so a module can pin a hint in its corner
     .nx-stat--hero        the lead card: spans two grid rows, 42px value, content spread top to bottom
     .nx-delta             20px change pill: --up / --down / --flat; .nx-delta__vs is the muted "vs previous period"
     .nx-chartcard         a card that holds a chart: __head (__title + optional actions), __plot (position:relative
                           box for the canvas, height from --nx-chart-h, default 300), __empty (centered muted line)
     .nx-teamcard          a clickable team summary card: __head (__name · __lead · __count pill), __vol (+ __units),
                           __foot (delta pills), __mini (4-up grid of __mk label / __mv value / optional .nx-delta);
                           --dashed marks a synthetic group (Unassigned)
     .nx-monthstep         prev · month label · next row (__label); __prev mirrors a chevron-right glyph
   ═══════════════════════════════════════════════════════════════════════════ */
:root {
  --nx-up: #34D399;
  --nx-up-fill: rgba(52,211,153,.12);
  --nx-down: #F87171;
  --nx-down-fill: rgba(248,113,113,.12);
}
body.light-mode {
  --nx-up: #047857;
  --nx-up-fill: rgba(4,120,87,.10);
  --nx-down: #B91C1C;
  --nx-down-fill: rgba(185,28,28,.08);
}

.nx-center--wide { max-width: 1448px; }   /* a 1400px column between its 24px gutters */

/* ── Stat card ────────────────────────────────────────────────────────────
   <div class="nx-stat"><div class="nx-stat__label">Emails</div><div class="nx-stat__value">1,204</div>
     <div class="nx-stat__foot"><span class="nx-delta nx-delta--up">▲ 12%</span><span class="nx-delta__vs">vs previous period</span></div></div> */
.nx-stat {
  position: relative;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  min-width: 0;
  padding: 16px 18px;
  border-radius: 12px;
  border: 1px solid var(--nx-line);
  background: var(--card);
  overflow: hidden;
  font-family: var(--font-body);
  color: var(--text);
}
.nx-stat__label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .08em;
  line-height: 1.2;
  text-transform: uppercase;
  color: var(--text2);
}
.nx-stat__value {
  margin-top: 6px;
  font-size: 24px;
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.nx-stat__units { margin-top: 6px; font-size: 14px; font-weight: 500; color: var(--text); }
.nx-stat__split { margin-top: 4px; font-size: 12px; color: var(--text2); }
.nx-stat__foot { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.nx-stat--hero { grid-row: span 2; }
.nx-stat--hero .nx-stat__value { margin-top: 12px; font-size: 42px; line-height: 1.05; }

/* ── Delta pill ───────────────────────────────────────────────────────── */
.nx-delta {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  height: 20px;
  padding: 0 7px;
  border-radius: 999px;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.nx-delta--up   { color: var(--nx-up);   background: var(--nx-up-fill); }
.nx-delta--down { color: var(--nx-down); background: var(--nx-down-fill); }
.nx-delta--flat { color: var(--text2);   background: var(--nx-hover-fill); }
.nx-delta__vs { font-size: 11px; color: var(--text2); white-space: nowrap; }

/* ── Chart card ───────────────────────────────────────────────────────── */
.nx-chartcard {
  box-sizing: border-box;
  min-width: 0;
  padding: 16px 18px;
  border-radius: 12px;
  border: 1px solid var(--nx-line);
  background: var(--card);
  font-family: var(--font-body);
  color: var(--text);
}
.nx-chartcard__head { display: flex; align-items: center; gap: 12px; margin: 0 0 10px; }
.nx-chartcard__title { margin: 0; font-size: 14px; font-weight: 700; line-height: 1.2; color: var(--text); }
.nx-chartcard__plot { position: relative; height: var(--nx-chart-h, 300px); }
.nx-chartcard__empty { padding: 28px 16px; text-align: center; font-size: 13px; color: var(--text2); }

/* ── Team card ────────────────────────────────────────────────────────── */
.nx-teamcard {
  box-sizing: border-box;
  min-width: 0;
  padding: 16px 18px;
  border-radius: 12px;
  border: 1px solid var(--nx-line);
  background: var(--card);
  font-family: var(--font-body);
  color: var(--text);
  cursor: pointer;
  transition: border-color 120ms ease, background-color 120ms ease;
}
.nx-teamcard:hover { border-color: var(--nx-line-strong); background-image: linear-gradient(var(--nx-hover-fill), var(--nx-hover-fill)); }
.nx-teamcard:focus-visible { outline: 2px solid var(--nx-focus); outline-offset: 2px; }
.nx-teamcard--dashed { border-style: dashed; }
.nx-teamcard__head { display: flex; align-items: baseline; gap: 10px; min-width: 0; }
.nx-teamcard__name { margin: 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 15px; font-weight: 700; line-height: 1.2; color: var(--text); }
.nx-teamcard__lead { flex-shrink: 0; font-size: 12px; color: var(--text2); white-space: nowrap; }
.nx-teamcard__count {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  height: 20px;
  margin-left: auto;
  padding: 0 8px;
  border-radius: 999px;
  background: var(--nx-press-fill);
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  color: var(--text2);
  white-space: nowrap;
}
.nx-teamcard__vol { margin-top: 10px; font-size: 22px; font-weight: 800; line-height: 1.1; font-variant-numeric: tabular-nums; color: var(--text); }
.nx-teamcard__units { font-size: 12px; font-weight: 500; color: var(--text2); }
.nx-teamcard__foot { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.nx-teamcard__mini {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 6px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--nx-line);
}
.nx-teamcard__mk { font-size: 10px; font-weight: 700; letter-spacing: .08em; line-height: 1.2; text-transform: uppercase; color: var(--text2); }
.nx-teamcard__mv { margin-top: 2px; font-size: 14px; font-weight: 700; line-height: 1.2; font-variant-numeric: tabular-nums; color: var(--text); }
.nx-teamcard__mini .nx-delta { height: 16px; margin-top: 3px; padding: 0 5px; font-size: 10px; }
.nx-teamcard__mini .nx-delta__vs { display: none; }

/* ── Month stepper ────────────────────────────────────────────────────────
   <div class="nx-monthstep"><button class="nx-btn nx-btn--secondary nx-btn--icon nx-btn--sm nx-monthstep__prev">chevron-right</button>
     <span class="nx-monthstep__label">Oct 2026</span><button class="… nx-btn--icon">chevron-right</button></div> */
.nx-monthstep { display: inline-flex; align-items: center; gap: 8px; font-family: var(--font-body); }
.nx-monthstep__label { min-width: 104px; text-align: center; font-size: 16px; font-weight: 700; line-height: 1.2; font-variant-numeric: tabular-nums; color: var(--text); white-space: nowrap; }
.nx-monthstep__prev svg { transform: scaleX(-1); }

/* ═══════════════════════════════════════════════════════════════════════════
   Batch 12b (leader Pipeline + MCR) additions, all token-driven, dark + light.
     --nx-urgent / --nx-hold / --nx-info   state colors (text) + their -fill and -line tints
     .nx-status--neutral / --info / --warn / --danger / --ok
                           tone modifiers for the 22px .nx-status pill (its dot follows the text color)
     .nx-stagestrip        a left → right row of .nx-stage cards joined by chevrons (a flow)
     .nx-stage             a clickable stage card (a <button>): __label (11px caps) · __count (22/800 tabular) ·
                           __sub (12px muted); .is-active = the teal tint of the active chip; `position:relative`
     .nx-attn-row / .nx-attn
                           "needs attention" cards: the .nx-stage grammar outside the flow (no chevrons), tinted by
                           --urgent (red) / --hold (amber) / --neutral; the count takes the tone; .is-active fills it
     .nx-rail__item--status
                           a two-line rail row: the label (+ an optional __meta like "current") over an .nx-status
                           pill that may wrap; .is-active as every rail row
     .nx-table-more        the load-more footer inside an .nx-table-wrap: one centered --secondary --sm button
   ═══════════════════════════════════════════════════════════════════════════ */
:root {
  --nx-urgent: #F87171;
  --nx-urgent-fill: rgba(248,113,113,.10);
  --nx-urgent-line: rgba(248,113,113,.40);
  --nx-hold: #FBBF24;
  --nx-hold-fill: rgba(251,191,36,.10);
  --nx-hold-line: rgba(251,191,36,.40);
  --nx-info: #2DD4BF;
  --nx-info-fill: rgba(45,212,191,.14);
}
body.light-mode {
  --nx-urgent: #B91C1C;
  --nx-urgent-fill: rgba(185,28,28,.07);
  --nx-urgent-line: rgba(185,28,28,.35);
  --nx-hold: #B45309;
  --nx-hold-fill: rgba(180,83,9,.08);
  --nx-hold-line: rgba(180,83,9,.35);
  --nx-info: #0F766E;
  --nx-info-fill: rgba(15,118,110,.10);
}

/* ── Status pill tones ────────────────────────────────────────────────── */
.nx-status--neutral { background: var(--nx-hover-fill); color: var(--text2); }
.nx-status--info    { background: var(--nx-info-fill);   color: var(--nx-info); }
.nx-status--warn    { background: var(--nx-hold-fill);   color: var(--nx-hold); }
.nx-status--danger  { background: var(--nx-urgent-fill); color: var(--nx-urgent); }
.nx-status--ok      { background: var(--nx-up-fill);     color: var(--nx-up); }

/* ── Stage strip ──────────────────────────────────────────────────────────
   <div class="nx-stagestrip"><button class="nx-stage is-active"><span class="nx-stage__label">1 · Projected</span>
     <span class="nx-stage__count">3</span><span class="nx-stage__sub">$930K · avg 5d</span></button>…</div> */
.nx-stagestrip { display: flex; align-items: stretch; gap: 20px; overflow-x: auto; padding: 2px 2px 8px; }
.nx-stage,
.nx-attn {
  position: relative;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  min-width: 0;
  padding: 12px 14px;
  border-radius: 12px;
  border: 1px solid var(--nx-line);
  background: var(--card);
  font-family: var(--font-body);
  text-align: left;
  color: var(--text);
  cursor: pointer;
  transition: border-color 120ms ease, background-color 120ms ease;
}
.nx-stage { flex: 1 1 0; min-width: 128px; }
.nx-stage:hover,
.nx-attn:hover { border-color: var(--nx-line-strong); background-image: linear-gradient(var(--nx-hover-fill), var(--nx-hover-fill)); }
.nx-stage:focus-visible,
.nx-attn:focus-visible { outline: 2px solid var(--nx-focus); outline-offset: 2px; }
.nx-stage.is-active { background: var(--nx-active-fill); border-color: var(--nx-active-line); }
.nx-stagestrip > .nx-stage:not(:last-child)::after {
  content: '';
  position: absolute;
  top: 50%;
  right: -14px;
  width: 7px;
  height: 7px;
  border-top: 1.5px solid var(--text2);
  border-right: 1.5px solid var(--text2);
  transform: translateY(-50%) rotate(45deg);
  pointer-events: none;
}
.nx-stage__label { font-size: 11px; font-weight: 700; letter-spacing: .08em; line-height: 1.2; text-transform: uppercase; color: var(--text2); white-space: nowrap; }
.nx-stage__count { font-size: 22px; font-weight: 800; line-height: 1.1; font-variant-numeric: tabular-nums; color: var(--text); }
.nx-stage__sub { font-size: 12px; line-height: 1.2; color: var(--text2); white-space: nowrap; }
body.light-mode button.nx-stage,
body.light-mode button.nx-attn { color: var(--text); }

/* ── Attention cards ──────────────────────────────────────────────────── */
.nx-attn-row { display: flex; gap: 12px; flex-wrap: wrap; }
.nx-attn { flex: 0 1 220px; min-width: 170px; }
.nx-attn--urgent { border-color: var(--nx-urgent-line); }
.nx-attn--urgent .nx-stage__count { color: var(--nx-urgent); }
.nx-attn--urgent.is-active { background: var(--nx-urgent-fill); border-color: var(--nx-urgent); }
.nx-attn--hold { border-color: var(--nx-hold-line); }
.nx-attn--hold .nx-stage__count { color: var(--nx-hold); }
.nx-attn--hold.is-active { background: var(--nx-hold-fill); border-color: var(--nx-hold); }
.nx-attn--neutral.is-active { background: var(--nx-active-fill); border-color: var(--nx-active-line); }

/* ── Rail row with a status pill ──────────────────────────────────────────
   <button class="nx-rail__item nx-rail__item--status"><span class="nx-rail__label">2026 Q3<span class="nx-rail__meta">current</span></span>
     <span class="nx-status nx-status--ok">Finalized 2026-10-02</span></button> */
.nx-rail__item--status { flex-direction: column; align-items: flex-start; justify-content: center; gap: 6px; height: auto; min-height: 52px; padding: 8px 12px; white-space: normal; }
.nx-rail__label { display: flex; align-items: baseline; gap: 8px; width: 100%; }
.nx-rail__meta { margin-left: auto; font-size: 11px; font-weight: 600; color: var(--text2); }
.nx-rail__item--status .nx-status { max-width: 100%; height: auto; min-height: 22px; padding: 4px 9px; line-height: 1.25; white-space: normal; }

/* ── Load-more footer (inside .nx-table-wrap, after the table) ────────── */
.nx-table-more { position: sticky; left: 0; display: flex; justify-content: center; padding: 12px; border-top: 1px solid var(--nx-line); }

/* ═══════════════════════════════════════════════════════════════════════════
   Batch 13a (Admin shell) additions, all token-driven, dark + light.
     .nx-card__meta        a wrapping row of 12px muted facts under a card title ("12 events · First … · production");
                           each fact is a <span>; an inline glyph inside one sits at 14px
     .nx-modal-backdrop    a fixed full-window scrim (z 10000) centering one .nx-modal; the module removes it (or hides
                           it) on close — a backdrop click closes when the module wires it
     .nx-modal             the dialog panel: var(--card), 1px line, radius 14, 560 wide (--wide = 760), max 85vh
       __head              title block left (__title 16/700 + an optional 12px __sub), an --ghost --icon close right
       __body              the one scroller inside the dialog
       __foot              actions right on a top rule: Cancel / Close (--ghost or --secondary), then at most one --primary
   <div class="nx-modal-backdrop"><div class="nx-modal" role="dialog" aria-modal="true" aria-labelledby="…">
     <div class="nx-modal__head"><div><h3 class="nx-modal__title" id="…">Title</h3><div class="nx-modal__sub">…</div></div>
       <button class="nx-btn nx-btn--ghost nx-btn--icon" aria-label="Close"><span class="nx-glyph-x">×</span></button></div>
     <div class="nx-modal__body">…</div>
     <div class="nx-modal__foot"><button class="nx-btn nx-btn--ghost">Cancel</button><button class="nx-btn nx-btn--primary">Save</button></div>
   </div></div>
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Card meta line ───────────────────────────────────────────────────── */
.nx-card__meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; margin-top: 6px; font-size: 12px; line-height: 1.4; color: var(--text2); }
.nx-card__meta > span { display: inline-flex; align-items: center; gap: 4px; min-width: 0; overflow-wrap: anywhere; }
.nx-card__meta svg { width: 14px; height: 14px; flex-shrink: 0; }

/* ── Modal ────────────────────────────────────────────────────────────── */
.nx-modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 10000;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(0,0,0,.55);
}
body.light-mode .nx-modal-backdrop { background: rgba(15,23,42,.35); }
.nx-modal {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  width: 560px;
  max-width: 100%;
  max-height: 85vh;
  border: 1px solid var(--nx-line);
  border-radius: 14px;
  background: var(--card);
  box-shadow: 0 16px 48px rgba(0,0,0,.35);
  font-family: var(--font-body);
  color: var(--text);
}
.nx-modal--wide { width: 760px; }
.nx-modal__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; padding: 20px 24px 12px; }
.nx-modal__title { margin: 0; font-size: 16px; font-weight: 700; line-height: 1.3; color: var(--text); }
.nx-modal__sub { margin-top: 2px; font-size: 12px; color: var(--text2); }
.nx-modal__body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 4px 24px 16px; }
.nx-modal__foot { display: flex; justify-content: flex-end; align-items: center; gap: 8px; padding: 16px 24px; border-top: 1px solid var(--nx-line); }

/* ═══════════════════════════════════════════════════════════════════════════
   Batch 13b (Admin › Users + Tickets) additions, all token-driven, dark + light.
     --nx-row-detail       the slightly darker ground of an expanded row and its detail row
     .nx-table__expand     the first cell of an expandable row: an --ghost --icon --sm button .nx-table__chevron
                           (chevron-right glyph, aria-expanded + aria-controls) that turns 90° when open
     tr.is-expanded        the open row (its bottom rule drops so it reads as one block with its detail row)
     tr.nx-table__detail   the detail row under it: one cell spanning every column, auto height, wrapping text, indented
                           past the chevron column; never tinted by hover
       <tr class="is-expanded"><td class="nx-table__expand"><button class="nx-btn nx-btn--ghost nx-btn--icon nx-btn--sm
         nx-table__chevron" aria-expanded="true" aria-controls="d1" aria-label="Show details">›</button></td>…</tr>
       <tr class="nx-table__detail" id="d1"><td colspan="N">…</td></tr>
     .nx-banner--warn      the banner in the amber hold tone (a data or service warning), icon in the same tone
     .nx-btn--danger-label a secondary button whose label reads in the danger text color (a consequential action that
                           is not the destructive one on screen, e.g. Suspend next to Delete)
   ═══════════════════════════════════════════════════════════════════════════ */
:root { --nx-row-detail: rgba(0,0,0,.18); }
body.light-mode { --nx-row-detail: rgba(15,23,42,.035); }

/* ── Expandable table row ─────────────────────────────────────────────── */
.nx-table .nx-table__expand { width: 48px; padding-right: 0; }
.nx-table__chevron > svg { transition: transform 120ms ease; }
.nx-table__chevron[aria-expanded="true"] > svg { transform: rotate(90deg); }
.nx-table > tbody > tr.is-expanded,
.nx-table > tbody > tr.is-expanded:hover { --nx-row-tint: var(--nx-row-detail); }
.nx-table > tbody > tr.is-expanded > td { border-bottom-color: transparent; }
.nx-table > tbody > tr.nx-table__detail,
.nx-table > tbody > tr.nx-table__detail:hover { --nx-row-tint: var(--nx-row-detail); --nx-row-wash: transparent; }
.nx-table > tbody > tr.nx-table__detail > td { height: auto; padding: 4px 16px 16px 60px; white-space: normal; overflow: visible; text-overflow: clip; cursor: default; }
@media (prefers-reduced-motion: reduce) { .nx-table__chevron > svg { transition: none; } }

/* ── Warning banner ───────────────────────────────────────────────────── */
.nx-banner--warn { border-color: var(--nx-hold-line); background: var(--nx-hold-fill); }
.nx-banner--warn .nx-banner__icon { color: var(--nx-hold); }

/* ── Danger-label secondary button ────────────────────────────────────── */
.nx-btn.nx-btn--danger-label,
.nx-btn.nx-btn--danger-label:hover,
body.light-mode button.nx-btn--danger-label { color: var(--nx-danger-text); }

/* ── Editing state (batch 15a): the form behind this button holds an edit in progress ── */
.nx-btn.is-editing,
.nx-btn.is-editing:hover,
.nx-btn.is-editing:active { background: var(--nx-hold-fill); border-color: var(--nx-hold-line); color: var(--nx-hold); }
body.light-mode button.nx-btn.is-editing { color: var(--nx-hold); }

/* ═══════════════════════════════════════════════════════════════════════════
   Batch 13c (Admin › Updates, Flyers, Recaps, Polls, SMS Broadcast) additions, all token-driven, dark + light.
     --nx-meter-track      the empty part of a meter bar (a faint line in both themes)
     --nx-paper            the white page of an inline document preview (an email is white in both themes)
     .nx-checklist         a searchable multi-select list: an .nx-search over a bordered __list of __row labels, each a
                           real checkbox + __label (600) + an optional __meta (muted) + __aside (right, muted); the
                           checked row is tinted; __empty = the centered "no matches" line; __count = the live
                           "N selected" line under the list
       <div class="nx-checklist"><label class="nx-search">svg<input …></label>
         <div class="nx-checklist__list"><label class="nx-checklist__row"><input type="checkbox">
           <span class="nx-checklist__label">Sam Ortiz</span><span class="nx-checklist__meta">Harness</span>
           <span class="nx-checklist__aside">sam@example.com</span></label></div>
         <div class="nx-checklist__count">1 user selected</div></div>
     .nx-optrow            one repeatable option: a 24px color __swatch (an <input type="color"> or a static <span>),
                           an .nx-field--sm, then an --ghost --icon --sm remove (aria-label); __sub = an optional
                           second line indented past the swatch (a description field); rows stack 8px apart
     .nx-meter             one labelled bar: __label (+ __desc under it) right-aligned in a 120px column, the __track
                           with a __fill whose color is the data's own (--nx-meter-color, else the action teal), and
                           a __value ("2 (40%)") on the right
     .nx-charcount         the right-aligned 11px character-count hint under a field
     .nx-field--code       a monospace text area (HTML source): 12px, line-height 1.5, no wrapping of long lines;
                           15e: on an <input> (`.nx-field--code > input` / bare `input.nx-field--code`) it is the one-time
                           code box (MFA overlay, wizard 2FA): monospace 20px, centered, 6px tracking, tabular digits
     .nx-preview-frame     an inline frame showing a rendered document (an email): 1px line, radius 10, on --nx-paper;
                           its <iframe> fills the width at 500px
   ═══════════════════════════════════════════════════════════════════════════ */
:root {
  --nx-meter-track: rgba(255,255,255,.06);
  --nx-paper: #fff;
}
body.light-mode {
  --nx-meter-track: rgba(0,0,0,.07);
}

/* ── Checkbox / radio (.nx-check) ─────────────────────────────────────────
   The one checkbox: a real input drawn by CSS, so it follows the theme tokens. A checklist row's bare
   box takes the same rules (no class needed in that markup). */
.nx-check,
.nx-checklist__row > input[type="checkbox"] {
  -webkit-appearance: none;
  appearance: none;
  box-sizing: border-box;
  display: inline-block;
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  margin: 0;
  border: 1.5px solid var(--nx-field-line);
  border-radius: 5px;
  background: var(--nx-field-fill) center / 12px 12px no-repeat;
  vertical-align: middle;
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease;
}
.nx-check:hover:not(:disabled),
.nx-checklist__row > input[type="checkbox"]:hover:not(:disabled) { border-color: var(--nx-action); }
.nx-check:checked,
.nx-checklist__row > input[type="checkbox"]:checked {
  border-color: var(--nx-action);
  background-color: var(--nx-action);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E");
}
.nx-check--radio { border-radius: 50%; }
.nx-check--radio:checked { background-image: none; box-shadow: inset 0 0 0 4px var(--nx-field-fill); }
.nx-check:focus-visible,
.nx-checklist__row > input[type="checkbox"]:focus-visible { outline: 2px solid var(--nx-focus); outline-offset: 2px; }
.nx-check:disabled,
.nx-checklist__row > input[type="checkbox"]:disabled { opacity: .4; cursor: default; }
.nx-check-label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.3;
  color: var(--text);
  cursor: pointer;
}
.nx-check-label:has(> .nx-check:disabled) { opacity: .45; cursor: default; }
.nx-check-label > .nx-check:disabled { opacity: 1; }

/* ── Pick-one card (.nx-choice, batch 15b) ────────────────────────────────
   A radio drawn as a card: title + one line. The checked card wears the active-chip tint (never solid). */
.nx-choice {
  position: relative;
  display: block;
  box-sizing: border-box;
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid var(--nx-line-strong);
  background: var(--nx-field-fill);
  font-family: var(--font-body);
  text-transform: none;
  letter-spacing: normal;
  cursor: pointer;
  transition: border-color 120ms ease, background-color 120ms ease;
}
.nx-choice > input { position: absolute; width: 1px; height: 1px; margin: 0; opacity: 0; pointer-events: none; }
.nx-choice:hover { border-color: var(--nx-action); }
.nx-choice:has(> input:checked) { background: var(--nx-active-fill); border-color: var(--nx-active-line); }
.nx-choice:has(> input:focus-visible) { outline: 2px solid var(--nx-focus); outline-offset: 2px; }
.nx-choice__title { display: block; margin: 0 0 3px; font-family: var(--font-body); font-size: 13px; font-weight: 700; line-height: 1.3; letter-spacing: normal; text-transform: none; color: var(--text); }
.nx-choice:has(> input:checked) .nx-choice__title { color: var(--nx-chip-active-text); }
.nx-choice__desc { display: block; font-family: var(--font-body); font-size: 12px; font-weight: 400; line-height: 1.4; letter-spacing: normal; text-transform: none; color: var(--text2); }

/* ── Searchable checklist ─────────────────────────────────────────────── */
.nx-checklist { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.nx-checklist > .nx-search { width: 100%; }
.nx-checklist__list {
  box-sizing: border-box;
  max-height: 240px;
  overflow-y: auto;
  border: 1px solid var(--nx-field-line);
  border-radius: 10px;
  background: var(--nx-field-fill);
}
.nx-checklist__row {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 40px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--nx-line);
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
  user-select: none;
}
.nx-checklist__row:last-child { border-bottom: 0; }
.nx-checklist__row:hover { background: var(--nx-hover-fill); }
.nx-checklist__row:has(> input:checked) { background: var(--nx-info-fill); }
.nx-checklist__label { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.nx-checklist__meta { font-size: 12px; color: var(--text2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.nx-checklist__aside { margin-left: auto; padding-left: 8px; font-size: 12px; color: var(--text2); white-space: nowrap; }
.nx-checklist__empty { padding: 12px; text-align: center; font-size: 13px; color: var(--text2); }
.nx-checklist__count { font-size: 12px; color: var(--text2); }

/* ── Repeatable option row ────────────────────────────────────────────── */
.nx-optrow { display: flex; flex-direction: column; gap: 6px; }
.nx-optrow + .nx-optrow { margin-top: 8px; }
.nx-optrow__main { display: flex; align-items: center; gap: 8px; min-width: 0; }
.nx-optrow__main > .nx-field { flex: 1 1 auto; }
.nx-optrow__swatch {
  box-sizing: border-box;
  display: inline-block;
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  padding: 0;
  border: 1px solid var(--nx-line-strong);
  border-radius: 6px;
  background: none;
  cursor: pointer;
}
span.nx-optrow__swatch { cursor: default; }
input.nx-optrow__swatch::-webkit-color-swatch-wrapper { padding: 2px; }
input.nx-optrow__swatch::-webkit-color-swatch { border: 0; border-radius: 4px; }
.nx-optrow__text { font-size: 13px; font-weight: 600; color: var(--text); }
.nx-optrow__sub { padding-left: 32px; }

/* ── Meter bar ────────────────────────────────────────────────────────── */
.nx-meter { display: flex; align-items: center; gap: 10px; font-family: var(--font-body); }
.nx-meter + .nx-meter { margin-top: 6px; }
.nx-meter__label { flex: 0 0 120px; min-width: 0; text-align: right; font-size: 12px; font-weight: 600; line-height: 1.3; color: var(--text2); overflow-wrap: anywhere; }
.nx-meter__desc { display: block; margin-top: 1px; font-size: 11px; font-weight: 400; color: var(--text2); opacity: .8; }
.nx-meter__track { position: relative; flex: 1 1 auto; height: 18px; border-radius: 6px; background: var(--nx-meter-track); overflow: hidden; }
.nx-meter__fill { height: 100%; border-radius: 6px; background: var(--nx-meter-color, var(--nx-action)); transition: width 300ms ease; }
.nx-meter__value { flex: 0 0 72px; font-size: 12px; color: var(--text2); font-variant-numeric: tabular-nums; }
@media (prefers-reduced-motion: reduce) { .nx-meter__fill { transition: none; } }

/* ── Character-count hint ─────────────────────────────────────────────── */
.nx-charcount { margin-top: 4px; text-align: right; font-size: 11px; color: var(--text2); font-variant-numeric: tabular-nums; }

/* ── Monospace code field ─────────────────────────────────────────────── */
.nx-field--code > textarea { font-family: 'Fira Code', ui-monospace, SFMono-Regular, Consolas, monospace; font-size: 12px; line-height: 1.5; white-space: pre; overflow-wrap: normal; overflow-x: auto; }
.nx-field--code > input,
input.nx-field--code { font-family: 'Fira Code', ui-monospace, SFMono-Regular, Consolas, monospace; font-size: 20px; letter-spacing: 6px; text-align: center; font-variant-numeric: tabular-nums; }   /* 15e: the one-time code box */

/* ── Inline preview frame ─────────────────────────────────────────────── */
.nx-preview-frame { box-sizing: border-box; border: 1px solid var(--nx-line-strong); border-radius: 10px; overflow: hidden; background: var(--nx-paper); }
.nx-preview-frame > iframe { display: block; width: 100%; height: 500px; border: 0; background: var(--nx-paper); }

/* ═══════════════════════════════════════════════════════════════════════════
   Batch 13d (Admin › Companies + Integrations) additions, all token-driven, dark + light.
     .nx-tabbar            a tab row inside a body (a page's own sections, under the module header): a 44px bar on a 1px
                           bottom line holding shell tabs (.nx-tab, role=tab), 28 apart; the active tab's 2px underline
                           sits on the line (the .nx-drawer__tabs recipe, outside a drawer). No scroller: an overflow
                           clip would cut the underline off the line. 20px below it before the body content.
       <nav class="nx-tabbar" role="tablist" aria-label="…"><button type="button" class="nx-tab is-active" role="tab"
         aria-selected="true">Overview</button><button type="button" class="nx-tab" role="tab" aria-selected="false">Users</button></nav>
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Body tab row ─────────────────────────────────────────────────────── */
.nx-tabbar {
  box-sizing: border-box;
  display: flex;
  align-items: stretch;
  gap: 28px;
  height: 44px;
  margin: 0 0 20px;
  border-bottom: 1px solid var(--nx-line);
}
.nx-tabbar > .nx-tab { flex-shrink: 0; }

/* ═══════════════════════════════════════════════════════════════════════════
   Batch 14 (Booking page builder) additions, all token-driven, dark + light.
     .nx-header__status    a 12px muted status line just left of the action cluster (Loading…, Saved); it shrinks and
                           ellipsizes before the cluster does. Set its text with textContent.
     .nx-sheet__back       (existing) also serves any full-screen fixed root that holds a header B (the builder's back circle)
     .nx-rail__item--desc  a two-line rail row: __text holds __title (14/600) over __desc (12 muted, wraps); __trail is a
                           glyph at the row's right end (plus = add, check = already placed)
       <button type="button" class="nx-rail__item nx-rail__item--desc"><span class="nx-rail__text">
         <span class="nx-rail__title">FAQ</span><span class="nx-rail__desc">Expandable questions</span></span>
         <span class="nx-rail__trail">svg</span></button>
     .nx-rail__item:disabled / [aria-disabled="true"]   a row that cannot be used right now: opacity .4, no pointer
     .nx-aside__title      the title block inside an .nx-aside__head: __name (15/700, ellipsized) over __meta (12 muted)
     .nx-aside__body       the aside's scroller under its head (inside an .nx-aside--stack), 20px gutter
     .nx-aside__empty      the one muted line an aside shows when nothing is selected
     --nx-well             the recessed ground around an artboard (a page preview on a canvas)
     --nx-canvas-*         editor chrome drawn OVER a rendered page (outline dashes, the halo pair that keeps a line
                           readable on light and dark pages): constant in both app themes, because the page under them
                           carries its own theme
   ═══════════════════════════════════════════════════════════════════════════ */
:root {
  --nx-well: rgba(0,0,0,.25);
  --nx-canvas-dash: rgba(100,116,139,.55);
  --nx-canvas-lock: rgba(148,163,184,.55);
  --nx-canvas-halo-in: rgba(10,13,20,.5);
  --nx-canvas-halo-out: rgba(255,255,255,.65);
}
body.light-mode {
  --nx-well: rgba(15,23,42,.06);
}

/* ── Header status line ───────────────────────────────────────────────── */
.nx-header__status {
  align-self: center;
  flex: 0 1 auto;
  min-width: 0;
  font-size: 12px;
  font-weight: 500;
  line-height: 1.2;
  color: var(--text2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.nx-header__status:empty { display: none; }

/* ── Two-line rail row + disabled row ─────────────────────────────────── */
.nx-rail__item--desc { height: auto; min-height: 56px; padding: 9px 12px; white-space: normal; }
.nx-rail__text { display: flex; flex-direction: column; gap: 3px; flex: 1 1 auto; min-width: 0; }
.nx-rail__title { font-size: 14px; font-weight: 600; line-height: 1.25; }
.nx-rail__desc { font-size: 12px; font-weight: 500; line-height: 1.35; color: var(--text2); }
.nx-rail__trail { display: inline-flex; flex-shrink: 0; margin-left: auto; line-height: 0; color: var(--text2); }
.nx-rail__trail > svg { width: 18px; height: 18px; display: block; }
.nx-rail__item:disabled,
.nx-rail__item[aria-disabled="true"] { opacity: .4; cursor: default; pointer-events: none; }

/* ── Aside head title, body scroller, empty line ──────────────────────── */
.nx-aside__title { display: flex; flex-direction: column; gap: 3px; flex: 1 1 auto; min-width: 0; }
.nx-aside__name { font-size: 15px; font-weight: 700; line-height: 1.2; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nx-aside__meta { font-size: 12px; font-weight: 500; line-height: 1.2; color: var(--text2); font-variant-numeric: tabular-nums; }
.nx-aside__body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 20px; }
.nx-aside__empty { padding: 20px; font-size: 13px; line-height: 1.5; color: var(--text2); }
