/* ==========================================================================
   style design system — v1.0 (standalone, no framework)
   --------------------------------------------------------------------------
   §0  Reset
   §1  Design tokens (light only — see tokens.css)
   §2  Base styles
   §3  Layout primitives
   §4  Components
   §5  Data table + DataTables vendor skin
   §6  Utilities
   ========================================================================== */

/* ==========================================================================
   §0 RESET
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
/* The line above also strips the UA's `dialog { margin: auto }`, which is what
   centres a modal in the viewport — without it every <dialog> in the app
   opened pinned to the top-left corner. Put back explicitly. */
dialog { margin: auto; }
img, svg, video { display: block; max-width: 100%; }
input, button, textarea, select { font: inherit; color: inherit; }
p, h1, h2, h3, h4, h5, h6 { overflow-wrap: break-word; }
[hidden] { display: none !important; }
/* Present to assistive tech, absent on screen. For controls that carry their
   whole meaning in a glyph — the platform badges in the profiles table. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ==========================================================================
   §1 DESIGN TOKENS
   ========================================================================== */
:root {
  /* Typography — see tokens.css. The size scale stays dense (13-14px body)
     rather than adopting the design's 16px: that scale is written for a
     marketing page, and raising body type would reflow every table in the app.
     What is adopted is the part that carries the character — the fractional
     weights and the tracking. */
  --font-sans: var(--font-saans);
  --font-heading: var(--font-sans);   /* headings default to the body font */
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --text-xs: 0.75rem;      /* 12px — table meta, badges */
  --text-sm: 0.8125rem;    /* 13px — table cells, controls */
  --text-base: 0.875rem;   /* 14px — body (data-dense default) */
  --text-lg: 1rem;
  --text-xl: 1.25rem;
  --text-2xl: 1.5rem;
  --leading: 1.5;
  --weight-body: var(--font-weight-regular);
  --weight-ui: var(--font-weight-w440);      /* nav, labels, buttons */
  --weight-emphasis: var(--font-weight-w456); /* table primary values */
  --weight-heading: var(--font-weight-semibold);
  --tracking-heading: var(--tracking-heading-lg);
  --tracking-ui: var(--tracking-body);   /* +0.013em at small sizes */

  /* Spacing unit — all component padding/margins are multiples of this */
  --space: 0.25rem;
  /* One vertical rhythm for stacked filter rows, wherever they appear. Set
     here beside --space because it is spacing, and shared because three pages
     each spelling it out is three chances to drift — which is what happened. */
  --filter-row-gap: calc(var(--space) * 4);

  /* Neutrals — mapped onto the design primitives in tokens.css. The names
     here stay put on purpose: 109 component rules consume them, so a palette
     change is this block, not a rename across the file. */
  --color-surface: var(--color-pure-canvas);  /* page is white, not off-white */
  --color-card: var(--color-pure-canvas);
  --color-card-hover: var(--color-mist);
  --color-inset: var(--color-mist);            /* wells, table header, hover */
  --color-border: var(--color-fog);
  --color-border-strong: var(--color-slate-shadow);
  --color-heading: var(--color-midnight-ink);
  --color-text: var(--color-midnight-ink);
  --color-muted: var(--color-graphite);
  --color-faint: var(--color-ash);

  /* Brand — the CTA fill is near-black, not a hue. Links included: the design
     is explicit that there is no blue for links. */
  --color-primary: var(--color-midnight-ink);
  --color-primary-hover: #2e2e2e;
  --color-on-primary: var(--color-pure-canvas);
  --color-link: var(--color-midnight-ink);

  /* Semantic — achromatic except danger.
     The design bans chromatic accent outright, and success/warning/info follow
     that: they differentiate by border, weight and icon instead of hue. Danger
     keeps its red as one deliberate exception, because a delete button and a
     validation error are the two places where losing colour costs more than
     the consistency is worth. */
  --color-success: var(--color-midnight-ink);
  --color-danger: #dc2626;
  --color-warning: var(--color-midnight-ink);
  --color-info: var(--color-graphite);
  /* Soft tints derive from the base color — they adapt to dark mode free */
  --soft-mix: 12%;
  --color-primary-soft: color-mix(in oklab, var(--color-primary) var(--soft-mix), transparent);
  --color-success-soft: color-mix(in oklab, var(--color-success) var(--soft-mix), transparent);
  --color-danger-soft:  color-mix(in oklab, var(--color-danger)  var(--soft-mix), transparent);
  --color-warning-soft: color-mix(in oklab, var(--color-warning) var(--soft-mix), transparent);
  --color-info-soft:    color-mix(in oklab, var(--color-info)    var(--soft-mix), transparent);
  --color-neutral-soft: color-mix(in oklab, var(--color-muted)   var(--soft-mix), transparent);
  /* Trial reels are the third place hue survives the achromatic rule, after
     danger and the trend arrows. A trial is a temporary distribution state, so
     a reader scanning a table needs to spot it without reading every badge —
     which is the same argument the delete button won. */
  --color-trial-soft:   color-mix(in oklab, var(--color-trial)   var(--soft-mix), transparent);
  --color-record-soft:  color-mix(in oklab, var(--color-record)  var(--soft-mix), transparent);

  /* Shape — a closed vocabulary. Anything you can click is a pill; static
     containers are 16px, floating ones 24px, inline badges 8px. --radius-md is
     the one doing the visible work: it is what buttons and inputs use, so
     pointing it at the pill turns every control in the app into a pill. */
  --radius-sm: var(--radius-badge);        /* 8px — inline badges, tags */
  --radius-md: var(--radius-pill-full);    /* buttons, inputs, chips */
  --radius-lg: var(--radius-card);         /* 16px — cards, tables, images */
  --radius-xl: var(--radius-container);    /* 24px — dialogs, dropdowns */
  --radius-pill: var(--radius-pill-full);

  /* Elevation — layered, soft, low-contrast */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
  --shadow-md: var(--shadow-float);   /* dropdowns/dialogs only — never cards */
  --shadow-lg: var(--shadow-float);
  --focus-ring: 0 0 0 3px color-mix(in oklab, var(--color-primary) 25%, transparent);

  /* Unused since the restyle — the design is explicit that surfaces are flat.
     Kept only so any stray consumer resolves rather than breaking. */
  --gradient-subtle: linear-gradient(to bottom, var(--color-card), color-mix(in oklab, var(--color-inset) 55%, var(--color-card)));

  /* Motion */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --speed: 0.15s;

  /* Z-scale */
  --z-sticky: 10;
  --z-dropdown: 1000;
  --z-modal: 1050;
  --z-tooltip: 1080;

  /* Controls */
  --control-h: 2.25rem;       /* 36px default control height */
  --control-h-sm: 1.875rem;   /* 30px */

  /* Table density — .table-compact overrides these */
  --table-pad-y: calc(var(--space) * 2.5);
  --table-pad-x: calc(var(--space) * 3);

  color-scheme: light;
}

/* ==========================================================================
   §2 BASE
   ========================================================================== */
html { font-family: var(--font-sans); }

body {
  background: var(--color-surface);
  color: var(--color-text);
  font-size: var(--text-base);
  font-weight: var(--weight-body);
  line-height: var(--leading);
  letter-spacing: var(--tracking-ui);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  color: var(--color-heading);
  font-family: var(--font-heading);
  font-weight: var(--weight-heading);
  letter-spacing: var(--tracking-heading);
  line-height: 1.25;
}
.page-title, .card-title, .dialog-title, .stat-value { font-family: var(--font-heading); }
h1 { font-size: var(--text-2xl); }
h2 { font-size: var(--text-xl); }
h3 { font-size: var(--text-lg); }
h4 { font-size: var(--text-base); }

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

code, kbd, pre { font-family: var(--font-mono); font-size: 0.9em; }
code {
  background: var(--color-inset);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 0.1em 0.35em;
}
pre {
  background: var(--color-inset);
  border: 1px solid var(--color-border);
  /* A container, so 16px — not the pill --radius-md carries. A multi-line
     code block with a 9999px radius loses its first and last lines to the
     curve. */
  border-radius: var(--radius-lg);
  padding: calc(var(--space) * 4);
  overflow-x: auto;
}
pre code { background: none; border: 0; padding: 0; }

kbd {
  background: var(--color-inset);
  border: 1px solid var(--color-border-strong);
  border-bottom-width: 2px;
  border-radius: var(--radius-sm);
  padding: 0.1em 0.45em;
  font-size: var(--text-xs);
  color: var(--color-heading);
}

hr { border: 0; border-top: 1px solid var(--color-border); }

:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius-sm); }

::placeholder { color: var(--color-faint); }

/* ==========================================================================
   §3 LAYOUT PRIMITIVES
   ========================================================================== */
.container { max-width: 80rem; margin-inline: auto; padding-inline: calc(var(--space) * 6); }
.container-wide { max-width: 100rem; margin-inline: auto; padding-inline: calc(var(--space) * 6); }

/* Vertical rhythm */
.stack > * + * { margin-top: calc(var(--space) * 4); }
.stack-lg > * + * { margin-top: calc(var(--space) * 8); }

/* Horizontal grouping with wrap */
.cluster { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--space) * 2); }
.cluster-lg { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--space) * 4); }

/* Left group + right group on one line */
.split { display: flex; align-items: center; justify-content: space-between; gap: calc(var(--space) * 4); flex-wrap: wrap; }

/* Card grid */
.grid-cards { display: grid; gap: calc(var(--space) * 4); grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)); }

/* ==========================================================================
   §4 COMPONENTS
   ========================================================================== */

/* --- App shell ---------------------------------------------------------- */
.navbar {
  background: var(--color-card);
  border-bottom: 1px solid var(--color-border);
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
}
.navbar-inner { display: flex; align-items: center; gap: calc(var(--space) * 6); height: 3.5rem; }
.navbar-brand { display: flex; align-items: center; gap: calc(var(--space) * 2); font-weight: var(--weight-heading); color: var(--color-heading); font-size: var(--text-lg); }
.navbar-brand:hover { text-decoration: none; }
.navbar-brand .brand-dot { width: 0.625rem; height: 0.625rem; border-radius: 50%; background: var(--color-primary); }
.navbar-nav { display: flex; align-items: center; gap: calc(var(--space) * 1); margin-right: auto; }
.navbar-link {
  color: var(--color-muted);
  font-weight: var(--weight-ui);
  font-size: var(--text-sm);
  padding: calc(var(--space) * 1.5) calc(var(--space) * 3);
  border-radius: var(--radius-md);
}
.navbar-link:hover { color: var(--color-heading); background: var(--color-neutral-soft); text-decoration: none; }
.navbar-link.active { color: var(--color-primary); background: var(--color-primary-soft); }

.page-header { padding-block: calc(var(--space) * 6); }
.page-title { font-size: var(--text-2xl); }
.page-subtitle { color: var(--color-muted); margin-top: calc(var(--space) * 1); }

/* --- Buttons ------------------------------------------------------------ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: calc(var(--space) * 1.5);
  height: var(--control-h);
  padding-inline: calc(var(--space) * 3.5);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  background: var(--color-card);
  color: var(--color-heading);
  font-size: var(--text-sm);
  font-weight: var(--weight-ui);
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  transition: background-color var(--speed) var(--ease-out), border-color var(--speed) var(--ease-out),
              color var(--speed) var(--ease-out), scale var(--speed) var(--ease-out), box-shadow var(--speed) var(--ease-out);
}
.btn:hover { text-decoration: none; }
.btn:active:not(:disabled) { scale: 0.97; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.btn:focus-visible { box-shadow: var(--focus-ring); }
.btn svg { width: 1em; height: 1em; flex: none; }

.btn-primary { background: var(--color-primary); border-color: var(--color-primary); color: var(--color-on-primary); }
.btn-primary:hover:not(:disabled) { background: var(--color-primary-hover); border-color: var(--color-primary-hover); }

.btn-outline { border-color: var(--color-midnight-ink); }
.btn-outline:hover:not(:disabled) { background: var(--color-inset); border-color: var(--color-border-strong); }

/* The quiet outline: a divider-weight border instead of the ink one. Reserved
   for actions that must stay reachable without being offered — Remove in the
   account pane, which sits beside two buttons that ARE being offered and
   should not read as a third of them. */
.btn-subtle { border-color: var(--color-border); }
.btn-subtle:hover:not(:disabled) { background: var(--color-inset); border-color: var(--color-border-strong); }

.btn-ghost { background: transparent; }
.btn-ghost:hover:not(:disabled) { background: var(--color-neutral-soft); }

.btn-danger { background: var(--color-danger); border-color: var(--color-danger); color: #fff; }
.btn-danger:hover:not(:disabled) { filter: brightness(0.92); }

.btn-sm { height: var(--control-h-sm); padding-inline: calc(var(--space) * 2.5); font-size: var(--text-xs); }
.btn-square { padding-inline: 0; width: var(--control-h); }
.btn-sm.btn-square { width: var(--control-h-sm); }

/* Segmented control (density toggle, view switch) — ruixen action-toolbar style:
   gradient shell, floating pill for the active segment */
.segmented {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-mist);
  /* Flat: no gradient, no shadow — the pill track is a plain #f2f2f2 fill. */
}
.segmented .btn { border: 0; border-radius: var(--radius-pill-full); background: transparent; color: var(--color-muted); height: calc(var(--control-h) - 8px); }
.segmented .btn-sm { height: calc(var(--control-h-sm) - 8px); }
.segmented .btn:hover:not([aria-pressed="true"]) { color: var(--color-heading); background: var(--color-neutral-soft); }
.segmented .btn[aria-pressed="true"] { background: var(--color-primary); color: var(--color-on-primary); }

/* --- Badges ------------------------------------------------------------- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--space) * 1);
  padding: 0.15em 0.6em;
  /* 8px, not a pill. The design reserves the 9999px radius for things you can
     act on, so a static label (a platform name, a list a talent belongs to)
     stays visually distinct from a filter chip you can click. */
  border-radius: var(--radius-badge);
  font-size: var(--text-xs);
  font-weight: var(--weight-heading);
  line-height: 1.4;
  white-space: nowrap;
}
/* Solid ink, and the one badge the design specifies outright: the "New" /
   "Updated" marker, #141414 fill with white text at a full pill radius. The
   other variants stay at 8px — a status marker announces itself, a quiet
   inline label does not. */
.badge-primary {
  background: var(--color-primary);
  color: var(--color-on-primary);
  border-radius: var(--radius-pill-full);
}
/* Outlined — reads as affirmative without a green. */
.badge-success { background: transparent; color: var(--color-heading); border: 1px solid var(--color-midnight-ink); }
/* The one chromatic exception in the system. */
.badge-danger  { background: var(--color-danger-soft);  color: var(--color-danger); }
/* Outlined in graphite — present, but quieter than success. */
.badge-warning { background: transparent; color: var(--color-muted); border: 1px solid var(--color-graphite); }
/* Filled mist — ambient, the least insistent of the set. */
.badge-info    { background: var(--color-mist); color: var(--color-muted); }
.badge-neutral { background: var(--color-mist); color: var(--color-muted); }
.badge-solid   { background: var(--color-primary); color: var(--color-on-primary); }

/* Count bubble inside buttons/tabs */
.badge-count {
  background: var(--color-primary);
  color: var(--color-on-primary);
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  font-weight: var(--weight-heading);
  min-width: 1.25rem;
  height: 1.25rem;
  padding-inline: 0.3em;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* --- Cards -------------------------------------------------------------- */
.card {
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  /* No shadow, deliberately. The design is explicit: card elevation is a 1px
     border and nothing else — shadow is reserved for things that genuinely
     float (dropdowns, dialogs), so a card and a popover never read alike. */
}
.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--space) * 3);
  padding: calc(var(--space) * 4) calc(var(--space) * 5);
  border-bottom: 1px solid var(--color-border);
}
.card-title { font-size: var(--text-lg); font-weight: var(--weight-heading); color: var(--color-heading); }
.card-body { padding: calc(var(--space) * 5); }
.card-footer { padding: calc(var(--space) * 4) calc(var(--space) * 5); border-top: 1px solid var(--color-border); }

/* Stat card */
.stat { display: flex; flex-direction: column; gap: calc(var(--space) * 1); padding: calc(var(--space) * 5); }
.stat-label { font-size: var(--text-xs); font-weight: var(--weight-heading); text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-muted); }
.stat-value { font-size: var(--text-2xl); font-weight: var(--font-weight-w652); color: var(--color-heading); font-variant-numeric: tabular-nums; }
.stat-delta { font-size: var(--text-xs); font-weight: var(--weight-heading); }
/* Direction keeps its colour — see --color-trend-* in tokens.css. Without it
   "up" resolved to the same ink as the rest of the table while "down" stayed
   red, which reads as "falling is notable, rising is not". */
.stat-delta.up { color: var(--color-trend-up); }
.stat-delta.down { color: var(--color-trend-down); }

/* --- Forms -------------------------------------------------------------- */
.field { display: flex; flex-direction: column; gap: calc(var(--space) * 1.5); }
.label { font-size: var(--text-sm); font-weight: var(--weight-ui); color: var(--color-heading); }
.help { font-size: var(--text-xs); color: var(--color-muted); }

.input, .select, .textarea {
  width: 100%;
  height: var(--control-h);
  padding-inline: calc(var(--space) * 3);
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  font-size: var(--text-sm);
  color: var(--color-heading);
  transition: border-color var(--speed) var(--ease-out), box-shadow var(--speed) var(--ease-out);
}
.input:hover:not(:focus):not(:disabled), .select:hover:not(:focus):not(:disabled) { border-color: var(--color-border-strong); }
.textarea {
  height: auto;
  padding-block: calc(var(--space) * 2);
  resize: vertical;
  /* A container, so 16px — not the pill the rule above hands down. The same
     trap `pre` documents: at 9999px a multi-line box loses its first and last
     lines into the curve, and anything positioned in a corner (a reset button,
     a character count) ends up outside the shape. An input is a pill because
     it is one line tall; a textarea never is. */
  border-radius: var(--radius-lg);
}
.input:focus, .select:focus, .textarea:focus { outline: none; border-color: var(--color-primary); box-shadow: var(--focus-ring); }
.input:disabled, .select:disabled { background: var(--color-inset); opacity: 0.7; cursor: not-allowed; }
.input-sm, .select-sm { height: var(--control-h-sm); font-size: var(--text-xs); }
.input.is-invalid { border-color: var(--color-danger); }
.invalid-msg { font-size: var(--text-xs); color: var(--color-danger); }

.select {
  appearance: none;
  padding-right: calc(var(--space) * 8);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right calc(var(--space) * 2) center;
}

/* Search input with embedded icon */
.input-search { position: relative; }
.input-search .input { padding-left: calc(var(--space) * 8); }
.input-search > svg {
  position: absolute; left: calc(var(--space) * 2.5); top: 50%; transform: translateY(-50%);
  width: 1rem; height: 1rem; color: var(--color-faint); pointer-events: none;
}

/* Checkbox / radio */
.checkbox, .radio {
  appearance: none;
  width: 1rem; height: 1rem;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  background: var(--color-card);
  cursor: pointer;
  vertical-align: -0.15em;
  display: inline-grid;
  place-content: center;
  flex: none;
  transition: background-color 0.12s, border-color 0.12s;
}
.radio { border-radius: 50%; }
.checkbox:checked, .radio:checked { background: var(--color-primary); border-color: var(--color-primary); }
.checkbox:checked::before {
  content: "";
  width: 0.6rem; height: 0.6rem;
  background: var(--color-on-primary);
  clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
}
.checkbox:indeterminate { background: var(--color-primary); border-color: var(--color-primary); }
.checkbox:indeterminate::before { content: ""; width: 0.55rem; height: 2px; background: var(--color-on-primary); }
.radio:checked::before { content: ""; width: 0.4rem; height: 0.4rem; border-radius: 50%; background: var(--color-on-primary); }
.checkbox:focus-visible, .radio:focus-visible { box-shadow: var(--focus-ring); }

.check-label { display: inline-flex; align-items: center; gap: calc(var(--space) * 2); font-size: var(--text-sm); cursor: pointer; }

/* Switch */
.switch {
  appearance: none;
  width: 2.1rem; height: 1.2rem;
  border-radius: var(--radius-pill);
  background: var(--color-border-strong);
  position: relative;
  cursor: pointer;
  flex: none;
  transition: background-color 0.15s;
}
.switch::before {
  content: "";
  position: absolute; top: 2px; left: 2px;
  width: calc(1.2rem - 4px); height: calc(1.2rem - 4px);
  border-radius: 50%;
  background: #fff;
  box-shadow: var(--shadow-sm);
  transition: translate 0.15s;
}
.switch:checked { background: var(--color-primary); }
.switch:checked::before { translate: 0.9rem 0; }
.switch:focus-visible { box-shadow: var(--focus-ring); }

/* --- Tabs --------------------------------------------------------------- */
.tabs { display: flex; gap: calc(var(--space) * 1); border-bottom: 1px solid var(--color-border); }
.tab {
  padding: calc(var(--space) * 2) calc(var(--space) * 3);
  margin-bottom: -1px;
  border: 0;
  border-bottom: 2px solid transparent;
  background: none;
  color: var(--color-muted);
  font-size: var(--text-sm);
  font-weight: var(--weight-ui);
  cursor: pointer;
}
.tab:hover { color: var(--color-heading); }
.tab.active { color: var(--color-primary); border-bottom-color: var(--color-primary); }
.tab-panel[hidden] { display: none; }

/* --- Dropdown (native <details>, closed on outside click by style.js) ---- */
.dropdown { position: relative; display: inline-block; }
.dropdown > summary { list-style: none; cursor: pointer; }
.dropdown > summary::-webkit-details-marker { display: none; }
.dropdown-menu {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: var(--z-dropdown);
  min-width: 12rem;
  padding: calc(var(--space) * 1.5);
  background: var(--color-card);
  border: 1px solid var(--color-border);
  /* --radius-xl, not --radius-md. The latter is the 9999px pill, which is
     right for a button and turns a stack of menu items into a lozenge with
     its corners eating the first and last row. The token scale above says
     floating containers are 24px; this is one. */
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-md);
  font-size: var(--text-sm);
}
.dropdown-menu-end { left: auto; right: 0; }
.dropdown-item {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  width: 100%;
  padding: calc(var(--space) * 1.5) calc(var(--space) * 2);
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--color-heading);
  font-size: var(--text-sm);
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
}
.dropdown-item:hover { background: var(--color-neutral-soft); text-decoration: none; }
.dropdown-divider { height: 0; margin: calc(var(--space) * 1.5) 0; border-top: 1px solid var(--color-border); }
.dropdown-heading { padding: calc(var(--space) * 1.5) calc(var(--space) * 2); font-size: var(--text-xs); font-weight: var(--weight-heading); text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-muted); }

/* --- Dialog (native <dialog>) ------------------------------------------- */
.dialog {
  width: min(32rem, calc(100vw - 2rem));
  padding: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-card);
  color: var(--color-text);
  box-shadow: var(--shadow-lg);
}
.dialog::backdrop { background: rgba(15, 23, 42, 0.5); }
.dialog-header { display: flex; align-items: center; justify-content: space-between; padding: calc(var(--space) * 4) calc(var(--space) * 5); border-bottom: 1px solid var(--color-border); }
.dialog-title { font-size: var(--text-lg); font-weight: var(--weight-heading); color: var(--color-heading); }
.dialog-body { padding: calc(var(--space) * 5); }
.dialog-footer { display: flex; justify-content: flex-end; gap: calc(var(--space) * 2); padding: calc(var(--space) * 4) calc(var(--space) * 5); border-top: 1px solid var(--color-border); }

/* --- Alerts ------------------------------------------------------------- */
.alert {
  display: flex;
  gap: calc(var(--space) * 2.5);
  padding: calc(var(--space) * 3) calc(var(--space) * 4);
  border: 1px solid transparent;
  /* Same reason as `pre`: an alert holds an icon and a sentence that wraps,
     so it is a container at 16px rather than a control at the pill radius. */
  border-radius: var(--radius-lg);
  font-size: var(--text-sm);
}
.alert-title { font-weight: var(--weight-heading); }
.alert-success { background: var(--color-mist); color: var(--color-heading); border-color: var(--color-midnight-ink); }
.alert-danger  { background: var(--color-danger-soft);  color: var(--color-danger);  border-color: color-mix(in oklab, var(--color-danger) 25%, transparent); }
.alert-warning { background: var(--color-mist); color: var(--color-heading); border-color: var(--color-graphite); }
.alert-info    { background: var(--color-mist); color: var(--color-muted); border-color: var(--color-border); }

/* --- Empty state -------------------------------------------------------- */
.empty-state { text-align: center; padding: calc(var(--space) * 12) calc(var(--space) * 6); color: var(--color-muted); }
.empty-state h3 { color: var(--color-heading); margin-bottom: calc(var(--space) * 1); }

/* --- Tooltip (CSS-only, data-tip attribute) ------------------------------ */
[data-tip] { position: relative; }
/* The CSS-only fallback, for when style.js has not run. It is clipped by any
   scrolling ancestor and cannot wrap, which is why style.js replaces it with a
   fixed-position node and marks the root .js-tips to switch this off. */
:root:not(.js-tips) [data-tip]:hover::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  z-index: var(--z-tooltip);
  padding: calc(var(--space) * 1) calc(var(--space) * 2);
  background: var(--color-heading);
  color: var(--color-surface);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-weight: var(--weight-ui);
  white-space: nowrap;
  pointer-events: none;
}

/* The real tooltip: one node, positioned by style.js. Fixed, so no scroll
   container can clip it, and free to wrap — the roster's column tooltips are
   whole sentences defining how a figure is calculated, not one-word labels. */
.tip {
  position: fixed;
  z-index: var(--z-tooltip);
  max-width: 22rem;
  padding: calc(var(--space) * 1.5) calc(var(--space) * 2.5);
  background: var(--color-heading);
  color: var(--color-surface);
  border-radius: var(--radius-badge);
  font-size: var(--text-xs);
  font-weight: var(--weight-body);
  line-height: var(--leading-caption);
  letter-spacing: var(--tracking-caption);
  box-shadow: var(--shadow-float);
  pointer-events: none;
}
.tip[hidden] { display: none; }

/* ==========================================================================
   §5 DATA TABLE + DATATABLES SKIN
   ========================================================================== */

/* --- Table anatomy ------------------------------------------------------ */
.table-shell { display: flex; flex-direction: column; }
.table-shell > :first-child { border-top-left-radius: var(--radius-lg); border-top-right-radius: var(--radius-lg); }
.table-shell > :last-child { border-bottom-left-radius: var(--radius-lg); border-bottom-right-radius: var(--radius-lg); }
.table-toolbar {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  flex-wrap: wrap;
  padding: calc(var(--space) * 3) calc(var(--space) * 4);
  border-bottom: 1px solid var(--color-border);
  /* Flat white — the design has no gradients anywhere. */
  background: var(--color-card);
}
.table-toolbar .input-search { width: 16rem; }

/* Filter panel (collapsible) */
.filter-panel { border-bottom: 1px solid var(--color-border); background: var(--color-inset); }
.filter-panel[hidden] { display: none; }
.filter-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
  gap: calc(var(--space) * 4);
  padding: calc(var(--space) * 4);
}
.filter-actions { display: flex; gap: calc(var(--space) * 2); padding: 0 calc(var(--space) * 4) calc(var(--space) * 4); }
.range-pair { display: flex; align-items: center; gap: calc(var(--space) * 1.5); }
.range-pair .input { min-width: 0; }
.range-pair span { color: var(--color-faint); }

/* Active filter chips */
.chip {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--space) * 1);
  padding: 0.15em 0.4em 0.15em 0.7em;
  background: var(--color-primary-soft);
  color: var(--color-primary);
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  font-weight: var(--weight-ui);
}
.chip button {
  border: 0; background: none; cursor: pointer; color: inherit;
  display: grid; place-content: center;
  width: 1.1em; height: 1.1em; border-radius: 50%;
  font-size: inherit; line-height: 1; padding: 0;
}
.chip button:hover { background: color-mix(in oklab, var(--color-primary) 25%, transparent); }

/* Bulk-action bar — replaces toolbar content when rows are selected */
.bulk-bar {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 3);
  padding: calc(var(--space) * 2.5) calc(var(--space) * 4);
  background: var(--color-primary-soft);
  border-bottom: 1px solid color-mix(in oklab, var(--color-primary) 25%, transparent);
  font-size: var(--text-sm);
  font-weight: var(--weight-ui);
  color: var(--color-primary);
}
.bulk-bar[hidden] { display: none; }

/* The table itself */
.table-scroll { overflow-x: auto; }
.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
}
.table th, .table td {
  padding: var(--table-pad-y) var(--table-pad-x);
  text-align: left;
  border-bottom: 1px solid var(--color-border);
  white-space: nowrap;
}
/* The design specifies no tabular UI at all, so this is derived from its
   nearest relative: the mega-menu's category labels (12px, weight 400, #adadad,
   uppercase). Header sits on the card's own white rather than a filled band —
   #f2f2f2 is already doing duty as input fill and row hover, and a third
   meaning on the same screen would blur all three. */
.table thead th {
  background: transparent;
  color: var(--color-faint);
  font-size: var(--text-xs);
  font-weight: var(--weight-body);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  border-bottom: 1px solid var(--color-border);
}
/* Primary value in a row carries the fractional mid-weight; everything else
   recedes to graphite. Weight, not colour, is what separates them. */
.table tbody td { color: var(--color-muted); }
.table tbody td:first-child { color: var(--color-heading); font-weight: var(--weight-emphasis); }
.table tbody tr:hover td { background: var(--color-inset); }
.table tbody tr.selected td { background: var(--color-primary-soft); }
.table .cell-num { text-align: right; }
.table th.cell-num { text-align: right; }

/* --- Two-tier header (platform column groups) ---------------------------
   A band naming the platform sits above the column names. It deliberately
   does NOT take the 12px uppercase-ash header treatment: two rows of that
   stacked read as one mushy block rather than as a hierarchy, so the band
   goes graphite and mixed-case and the labels beneath it stay uppercase.
   Its bottom border is dropped so the two rows read as one header rather
   than as a header plus a stray first row. */
.table th.group-label {
  color: var(--color-muted);
  font-weight: var(--weight-emphasis);
  text-transform: none;
  letter-spacing: var(--tracking-caption);
  border-bottom-color: transparent;
  padding-bottom: calc(var(--space) * 0.5);
  /* Centred over the whole group rather than left-aligned above its first
     column: the label names all four (or three) columns beneath it, and
     sitting over one of them made it look like that column's heading. */
  text-align: center;
}
/* The label and its platform mark travel together, centred as one unit. */
.table th.group-label .group-label-inner {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--space) * 1.5);
}
.table th.group-label .platform-mark { flex: none; opacity: 0.75; }

/* A table that is the whole page does not need boxing in — and, it turns out,
   does not need any rules at all. Every border goes: the card's own, the row
   separators, the header underline and the vertical group dividers. What
   separates a row from its neighbour is the gap between them and the hover
   fill; what separates Instagram's columns from TikTok's is the platform band
   above them. Both were doing that work already, with the rules on top. */
.table-bare {
  border: 0;
  border-radius: 0;
  background: transparent;
}
.table-bare .table th,
.table-bare .table td {
  border: 0;
}
/* The one rule left in the bare table: the seam between Instagram's columns
   and TikTok's. Everything else reads fine unruled, but those two groups sit
   side by side with the same headings — Followers, 1d, Post eng. — and without
   a seam the eye has to count columns to know which platform a number belongs
   to. The account column needs no such help; nothing is ambiguous next to it.

   Applied to the column-label cell and the body cells, never to the platform
   band above them, so the rule starts at the top of the individual headers and
   the band stays one unbroken line. */
.table-bare .table .group-divider { border-left: 1px solid var(--color-border); }

/* "Account" spans both header rows, so by default it floats midway between
   them — level with neither. Bottom-aligned it sits on the same line as
   Followers and the rest, which is what it actually labels; centred, it sits
   over its column the way the platform bands sit over theirs. Both cells
   carry the same bottom padding, so aligning the boxes aligns the text. */
.table th.account-head {
  vertical-align: bottom;
  text-align: center;
}
.table .cell-mono { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-muted); }
.table .cell-check { width: 2.25rem; padding-right: 0; }

/* Density toggle */
.table-compact { --table-pad-y: calc(var(--space) * 1.25); --table-pad-x: calc(var(--space) * 2); }

/* Sticky header (needs a max-height scroll container) */
.table-sticky { max-height: 65vh; overflow-y: auto; }
.table-sticky thead th { position: sticky; top: 0; z-index: var(--z-sticky); }

/* Footer: info + pagination */
.table-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--space) * 3);
  flex-wrap: wrap;
  padding: calc(var(--space) * 3) calc(var(--space) * 4);
  border-top: 1px solid var(--color-border);
  font-size: var(--text-sm);
  color: var(--color-muted);
}

/* --- DataTables core-build skin ------------------------------------------
   Loads with the plain jquery.dataTables build (no DataTables CSS).
   Class names below are emitted by DataTables itself.
   -------------------------------------------------------------------------- */
.dataTables_wrapper { position: relative; }
table.dataTable { width: 100% !important; }

/* Sorting indicators on headers */
table.dataTable thead th.sorting,
table.dataTable thead th.sorting_asc,
table.dataTable thead th.sorting_desc { cursor: pointer; position: relative; padding-right: calc(var(--table-pad-x) + 1rem); }
table.dataTable thead th.sorting::after,
table.dataTable thead th.sorting_asc::after,
table.dataTable thead th.sorting_desc::after {
  content: "";
  position: absolute;
  right: calc(var(--space) * 2);
  top: 50%;
  translate: 0 -50%;
  width: 0.75rem; height: 0.75rem;
  background-color: currentColor;
  opacity: 0.35;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m7 15 5 5 5-5'/%3E%3Cpath d='m7 9 5-5 5 5'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m7 15 5 5 5-5'/%3E%3Cpath d='m7 9 5-5 5 5'/%3E%3C/svg%3E") center / contain no-repeat;
}
table.dataTable thead th.sorting_asc::after {
  opacity: 1;
  color: var(--color-primary);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m7 9 5-5 5 5'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m7 9 5-5 5 5'/%3E%3C/svg%3E");
}
table.dataTable thead th.sorting_desc::after {
  opacity: 1;
  color: var(--color-primary);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m7 15 5 5 5-5'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m7 15 5 5 5-5'/%3E%3C/svg%3E");
}

/* Processing overlay */
.dataTables_processing {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: grid;
  place-content: center;
  background: color-mix(in oklab, var(--color-card) 65%, transparent);
  color: var(--color-muted);
  font-size: var(--text-sm);
  font-weight: var(--weight-ui);
}

/* Info text ("Showing 1 to 25 of 1,000") */
.dataTables_info { font-size: var(--text-sm); color: var(--color-muted); }

/* Pagination */
.dataTables_paginate { display: flex; align-items: center; gap: calc(var(--space) * 1); }
.dataTables_paginate .paginate_button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--control-h-sm);
  height: var(--control-h-sm);
  padding-inline: calc(var(--space) * 2);
  border-radius: var(--radius-pill);
  color: var(--color-heading);
  font-size: var(--text-sm);
  font-weight: var(--weight-ui);
  cursor: pointer;
  user-select: none;
  transition: background-color var(--speed) var(--ease-out), color var(--speed) var(--ease-out), scale var(--speed) var(--ease-out);
}
.dataTables_paginate .paginate_button:hover { background: var(--color-neutral-soft); text-decoration: none; }
.dataTables_paginate .paginate_button:active { scale: 0.92; }
.dataTables_paginate .paginate_button.current { background: var(--color-primary); color: var(--color-on-primary); box-shadow: var(--shadow-sm); }
.dataTables_paginate .paginate_button.disabled { opacity: 0.4; cursor: not-allowed; pointer-events: none; }
.dataTables_paginate .ellipsis { color: var(--color-faint); padding-inline: calc(var(--space) * 1); }

/* Hide DataTables' own controls we replace with toolbar equivalents */
.dataTables_filter, .dataTables_length { display: none; }

/* Column-visibility dropdown checklist */
.col-vis-list { max-height: 16rem; overflow-y: auto; }
.col-vis-list .check-label { padding: calc(var(--space) * 1.5) calc(var(--space) * 2); border-radius: var(--radius-sm); width: 100%; }
.col-vis-list .check-label:hover { background: var(--color-neutral-soft); }

/* ==========================================================================
   §6 UTILITIES (deliberately small — add sparingly)
   ========================================================================== */
.text-muted { color: var(--color-muted); }
.text-faint { color: var(--color-faint); }
.text-heading { color: var(--color-heading); }
.text-danger { color: var(--color-danger); }
.text-success { color: var(--color-success); }
.text-xs { font-size: var(--text-xs); }
.text-sm { font-size: var(--text-sm); }
.text-right { text-align: right; }
.text-center { text-align: center; }
.font-medium { font-weight: var(--weight-ui); }
.font-semibold { font-weight: var(--weight-heading); }
.mono { font-family: var(--font-mono); }
.nowrap { white-space: nowrap; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hidden { display: none !important; }
.ml-auto { margin-left: auto; }
.w-full { width: 100%; }
.flex-1 { flex: 1; }
