/* ==========================================================================
   AI Training — admin panel.

   Same brand, different job. The public page is a persuasion surface; this is a
   tool people sit in for hours, so it is denser, quieter, and theme-aware —
   navy chrome with a light or dark working area, and orange reserved for the
   primary action in any given view.
   ========================================================================== */

:root {
  /* Same values as the public site, sampled from the logo. */
  --o-600: #c62d03;
  --o-500: #ec3705;
  --o-400: #f96f08;
  --o-300: #ff8c08;
  --o-050: #fff4ec;

  --nav-bg: #070835;
  --nav-bg-2: #0d0e4a;
  --nav-ink: #cdcef0;
  --nav-ink-dim: #8b8cc0;
  --nav-active: #ff8c08;

  --bg: #f4f5fa;
  --surface: #ffffff;
  --surface-2: #fafaff;
  --line: #e3e4f0;
  --line-2: #eeeff7;
  --ink: #171733;
  --ink-2: #4d4d70;
  --ink-3: #757595;

  --ok: #12805c;
  --ok-bg: #e7f6ef;
  --warn: #a86a00;
  --warn-bg: #fdf3e2;
  --err: #c62f34;
  --err-bg: #fdeced;
  --info: #2a51c8;
  --info-bg: #eaeeff;

  --f-display: 'Manrope', ui-sans-serif, system-ui, 'Segoe UI', sans-serif;
  --f-body: 'Inter', ui-sans-serif, system-ui, 'Segoe UI', sans-serif;
  --f-mono: ui-monospace, 'JetBrains Mono', SFMono-Regular, Menlo, monospace;

  --r: 10px;
  --r-lg: 14px;
  --sh: 0 1px 2px rgba(7, 8, 53, .05), 0 2px 8px rgba(7, 8, 53, .05);
  --sh-lg: 0 10px 30px rgba(7, 8, 53, .13);

  --top-h: 60px;

  /* Tile tones. Two hues from the logo — the navy and the orange — plus the amber
     that sits between them on the mark, and one green, which no logo colour can
     stand in for: "enrolled" has to read as the good outcome and orange cannot say
     that. Backgrounds are tints at roughly 6% so a row of four reads as a set
     rather than four warnings; the ink carries the meaning. */
  --tone-navy: #3a3b7d;
  --tone-navy-bg: #f0f0fa;
  --tone-navy-line: #dcdcf2;

  --tone-orange: #c62d03;
  --tone-orange-bg: #fff2ea;
  --tone-orange-line: #ffdcc8;

  --tone-amber: #855200;
  --tone-amber-bg: #fff7e8;
  --tone-amber-line: #f7e2bc;

  --tone-green: #0f6b4d;
  --tone-green-bg: #ecf7f2;
  --tone-green-line: #cfe9df;

  /* Two more hues for the dashboard, where six sections each need their own.
     Both are chosen to sit between the navy and the orange rather than beside
     them: violet leans on the navy, teal bridges the navy and the green. */
  --tone-violet: #6b3fa0;
  --tone-violet-bg: #f5f0fc;
  --tone-violet-line: #e4d8f6;

  --tone-teal: #0f6b73;
  --tone-teal-bg: #ecf6f7;
  --tone-teal-line: #cbe6e9;

  /* Medium tints, for the dashboard. The leads tiles sit at roughly 6% because
     they are read against a dense table; a dashboard is read at a glance and
     wants more colour, so these are nearer 14% — enough to group the page by
     eye, still short of a card that shouts. */
  --tone-navy-mid: #e3e4f6;
  --tone-orange-mid: #ffe2d1;
  --tone-amber-mid: #fdedcf;
  --tone-green-mid: #d9efe6;
  --tone-violet-mid: #ebe0f9;
  --tone-teal-mid: #d9ecee;

  /* The selected chip. Its own token because --o-050 is a light-only tint with no
     dark counterpart, and a peach chip in a dark panel glares. */
  --chip-on-bg: #fff4ec;
  --chip-on-ink: #c62d03;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --bg: #0a0922;
    --surface: #12112f;
    --surface-2: #171638;
    --line: #272552;
    --line-2: #1e1c44;
    --ink: #eceafc;
    --ink-2: #b3b1d6;
    --ink-3: #8886b0;
    --ok-bg: #0e3328;
    --warn-bg: #37280d;
    --err-bg: #3a1518;
    --info-bg: #17204d;
  }
}

:root[data-theme='dark'] {
  /* Same values as the public site's dark block, so the admin and the site it
     manages are visibly the same product. */
  --bg: #0b1020;
  --surface: #121a33;
  --surface-2: #0f1730;
  --line: #253156;
  --line-2: #1e2848;
  --ink: #ffffff;
  --ink-2: #cbd5e1;
  --ink-3: #94a3b8;

  /* Primary turns blue in dark for the same reason it does on the public site:
     an orange fill on a near-black panel reads as a warning, not an action. */
  --o-600: #1d4ed8;
  --o-500: #2563eb;
  --o-400: #3b82f6;
  --o-300: #06b6d4;
  --o-050: #0d1f3d;

  --nav-bg: #070b16;
  --nav-bg-2: #0d1428;
  --nav-ink: #cbd5e1;
  --nav-ink-dim: #94a3b8;
  --nav-active: #06b6d4;

  --ok: #34d399;
  --warn: #fbbf24;
  --err: #fb7185;
  --info: #93c5fd;
  --ok-bg: #0e2f26;
  --warn-bg: #33270c;
  --err-bg: #3a1620;
  --info-bg: #14203f;

  --sh: 0 1px 2px rgba(0, 0, 0, .40), 0 2px 8px rgba(0, 0, 0, .30);
  --sh-lg: 0 10px 30px rgba(0, 0, 0, .50);

  /* Dark reverses the relationship: the ink lightens so it stays legible, and the
     tint darkens rather than lightening, or the tiles would glow. */
  --tone-navy: #a8a9ef;
  --tone-navy-bg: #191a44;
  --tone-navy-line: #2c2a63;

  --tone-orange: #ff9153;
  --tone-orange-bg: #33190e;
  --tone-orange-line: #5a2c14;

  --tone-amber: #f2b445;
  --tone-amber-bg: #2f2409;
  --tone-amber-line: #533f10;

  --tone-green: #4ec89b;
  --tone-green-bg: #0d3227;
  --tone-green-line: #1a5442;

  --tone-violet: #c2a3ee;
  --tone-violet-bg: #251a3d;
  --tone-violet-line: #3d2c5e;

  --tone-teal: #57c2cb;
  --tone-teal-bg: #0d2f33;
  --tone-teal-line: #175056;

  --tone-navy-mid: #22224f;
  --tone-orange-mid: #3f1d10;
  --tone-amber-mid: #3a2c0c;
  --tone-green-mid: #103d30;
  --tone-violet-mid: #2c2049;
  --tone-teal-mid: #10393e;

  --chip-on-bg: #12294d;
  --chip-on-ink: #93c5fd;
}

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

body {
  margin: 0; background: var(--bg); color: var(--ink);
  font-family: var(--f-body); font-size: 14.5px; line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { font-family: var(--f-display); margin: 0; line-height: 1.2; letter-spacing: -.02em; }
p { margin: 0; }
a { color: inherit; text-decoration: none; }
img, svg { max-width: 100%; }
:focus-visible { outline: 2px solid var(--o-400); outline-offset: 2px; border-radius: 4px; }

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

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

/* The rail width snaps rather than animating, deliberately.
   Transitioning grid-template-columns does not work when the track size comes
   from a custom property — Chrome holds the start value and the sidebar never
   resizes at all. Registering the property and transitioning the variable
   instead leaves the transition permanently "running" without ever advancing.
   Both were tried; an instant width change is correct and a broken animation is
   not, so the toggle is instant and the label/icon states carry the feedback. */
.shell {
  --side-w: 250px;
  display: grid;
  grid-template-columns: var(--side-w) 1fr;
  min-height: 100vh;
}

.side {
  background: linear-gradient(180deg, var(--nav-bg) 0%, var(--nav-bg-2) 100%);
  color: var(--nav-ink); display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh;
  /* Only the nav list scrolls. Scrolling the whole sidebar pushes the profile
     link off the bottom of a laptop screen, because nineteen modules do not fit
     in 820px. */
  overflow: hidden;
}
.side nav::-webkit-scrollbar { width: 6px; }
.side nav::-webkit-scrollbar-thumb { background: rgba(255,255,255,.14); border-radius: 3px; }

.side-brand {
  display: flex; align-items: center; gap: 10px; padding: 16px 18px;
  border-bottom: 1px solid rgba(255,255,255,.09); flex: none;
}
.side-brand img { width: 32px; height: 32px; }
.side-brand b { font-family: var(--f-display); font-size: 14.5px; color: #fff; display: block; }
.side-brand span { font-size: 10.6px; color: var(--o-300); letter-spacing: .08em; text-transform: uppercase; }

.side nav { padding: 12px 10px; flex: 1; overflow-y: auto; min-height: 0; }
/* Section heading, now a real button that opens and closes its group. */
.side-group {
  width: 100%; display: flex; align-items: center; gap: 8px;
  font-family: inherit; font-size: 10.4px; font-weight: 700; letter-spacing: .13em;
  text-transform: uppercase; color: var(--nav-ink-dim);
  padding: 14px 10px 7px; border: 0; background: transparent; cursor: pointer;
  text-align: left; transition: color .14s ease;
}
.side-group:hover { color: #fff; }
.side-group .nav-label { flex: 1; min-width: 0; }

.grp-chev {
  width: 13px; height: 13px; flex: none; opacity: .75;
  transition: transform .18s ease;
}
.grp-chev svg { width: 13px; height: 13px; display: block; }

/* Closed: chevron points right and the items are removed from the flow, so the
   sections above and below close up rather than leaving a gap. */
.nav-group.is-closed .grp-chev { transform: rotate(-90deg); }
.nav-group.is-closed .nav-group-items { display: none; }

@media (prefers-reduced-motion: reduce) { .grp-chev { transition: none; } }
.side a.nav-item {
  display: flex; align-items: center; gap: 11px; padding: 9px 11px; border-radius: 8px;
  color: var(--nav-ink); font-size: 13.8px; font-weight: 500; margin-bottom: 1px;
  transition: background-color .14s ease, color .14s ease;
}
.side a.nav-item:hover { background: rgba(255,255,255,.07); color: #fff; }
.side a.nav-item.active { background: rgba(236,55,5,.22); color: #fff; font-weight: 600; }
.side a.nav-item.active .nav-ico { color: var(--nav-active); }
.nav-ico { width: 17px; height: 17px; flex: none; opacity: .9; }
.nav-ico svg { width: 17px; height: 17px; stroke-width: 1.8; }
.nav-count {
  margin-left: auto; font-size: 10.8px; font-weight: 700; padding: 1px 7px; border-radius: 999px;
  background: var(--o-500); color: #fff;
}

.side-foot { padding: 12px; border-top: 1px solid rgba(255,255,255,.09); flex: none; }
.side-user { display: flex; align-items: center; gap: 10px; padding: 8px; border-radius: 8px; }
.side-user:hover { background: rgba(255,255,255,.07); }
.side-user .av { width: 32px; height: 32px; border-radius: 50%; flex: none; }
.side-user b { display: block; font-size: 13px; color: #fff; font-weight: 600; }
.side-user span { font-size: 11.4px; color: var(--nav-ink-dim); }

.side-collapse {
  width: 38px; height: 38px; flex: none; border: 1px solid var(--line);
  background: var(--surface); border-radius: 8px; cursor: pointer; color: var(--ink-2);
  display: inline-flex; align-items: center; justify-content: center;
  transition: border-color .14s ease, color .14s ease;
}
.side-collapse:hover { border-color: var(--ink-3); color: var(--ink); }
.side-collapse svg { width: 17px; height: 17px; }
html.side-collapsed .side-collapse svg { transform: rotate(180deg); }

/* ------------------------------------------------- collapsed rail

   Toggling a class on <html> rather than on .side, so the pre-paint script in
   the layout can set it before any element exists and the sidebar never renders
   at the wrong width first.

   Labels are hidden with the sr-only pattern, not display:none — the rail is a
   visual affordance, and a screen reader should still get "Leads", not an
   unlabelled icon. Sighted mouse users get a native tooltip, applied by
   admin.js only while collapsed. */

html.side-collapsed .shell { --side-w: 68px; }

html.side-collapsed .side .nav-label {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

html.side-collapsed .side-brand { justify-content: center; padding-inline: 0; }
html.side-collapsed .side nav { padding-inline: 8px; }

html.side-collapsed .side .nav-item,
html.side-collapsed .side-user { justify-content: center; gap: 0; padding-inline: 0; }

/* The group heading collapses to a divider — the grouping is still legible,
   without a truncated word pretending to be one. The chevron goes with it, and
   every section is forced open: in a 68px rail there is nothing to click and no
   room to explain why an icon vanished. */
html.side-collapsed .side-group {
  padding: 12px 14px 6px; margin: 0; cursor: default; pointer-events: none;
}
html.side-collapsed .side-group::after {
  content: ''; display: block; height: 1px; background: rgba(255,255,255,.13);
}
html.side-collapsed .grp-chev { display: none; }
html.side-collapsed .nav-group.is-closed .nav-group-items { display: block; }

/* The badge has no room beside the label any more, so it rides the icon. */
html.side-collapsed .nav-item { position: relative; }
html.side-collapsed .nav-count {
  position: absolute; top: 4px; right: 10px; margin: 0;
  min-width: 16px; padding: 0 4px; font-size: 9.6px; line-height: 16px; text-align: center;
}


/* Only a rail on desktop. Below 1000px the sidebar is a full-width drawer that
   is either open or closed, and a 68px version of it would be useless. */
@media (max-width: 1000px) {
  html.side-collapsed .shell { --side-w: 250px; }
  html.side-collapsed .side .nav-label {
    position: static; width: auto; height: auto; margin: 0;
    overflow: visible; clip: auto; white-space: normal;
  }
  html.side-collapsed .side-brand,
  html.side-collapsed .side .nav-item,
  html.side-collapsed .side-user { justify-content: flex-start; gap: 11px; padding-inline: 11px; }
  html.side-collapsed .side-group::after { display: none; }
  html.side-collapsed .nav-count { position: static; }
  /* The hamburger is the nav control at this width; a rail makes no sense. */
  .side-collapse { display: none; }
}

.av {
  display: grid; place-items: center; object-fit: cover;
  background: linear-gradient(135deg, var(--o-500), var(--o-300));
  color: #fff; font-family: var(--f-display); font-weight: 800; font-size: 12px;
}

/* ------------------------------------------------------------- topbar */

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

.top {
  height: var(--top-h); background: var(--surface); border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 14px; padding: 0 20px;
  position: sticky; top: 0; z-index: 40;
}
.top h1 { font-size: 17px; font-weight: 800; }
.top .crumb { font-size: 12.4px; color: var(--ink-3); }
.top-actions { margin-left: auto; display: flex; align-items: center; gap: 9px; }

.side-toggle {
  display: none; width: 38px; height: 38px; border: 1px solid var(--line);
  background: var(--surface); border-radius: 8px; cursor: pointer; color: var(--ink);
  align-items: center; justify-content: center;
}

.content { padding: 22px 20px 60px; flex: 1; }

@media (max-width: 1000px) {
  .shell { grid-template-columns: 1fr; }
  .side {
    position: fixed; inset: 0 auto 0 0; width: 260px; z-index: 60;
    transform: translateX(-100%); transition: transform .24s cubic-bezier(.4,0,.2,1);
  }
  .side[data-open="true"] { transform: translateX(0); box-shadow: var(--sh-lg); }
  .side-toggle { display: inline-flex; }
  .side-scrim {
    position: fixed; inset: 0; background: rgba(7,8,53,.5); z-index: 55; display: none;
  }
  .side-scrim[data-open="true"] { display: block; }
}

/* ------------------------------------------------------------ buttons */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 8px 15px; border-radius: 8px; border: 1px solid transparent;
  font-family: var(--f-display); font-size: 13.4px; font-weight: 700; cursor: pointer;
  white-space: nowrap; transition: background-color .14s ease, border-color .14s ease, color .14s ease, transform .14s ease;
}
.btn:hover { transform: translateY(-1px); }
.btn svg { width: 15px; height: 15px; }
.btn-primary { background: var(--o-500); color: #fff; }
.btn-primary:hover { background: var(--o-600); }
.btn-secondary { background: var(--surface); border-color: var(--line); color: var(--ink); }
.btn-secondary:hover { border-color: var(--ink-3); }
.btn-danger { background: var(--err); color: #fff; }
.btn-danger:hover { filter: brightness(.92); }
.btn-ghost { background: transparent; color: var(--ink-2); }
.btn-ghost:hover { background: var(--line-2); color: var(--ink); }
.btn-sm { padding: 5px 10px; font-size: 12.4px; border-radius: 7px; }
.btn-sm svg { width: 13px; height: 13px; }
.btn:disabled { opacity: .55; cursor: not-allowed; transform: none; }

/* -------------------------------------------------------------- cards */

.card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: var(--sh);
}
.card-head {
  padding: 15px 18px; border-bottom: 1px solid var(--line-2);
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
}
.card-head h2 { font-size: 15px; font-weight: 800; }
/* A bare svg in a flex row has no intrinsic size and grows until it fills the card. */
.card-head > svg { width: 17px; height: 17px; flex: none; color: var(--ink-3); }
.card-head .sub { font-size: 12.6px; color: var(--ink-3); }
.card-head .spacer { margin-left: auto; }
.card-body { padding: 18px; }
.card-foot { padding: 13px 18px; border-top: 1px solid var(--line-2); display: flex; gap: 9px; flex-wrap: wrap; }


/* A card that folds away. Built on <details> so the open/closed state is the
   browser's, not ours — no script, and it still works if one fails to load.
   Collapsed content stays in the DOM, so fields inside a shut section are still
   submitted with the form; hidden is not the same as disabled. */
details.card > summary {
  padding: 15px 18px;
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  cursor: pointer; list-style: none; user-select: none;
  border-radius: var(--r-lg);
}
details.card > summary::-webkit-details-marker { display: none; }
details.card[open] > summary { border-bottom: 1px solid var(--line-2); border-radius: var(--r-lg) var(--r-lg) 0 0; }
details.card > summary:hover { background: var(--surface-2); }
details.card > summary:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
details.card > summary h2 { font-size: 15px; font-weight: 800; }
details.card > summary .sub { font-size: 12.6px; color: var(--ink-3); }

/* The chevron sits at the end and turns when the section opens. Wrapped in a
   span because the icon partial emits a bare <svg> with no class of its own. */
details.card > summary .chev {
  margin-left: auto; flex: none; display: flex; color: var(--ink-3);
  transition: transform .18s ease;
}
details.card > summary .chev svg { width: 16px; height: 16px; display: block; }
details.card[open] > summary .chev { transform: rotate(180deg); }

/* A short read-out of what the section holds, so a shut section still says
   whether it is configured. */
.sec-state { font-size: 12.2px; color: var(--ink-3); }
.sec-state.is-set { color: var(--ok, #16794a); font-weight: 700; }

@media (prefers-reduced-motion: reduce) {
  details.card > summary .chev { transition: none; }
}

.grid { display: grid; gap: 16px; }

/* A card that takes the full width of a two-column grid. Written as a class
   rather than inline so it can be undone: on a narrow screen the grid collapses
   to one column, and "span 2" then invents a second one and pushes the card off
   the side of the screen. */
.span-2 { grid-column: span 2; }
@media (max-width: 900px) { .span-2 { grid-column: auto; } }
.g-2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.g-3 { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.g-4 { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }

/* --------------------------------------------------------- stat tiles */

.tile {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: 16px 18px; box-shadow: var(--sh);
}
.tile .label { font-size: 12.2px; color: var(--ink-3); font-weight: 600; letter-spacing: .03em; text-transform: uppercase; }
.tile .value {
  font-family: var(--f-display); font-size: 1.85rem; font-weight: 800;
  letter-spacing: -.035em; margin-top: 6px; line-height: 1;
}
.tile .delta { margin-top: 7px; font-size: 12.4px; color: var(--ink-3); }
.tile.accent { border-color: var(--o-300); }
.tile.accent .value { color: var(--o-600); }

/* ------------------------------------------------------------- tables */

.table-tools {
  display: flex; flex-wrap: wrap; gap: 9px; align-items: center;
  padding: 13px 16px; border-bottom: 1px solid var(--line-2);
}
.table-tools .grow { flex: 1; min-width: 180px; }
.table-tools .spacer { margin-left: auto; }

.search-box { position: relative; }
.search-box svg {
  position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
  width: 15px; height: 15px; stroke: var(--ink-3); pointer-events: none;
}
.search-box input { padding-left: 33px; }

.table-wrap { overflow-x: auto; }
table.data { width: 100%; border-collapse: collapse; font-size: 13.6px; }
table.data th, table.data td {
  padding: 10px 14px; text-align: left; border-bottom: 1px solid var(--line-2);
  vertical-align: middle;
}
table.data thead th {
  background: var(--surface-2); font-family: var(--f-display); font-size: 11.4px;
  font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-3);
  white-space: nowrap; position: sticky; top: 0; z-index: 2;
}
table.data thead th a { display: inline-flex; align-items: center; gap: 5px; color: inherit; }
table.data thead th a:hover { color: var(--o-600); }
table.data thead th .sort-ind { font-size: 9px; opacity: .55; }
table.data thead th.is-sorted a { color: var(--o-600); }
table.data thead th.is-sorted .sort-ind { opacity: 1; }
table.data tbody tr:hover { background: var(--surface-2); }
table.data tbody tr:last-child td { border-bottom: 0; }
table.data td.actions { text-align: right; white-space: nowrap; }
table.data td.num { font-family: var(--f-mono); font-size: 12.8px; }
table.data .strong { font-weight: 700; color: var(--ink); }
table.data .dim { color: var(--ink-3); font-size: 12.6px; }
table.data .clip { max-width: 340px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.col-check { width: 34px; }
.col-check input { width: 15px; height: 15px; accent-color: var(--o-500); cursor: pointer; }

.bulkbar {
  display: none; align-items: center; gap: 10px; padding: 10px 16px;
  background: var(--info-bg); border-bottom: 1px solid var(--line-2); font-size: 13px;
}
.bulkbar[data-active="true"] { display: flex; }
.bulkbar .spacer { margin-left: auto; }

.pager {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  padding: 12px 16px; border-top: 1px solid var(--line-2); font-size: 13px; color: var(--ink-2);
}
.pager .spacer { margin-left: auto; }
.pager .pages { display: flex; gap: 4px; }
.pager .pages a, .pager .pages span {
  min-width: 30px; height: 30px; display: grid; place-items: center; padding: 0 8px;
  border: 1px solid var(--line); border-radius: 7px; font-size: 12.8px; background: var(--surface);
}
.pager .pages a:hover { border-color: var(--o-400); color: var(--o-600); }
.pager .pages .current { background: var(--o-500); border-color: var(--o-500); color: #fff; font-weight: 700; }
.pager .pages .disabled { opacity: .4; }

.empty {
  padding: 46px 20px; text-align: center; color: var(--ink-3);
}
.empty h3 { font-size: 15px; color: var(--ink-2); margin-bottom: 6px; }
.empty p { font-size: 13.4px; max-width: 44ch; margin: 0 auto 16px; }

/* ------------------------------------------------------------- badges */

.badge {
  display: inline-flex; align-items: center; gap: 5px; padding: 2px 9px; border-radius: 999px;
  font-size: 11.4px; font-weight: 700; letter-spacing: .02em; white-space: nowrap;
}
.b-new { background: var(--info-bg); color: var(--info); }
.b-contacted { background: var(--warn-bg); color: var(--warn); }
.b-qualified { background: #eae4ff; color: #5b2fc9; }
.b-enrolled { background: var(--ok-bg); color: var(--ok); }
.b-not_interested { background: var(--line-2); color: var(--ink-3); }
.b-junk { background: var(--err-bg); color: var(--err); }
.b-ok { background: var(--ok-bg); color: var(--ok); }
.b-off { background: var(--line-2); color: var(--ink-3); }
.b-warn { background: var(--warn-bg); color: var(--warn); }
.b-err { background: var(--err-bg); color: var(--err); }
.b-draft { background: var(--line-2); color: var(--ink-3); }
.b-review { background: var(--warn-bg); color: var(--warn); }
.b-published { background: var(--ok-bg); color: var(--ok); }
.b-discarded { background: var(--err-bg); color: var(--err); }
.b-high { background: var(--err-bg); color: var(--err); }
.b-medium { background: var(--warn-bg); color: var(--warn); }
.b-low { background: var(--line-2); color: var(--ink-3); }

.dot-ok, .dot-bad { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.dot-ok { background: var(--ok); }
.dot-bad { background: var(--err); }

/* -------------------------------------------------------------- forms */

.field { margin-bottom: 14px; }
.field > label {
  display: block; font-size: 12.8px; font-weight: 600; color: var(--ink-2); margin-bottom: 5px;
}
.field .hint { display: block; font-size: 12px; color: var(--ink-3); margin-top: 5px; }
.req { color: var(--err); }

.input, .select, .textarea {
  width: 100%; padding: 8px 11px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--surface); color: var(--ink); font-family: inherit; font-size: 13.8px;
  transition: border-color .14s ease, box-shadow .14s ease;
}
.input:focus, .select:focus, .textarea:focus {
  outline: none; border-color: var(--o-400); box-shadow: 0 0 0 3px rgba(249,115,22,.13);
}
.input::placeholder, .textarea::placeholder { color: var(--ink-3); opacity: .75; }
.textarea { min-height: 100px; resize: vertical; line-height: 1.6; }
.textarea.code { font-family: var(--f-mono); font-size: 12.6px; }
.textarea.tall { min-height: 240px; }
.select {
  appearance: none; padding-right: 30px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23757595' stroke-width='2.6'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center;
}
.input.mono { font-family: var(--f-mono); font-size: 12.8px; }

.row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.row-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
@media (max-width: 760px) { .row, .row-3 { grid-template-columns: 1fr; } }

.check { display: flex; align-items: flex-start; gap: 9px; font-size: 13.4px; cursor: pointer; margin-bottom: 10px; }
.check input { width: 16px; height: 16px; accent-color: var(--o-500); margin-top: 2px; flex: none; cursor: pointer; }
.check span { color: var(--ink-2); }
.check b { display: block; color: var(--ink); font-weight: 600; }

.switch { display: inline-flex; align-items: center; gap: 9px; cursor: pointer; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch .track {
  width: 38px; height: 21px; border-radius: 999px; background: var(--line); position: relative;
  transition: background-color .16s ease; flex: none;
}
.switch .track::after {
  content: ''; position: absolute; top: 2.5px; left: 2.5px; width: 16px; height: 16px;
  border-radius: 50%; background: #fff; transition: transform .16s ease; box-shadow: 0 1px 3px rgba(0,0,0,.25);
}
.switch input:checked + .track { background: var(--o-500); }
.switch input:checked + .track::after { transform: translateX(17px); }
.switch input:focus-visible + .track { outline: 2px solid var(--o-400); outline-offset: 2px; }

.field-error { color: var(--err); font-size: 12.2px; margin-top: 4px; display: block; }
.validation-summary { margin-bottom: 14px; }
.validation-summary ul { margin: 0; padding-left: 18px; }

/* ------------------------------------------------------------- alerts */

.alert {
  display: flex; gap: 10px; padding: 11px 14px; border-radius: var(--r);
  font-size: 13.4px; margin-bottom: 16px; border: 1px solid transparent;
}
.alert svg { width: 17px; height: 17px; flex: none; margin-top: 1px; }
.alert-ok { background: var(--ok-bg); color: var(--ok); border-color: currentColor; }
.alert-err { background: var(--err-bg); color: var(--err); border-color: currentColor; }
.alert-warn { background: var(--warn-bg); color: var(--warn); border-color: currentColor; }
.alert-info { background: var(--info-bg); color: var(--info); border-color: currentColor; }
.alert strong { font-weight: 700; }

/* --------------------------------------------------------------- tabs */

.tabs {
  display: flex; gap: 2px; overflow-x: auto; border-bottom: 1px solid var(--line);
  margin-bottom: 20px; scrollbar-width: thin;
}
.tabs a {
  padding: 9px 15px; font-size: 13.4px; font-weight: 600; color: var(--ink-2);
  border-bottom: 2px solid transparent; white-space: nowrap; margin-bottom: -1px;
  transition: color .14s ease, border-color .14s ease;
}
.tabs a:hover { color: var(--ink); }
.tabs a.active { color: var(--o-600); border-bottom-color: var(--o-500); }

/* --------------------------------------------------------- key/value */

dl.kv { display: grid; grid-template-columns: minmax(140px, auto) 1fr; gap: 9px 20px; margin: 0; font-size: 13.4px; }
dl.kv dt { color: var(--ink-3); }
dl.kv dd { margin: 0; color: var(--ink); font-weight: 500; word-break: break-word; }
dl.kv dd.mono { font-family: var(--f-mono); font-size: 12.6px; }

/* Banded rows. The gap is dropped and replaced with padding, because a grid gap
   leaves an unpainted channel between the term and its value and the band would
   arrive in two pieces. nth-of-type counts dt and dd separately, which is what
   makes the pair line up on the same band. */
dl.kv.zebra { gap: 0; }
dl.kv.zebra dt,
dl.kv.zebra dd { padding: 8px 12px; }
dl.kv.zebra dt { border-radius: 6px 0 0 6px; }
dl.kv.zebra dd { border-radius: 0 6px 6px 0; }
dl.kv.zebra dt:nth-of-type(odd),
dl.kv.zebra dd:nth-of-type(odd) { background: var(--surface-2); }

/* ------------------------------------------------------- role matrix */

.matrix-wrap { overflow-x: auto; }
table.matrix { width: 100%; border-collapse: collapse; font-size: 13px; min-width: 640px; }
table.matrix th, table.matrix td { padding: 8px 10px; border-bottom: 1px solid var(--line-2); }
table.matrix thead th {
  background: var(--surface-2); font-size: 11px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-3); text-align: center;
}
table.matrix thead th:first-child { text-align: left; }
table.matrix td { text-align: center; }
table.matrix td:first-child { text-align: left; }
table.matrix td:first-child b { display: block; font-size: 13.2px; }
table.matrix td:first-child span { font-size: 11.8px; color: var(--ink-3); }
table.matrix input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--o-500); cursor: pointer; }
table.matrix tbody tr:hover { background: var(--surface-2); }
.matrix-group td {
  background: var(--surface-2); font-family: var(--f-display); font-size: 11px;
  font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3);
}

/* ------------------------------------------------------------- login */

.login-wrap {
  min-height: 100vh; display: grid; place-items: center; padding: 24px;
  background:
    radial-gradient(900px 460px at 15% -10%, rgba(236,55,5,.24), transparent 60%),
    radial-gradient(700px 400px at 88% 108%, rgba(60,50,200,.3), transparent 62%),
    linear-gradient(160deg, #070835 0%, #0d0e4a 70%);
}
.login-card {
  width: min(420px, 100%); background: var(--surface); border-radius: 18px;
  padding: 32px 30px; box-shadow: var(--sh-lg);
}
.login-card .brand { display: flex; align-items: center; gap: 11px; margin-bottom: 22px; }
.login-card .brand img { width: 40px; height: 40px; }
.login-card .brand b { display: block; font-family: var(--f-display); font-size: 15.5px; }
.login-card .brand span { font-size: 11px; color: var(--o-600); letter-spacing: .07em; text-transform: uppercase; }
.login-card h1 { font-size: 20px; font-weight: 800; margin-bottom: 6px; }
.login-card .sub { font-size: 13.4px; color: var(--ink-3); margin-bottom: 22px; }
.login-foot { margin-top: 20px; text-align: center; font-size: 12.4px; color: var(--ink-3); }
.login-foot a { color: var(--o-600); }

/* ------------------------------------------------------------ helpers */

.stack { display: grid; gap: 16px; }
/* Password field with a reveal control. The wrapper is added by password-eye.js,
   so the markup at each field stays a plain input. */
.pw-wrap { position: relative; display: block; }
.pw-wrap .input { padding-right: 40px; }
.pw-toggle {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  display: flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0;
  background: none; border: 0; border-radius: 6px;
  color: var(--ink-3); cursor: pointer;
}
.pw-toggle svg { width: 17px; height: 17px; display: block; }
.pw-toggle:hover { color: var(--ink); background: var(--surface-2); }
.pw-toggle:focus-visible { outline: 2px solid var(--o-400); outline-offset: -2px; }

.inline { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* Fill the rest of a flex row. min-width:0 so a long value shrinks rather than
   pushing the control beside it out of the card. The .table-tools variant above
   is more specific and keeps its own minimum. */
.grow { flex: 1; min-width: 0; }
.muted { color: var(--ink-3); }
.small { font-size: 12.4px; }
.mono { font-family: var(--f-mono); font-size: 12.6px; }
.right { text-align: right; }
.nowrap { white-space: nowrap; }
.mt-1 { margin-top: 8px; } .mt-2 { margin-top: 16px; } .mt-3 { margin-top: 24px; }
.mb-2 { margin-bottom: 16px; }
.page-head { display: flex; align-items: flex-start; gap: 14px; flex-wrap: wrap; margin-bottom: 20px; }
.page-head h2 { font-size: 18px; font-weight: 800; }
.page-head p { font-size: 13.4px; color: var(--ink-3); margin-top: 4px; max-width: 66ch; }
.page-head .spacer { margin-left: auto; }

.bar { height: 6px; border-radius: 999px; background: var(--line-2); overflow: hidden; }
.bar > i { display: block; height: 100%; border-radius: 999px; background: var(--o-500); }

.media-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 14px; }
.media-item {
  border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; background: var(--surface);
  display: flex; flex-direction: column;
}
.media-item .thumb {
  aspect-ratio: 4/3; background: var(--surface-2); display: grid; place-items: center; overflow: hidden;
}
.media-item .thumb img { width: 100%; height: 100%; object-fit: cover; }
.media-item .meta { padding: 9px 10px; font-size: 11.8px; }
.media-item .meta b { display: block; font-size: 12.2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.media-item .meta span { color: var(--ink-3); }
.media-item .row-actions { display: flex; gap: 5px; padding: 0 10px 10px; }

.copy-field { display: flex; gap: 6px; }
.copy-field input { flex: 1; }

.timeline { display: grid; gap: 12px; }
.timeline .entry {
  display: grid; grid-template-columns: auto 1fr; gap: 12px; font-size: 13.2px;
  padding-bottom: 12px; border-bottom: 1px solid var(--line-2);
}
.timeline .entry:last-child { border-bottom: 0; padding-bottom: 0; }
.timeline .when { color: var(--ink-3); font-size: 12.2px; white-space: nowrap; }

.article-preview { max-width: 74ch; }
.article-preview h2 { font-size: 1.2rem; margin: 22px 0 10px; }
.article-preview h3 { font-size: 1.05rem; margin: 18px 0 8px; }
.article-preview p { margin-bottom: 12px; color: var(--ink-2); }
.article-preview ul, .article-preview ol { margin: 0 0 14px 20px; }
.article-preview li { margin-bottom: 5px; color: var(--ink-2); }
.article-preview a { color: var(--o-600); text-decoration: underline; }

@media print {
  .side, .top-actions, .table-tools, .pager, .btn { display: none !important; }
  .shell { grid-template-columns: 1fr; }
}

/* Stored API key: masked value plus a Replace action, sitting on one line.
   The mask is a readonly input rather than plain text so it inherits the field
   styling — a stored secret should look like the field it replaces, not like a
   caption next to an empty one. */
.key-stored { display: flex; gap: 8px; align-items: center; }
.key-stored input[readonly] {
  flex: 1; min-width: 0;
  color: var(--muted);
  background: var(--surface-2);
  cursor: default;
}
.key-stored .btn { flex: none; }
.mt-1 { margin-top: 8px; }

/* ------------------------------------------------- generation progress */
/* Shown while the Content Studio drafts. The bar is driven by characters
   actually streamed back from the provider, so it can sit still — that is
   information, not a bug, and it is why nothing here animates on a timer. */
.gen-progress {
  margin: 0 20px 20px;
  padding: 16px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface-2);
}
.gen-progress-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 10px;
}
.gen-stage { font-weight: 600; color: var(--ink); }
.gen-pct {
  font-family: var(--f-mono);
  font-size: 14px;
  font-variant-numeric: tabular-nums;
  color: var(--o-600);
}
.gen-bar {
  height: 8px;
  border-radius: 999px;
  background: var(--line-2);
  overflow: hidden;
}
.gen-bar-fill {
  display: block;
  height: 100%;
  width: 0;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--o-400), var(--o-600));
  transition: width .45s ease;
}
.gen-topic {
  margin: 10px 0 0;
  font-style: italic;
  color: var(--ink-2);
}
.gen-meta { margin: 4px 0 0; font-variant-numeric: tabular-nums; }

.gen-progress.is-failed { border-color: var(--err); background: var(--err-bg); }
.gen-progress.is-failed .gen-bar-fill { background: var(--err); }
.gen-progress.is-failed .gen-pct { color: var(--err); }

@media (prefers-reduced-motion: reduce) {
  .gen-bar-fill { transition: none; }
}

/* Media tile actions.
   The tiles are only ~150px wide, so Copy path takes a row of its own and the
   open/delete pair shares the next. Delete carries a word as well as an icon —
   as a lone glyph it read as decoration and people missed it. */
.media-item .row-actions { flex-wrap: wrap; }
.media-item .row-actions > [data-copy] { flex: 1 0 100%; }
.media-item .row-actions > form { flex: 1; min-width: 0; }
.media-item .row-actions > form .btn { width: 100%; gap: 5px; }
.media-item .row-actions .btn.is-danger { color: var(--err); }
.media-item .row-actions .btn.is-danger:hover { background: var(--err-bg); }

/* ------------------------------------------------------- icon actions */
/* Actions read as icons in a long table; the label lives in title and
   aria-label so nothing is lost to a screen reader or on hover. */
.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; flex: none;
  border: 1px solid transparent; border-radius: var(--r-sm);
  background: none; color: var(--ink-3); cursor: pointer;
  transition: color .15s ease, background-color .15s ease, border-color .15s ease;
}
.icon-btn:hover { color: var(--o-600); background: var(--surface-2); border-color: var(--line); }
.icon-btn:focus-visible { outline: 2px solid var(--o-500); outline-offset: 1px; }
.icon-btn.is-on { color: var(--o-600); background: var(--o-050); border-color: var(--o-300); }
.icon-btn svg { width: 16px; height: 16px; }

/* ---------------------------------------------------- internal links */
.link-count { font-variant-numeric: tabular-nums; font-weight: 600; }
.link-count.is-none { color: var(--ink-3); font-weight: 400; }

.link-row > td { background: var(--surface-2); padding: 0; }
.link-panel { padding: 12px 16px 14px; }
.link-panel-label {
  display: block; margin-bottom: 8px;
  font-size: 11.5px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-3);
}
.link-list { margin: 0; padding: 0; list-style: none; display: grid; gap: 6px; }
.link-list li { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; font-size: 13.4px; }
.link-anchor { font-weight: 600; color: var(--ink); }
.link-anchor::before { content: '“'; }
.link-anchor::after { content: '”'; }
.link-href { font-family: var(--f-mono); font-size: 12.4px; color: var(--o-600); }
.link-href:hover { text-decoration: underline; }

/* -------------------------------------------------------- date filter */
.datepick { position: relative; flex: none; }
.datepick-button {
  display: inline-flex; align-items: center; gap: 7px;
  width: auto; cursor: pointer; text-align: left;
}
.datepick-button svg { width: 15px; height: 15px; flex: none; }
.datepick-button.is-on { border-color: var(--o-300); color: var(--o-600); background: var(--o-050); }

.datepick-panel {
  position: absolute; z-index: 60; top: calc(100% + 6px); right: 0;
  width: 268px; padding: 12px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r); box-shadow: var(--sh-lg);
}
.datepick-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 8px; font-size: 13.6px;
}
.datepick-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.datepick-dow {
  display: grid; place-items: center; height: 24px;
  font-size: 11px; font-weight: 700; color: var(--ink-3);
}
.datepick-day {
  height: 30px; border: 1px solid transparent; border-radius: var(--r-sm);
  background: none; color: var(--ink); font-size: 12.8px; cursor: pointer;
  font-variant-numeric: tabular-nums;
  transition: background-color .12s ease, color .12s ease, border-color .12s ease;
}
.datepick-day:hover { background: var(--surface-2); border-color: var(--line); }
.datepick-day.is-today { font-weight: 800; color: var(--o-600); }
.datepick-day.is-on {
  background: var(--o-500); border-color: var(--o-600); color: #fff; font-weight: 700;
}
.datepick-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line-2);
}
.datepick-count { font-size: 12px; color: var(--ink-3); }

@media (prefers-reduced-motion: reduce) {
  .icon-btn, .datepick-day { transition: none; }
}

/* ------------------------------------------------------- lead statuses */
/* One chip per status, each a link into the table's own status filter, so
   the numbers and the filter can never disagree about what they mean. */
.status-strip { display: flex; flex-wrap: wrap; gap: 10px; }
.status-chip {
  display: flex; flex-direction: column; gap: 2px;
  min-width: 104px; padding: 11px 14px;
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--surface);
  transition: border-color .15s ease, background-color .15s ease, transform .15s ease;
}
.status-chip:hover { border-color: var(--o-300); transform: translateY(-1px); }
.status-chip-n {
  font-family: var(--f-display); font-size: 1.35rem; font-weight: 800;
  line-height: 1; letter-spacing: -.03em; color: var(--ink);
}
.status-chip-l { font-size: 12px; font-weight: 600; color: var(--ink-3); }
/* On a tinted chip the lightest ink drops under the contrast floor, so toned
   chips take the darker one. */
.status-chip[class*="s-"] .status-chip-l { color: var(--ink-2); }
.status-chip.is-empty .status-chip-n { color: var(--ink-3); font-weight: 700; }
.status-chip.is-on { border-color: var(--o-500); background: var(--o-050); }
.status-chip.is-on .status-chip-n, .status-chip.is-on .status-chip-l { color: var(--o-600); }

/* A left edge in the status colour, so the strip is scannable without reading. */
.status-chip.s-new { border-left: 3px solid var(--info); }
.status-chip.s-contacted { border-left: 3px solid var(--warn); }
.status-chip.s-qualified { border-left: 3px solid var(--o-500); }
.status-chip.s-enrolled { border-left: 3px solid var(--ok); }
.status-chip.s-not_interested { border-left: 3px solid var(--ink-3); }
.status-chip.s-junk { border-left: 3px solid var(--err); }

@media (max-width: 760px) {
  .status-strip { display: grid; grid-template-columns: repeat(2, 1fr); }
  .status-chip { min-width: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .status-chip { transition: none; }
  .status-chip:hover { transform: none; }
}

/* ------------------------------------------------------- toned tiles */
/* A tile says what kind of number it is by its colour: navy for the whole
   set, orange for what is happening now, amber for what is still open and
   needs someone, green for the outcome. The tint is faint and the ink does
   the work — four saturated cards side by side stop meaning anything. */
.tile.tone { background: var(--tone-bg); border-color: var(--tone-line); }
.tile.tone .label { color: var(--tone); }
.tile.tone .value { color: var(--tone); }
.tile.tone .delta { color: var(--ink-2); }


/* Enrolled is the one people look for, so it keeps a heavier edge on top of
   its tone rather than a louder fill. */
.tile.tone-green.is-headline { box-shadow: var(--sh), inset 0 0 0 1px var(--tone-green-line); }

/* Status chips take the same tones, so a status means the same colour whether
   it is read in the strip or in a tile. */
.status-chip { border-left-width: 3px; }
.status-chip.s-new { border-left-color: var(--tone-navy); background: var(--tone-navy-bg); }
.status-chip.s-new .status-chip-n { color: var(--tone-navy); }
.status-chip.s-contacted { border-left-color: var(--tone-amber); background: var(--tone-amber-bg); }
.status-chip.s-contacted .status-chip-n { color: var(--tone-amber); }
.status-chip.s-qualified { border-left-color: var(--tone-orange); background: var(--tone-orange-bg); }
.status-chip.s-qualified .status-chip-n { color: var(--tone-orange); }
.status-chip.s-enrolled { border-left-color: var(--tone-green); background: var(--tone-green-bg); }
.status-chip.s-enrolled .status-chip-n { color: var(--tone-green); }

/* Closed states stay grey on purpose. Colouring "junk" would give it a
   prominence it should not have in a row you scan for live work. */
.status-chip.s-not_interested, .status-chip.s-junk { border-left-color: var(--line); }
.status-chip.s-not_interested .status-chip-n, .status-chip.s-junk .status-chip-n { color: var(--ink-3); }

.status-chip.is-on { border-color: var(--o-500); border-left-color: var(--o-500); background: var(--chip-on-bg); }
.status-chip.is-on .status-chip-n,
.status-chip.is-on .status-chip-l,
.status-chip[class*="s-"].is-on .status-chip-l { color: var(--chip-on-ink); }

/* ---------------------------------------------------- dashboard tones */
/* The dashboard is read at a glance, so each section carries its own colour
   and the colours group by domain: the warm ones are leads, violet and green
   are content, teal and navy are the system. The card body stays plain — the
   colour is in the rule at the top and in the head, where it labels the
   section without sitting behind the numbers you came to read. */
.card.tone { border-top: 3px solid var(--tone); }
.card.tone > .card-head { background: var(--tone-mid); border-bottom-color: var(--tone-line); }
.card.tone > .card-head h2 { color: var(--tone); }

.tile.tone.is-mid { background: var(--tone-mid); border-color: var(--tone-line); }

.tone-navy   { --tone: var(--tone-navy);   --tone-bg: var(--tone-navy-bg);   --tone-mid: var(--tone-navy-mid);   --tone-line: var(--tone-navy-line); }
.tone-orange { --tone: var(--tone-orange); --tone-bg: var(--tone-orange-bg); --tone-mid: var(--tone-orange-mid); --tone-line: var(--tone-orange-line); }
.tone-amber  { --tone: var(--tone-amber);  --tone-bg: var(--tone-amber-bg);  --tone-mid: var(--tone-amber-mid);  --tone-line: var(--tone-amber-line); }
.tone-green  { --tone: var(--tone-green);  --tone-bg: var(--tone-green-bg);  --tone-mid: var(--tone-green-mid);  --tone-line: var(--tone-green-line); }
.tone-violet { --tone: var(--tone-violet); --tone-bg: var(--tone-violet-bg); --tone-mid: var(--tone-violet-mid); --tone-line: var(--tone-violet-line); }
.tone-teal   { --tone: var(--tone-teal);   --tone-bg: var(--tone-teal-bg);   --tone-mid: var(--tone-teal-mid);   --tone-line: var(--tone-teal-line); }

/* ------------------------------------------------------- the trend line */
/* preserveAspectRatio is none, so the chart fills whatever width the card
   gives it; the stroke is kept from stretching with it by non-scaling-stroke
   below, which is why the line stays 2px at every size. */
.trend { display: block; width: 100%; height: 170px; overflow: visible; }
.trend-grid { stroke: var(--line); stroke-width: 1; vector-effect: non-scaling-stroke; }
.trend-grid.is-faint { stroke: var(--line-2); stroke-dasharray: 3 4; }
.trend-area { fill: url(#trendFill); }
.trend-line {
  fill: none; stroke: var(--tone-orange); stroke-width: 2;
  stroke-linejoin: round; stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
.trend-dot { fill: var(--tone-orange); stroke: var(--surface); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.trend-dot.is-zero { fill: var(--line); }
/* --ink-3 is the usual muted grey but it lands at 4.44:1 on white, which is
   under the floor for text this small. */
.trend-axis { fill: var(--ink-2); font-size: 10px; font-family: var(--f-body); }

/* ---------------------------------------------------- phone with dial code */

/* Same control as the public forms, at admin density. Shares the markup so a number
   captured in the admin is stored in the same shape as one a candidate typed. */
.phone-field {
  display: flex; align-items: stretch;
  border: 1px solid var(--line); border-radius: 8px; background: var(--surface);
  transition: border-color .14s ease, box-shadow .14s ease;
}
.phone-field:focus-within { border-color: var(--o-400); box-shadow: 0 0 0 3px rgba(249,115,22,.13); }

.phone-cc {
  display: flex; align-items: center; gap: 6px;
  padding: 0 8px 0 10px; border-right: 1px solid var(--line); background: var(--bg-2);
  border-radius: 7px 0 0 7px;
}
.phone-flag {
  width: 19px; height: 14px; flex: none; display: block;
  border-radius: 2px; box-shadow: 0 0 0 1px rgba(15, 23, 42, .12); object-fit: cover;
}
.phone-dial {
  width: 40px; padding: 8px 0; border: 0; background: none;
  font-family: var(--f-mono); font-size: 13px; color: var(--ink);
}
.phone-dial:focus { outline: none; }

.phone-field .input { border: 0; border-radius: 0 8px 8px 0; background: none; min-width: 0; flex: 1; }
.phone-field .input:focus { box-shadow: none; }

/* ================================================================ follow-ups
   The queue, the calendar and the reminder toast. Everything here is coloured
   through the existing tone tokens, which already flip for dark, so no colour
   is written twice and none of it is defined only inside a theme block.

   Overdue borrows the orange tone and "today" the amber, matching the lead
   status strip: on this screen orange has to read as older and more urgent than
   amber, which is the opposite of a traffic light and the reason it is spelled
   out here rather than left to be inferred. */

.fu-bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 16px; }
.fu-bar .spacer { margin-left: auto; }

.fu-scope { display: inline-flex; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
.fu-scope a {
  padding: 6px 14px; font-size: 12.8px; font-weight: 600; color: var(--ink-3);
  text-decoration: none; background: var(--surface);
}
.fu-scope a + a { border-left: 1px solid var(--line); }
.fu-scope a:hover { color: var(--ink); }
.fu-scope a.is-on { background: var(--o-050); color: var(--o-600); }

.fu-cols { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: 16px; align-items: start; }
@media (max-width: 1100px) { .fu-cols { grid-template-columns: minmax(0, 1fr); } }

/* ------------------------------------------------------------------- a row */

.fu-row {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 11px 18px; border-bottom: 1px solid var(--line-2);
}
.fu-row:last-child { border-bottom: 0; }

.fu-rail { width: 3px; border-radius: 2px; align-self: stretch; flex: none; background: var(--line); }
.fu-row.is-late .fu-rail { background: var(--tone-orange); }
.fu-row.is-soon .fu-rail { background: var(--tone-amber); }
.fu-row.is-next .fu-rail { background: var(--tone-navy); }

.fu-when {
  font-family: var(--f-mono); font-size: 12.4px; font-weight: 700;
  min-width: 58px; padding-top: 2px; flex: none; font-variant-numeric: tabular-nums;
}
.fu-row.is-late .fu-when { color: var(--tone-orange); }
.fu-row.is-soon .fu-when { color: var(--tone-amber); }
.fu-row.is-next .fu-when { color: var(--tone-navy); }

.fu-who { min-width: 0; flex: 1; }
.fu-who .strong { font-weight: 700; color: var(--ink); text-decoration: none; }
.fu-who .strong:hover { color: var(--o-600); }
.fu-meta { font-size: 12.3px; color: var(--ink-3); margin-top: 2px; }
.fu-meta .mono { font-size: 12.3px; }

.fu-acts { margin-left: auto; display: flex; gap: 6px; flex-wrap: wrap; padding-top: 1px; }

.fu-chip {
  display: inline-block; padding: 1px 8px; border-radius: 999px;
  font-size: 11.2px; font-weight: 700; white-space: nowrap; border: 1px solid;
}
.fu-chip.late { background: var(--tone-orange-bg); color: var(--tone-orange); border-color: var(--tone-orange-line); }
.fu-chip.soon { background: var(--tone-amber-bg);  color: var(--tone-amber);  border-color: var(--tone-amber-line); }
.fu-chip.next { background: var(--tone-navy-bg);   color: var(--tone-navy);   border-color: var(--tone-navy-line); }

/* The log panel, revealed under the row it belongs to. */
.fu-panel { padding: 12px 18px 16px 33px; background: var(--surface-2); border-bottom: 1px solid var(--line-2); }
.fu-panel textarea { width: 100%; resize: vertical; }
.fu-panel-acts { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; margin-top: 10px; }
.fu-panel-acts .spacer { margin-left: auto; }
.fu-panel .hint { display: block; font-size: 12px; color: var(--ink-3); }
.fu-sep { width: 1px; height: 20px; background: var(--line); margin: 0 4px; }

/* -------------------------------------------------------------- the calendar */

.fu-cal { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 5px; }
.fu-dow {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--ink-3); font-weight: 700; text-align: center; padding-bottom: 2px;
}
.fu-day {
  aspect-ratio: 1 / 1; min-height: 46px; border: 1px solid var(--line-2); border-radius: 8px;
  padding: 5px 6px; display: flex; flex-direction: column; background: var(--surface-2);
  text-decoration: none; color: inherit;
}
.fu-day.is-out { opacity: .35; }
.fu-dn { font-size: 11px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.fu-ct {
  margin-top: auto; font-family: var(--f-display); font-size: 16px; font-weight: 800;
  line-height: 1; font-variant-numeric: tabular-nums;
}
a.fu-day:hover { border-color: var(--o-300); }
.fu-day.has-late { background: var(--tone-orange-bg); border-color: var(--tone-orange-line); }
.fu-day.has-late .fu-ct { color: var(--tone-orange); }
.fu-day.has-soon { background: var(--tone-amber-bg); border-color: var(--tone-amber-line); }
.fu-day.has-soon .fu-ct { color: var(--tone-amber); }
.fu-day.has-next { background: var(--tone-navy-bg); border-color: var(--tone-navy-line); }
.fu-day.has-next .fu-ct { color: var(--tone-navy); }
.fu-day.is-today { outline: 2px solid var(--o-400); outline-offset: 1px; }
.fu-day.is-picked { box-shadow: inset 0 0 0 2px var(--o-500); }

.fu-legend { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 12px; font-size: 12px; color: var(--ink-3); }
.fu-legend i { width: 10px; height: 10px; border-radius: 3px; display: inline-block; margin-right: 5px; vertical-align: -1px; }
.fu-legend .t-late { background: var(--tone-orange); }
.fu-legend .t-soon { background: var(--tone-amber); }
.fu-legend .t-next { background: var(--tone-navy); }
.fu-legend .t-none { background: var(--line); }

/* ------------------------------------------------------------ reminder card */

#fu-reminders .hint { display: block; font-size: 12px; color: var(--ink-3); }
#fu-reminders hr.rule { border: 0; border-top: 1px solid var(--line-2); margin: 14px 0; }
.fu-hours { display: flex; align-items: center; gap: 8px; margin: 0 0 12px 25px; }
.fu-hours .input { width: 68px; }

/* ------------------------------------------------------------------- toasts */

.fu-toasts {
  position: fixed; right: 18px; bottom: 18px; z-index: 60;
  display: flex; flex-direction: column; gap: 10px;
  width: min(400px, calc(100vw - 36px)); pointer-events: none;
}
.fu-toast {
  display: flex; gap: 12px; padding: 14px; border-radius: var(--r-lg);
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--sh-lg);
  pointer-events: auto; animation: fu-in .22s ease-out both;
}
.fu-toast.is-going { opacity: 0; transform: translateY(6px); transition: opacity .2s, transform .2s; }
@keyframes fu-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .fu-toast { animation: none; }
  .fu-toast.is-going { transition: none; }
}
.fu-toast-ico {
  width: 36px; height: 36px; border-radius: 9px; flex: none;
  display: flex; align-items: center; justify-content: center;
  background: var(--tone-amber-bg); color: var(--tone-amber); border: 1px solid var(--tone-amber-line);
}
.fu-toast-ico svg { width: 18px; height: 18px; }
.fu-toast-t { font-weight: 700; font-size: 13.5px; color: var(--ink); }
.fu-toast-b { font-size: 12.5px; color: var(--ink-3); margin-top: 2px; }
.fu-toast-acts { display: flex; gap: 6px; margin-top: 10px; flex-wrap: wrap; }

/* --------------------------------------------------------- follow-ups, narrow */

@media (max-width: 700px) {
  /* The row is one flex line on a laptop; on a phone the actions crowd the name into
     a single word per line, so the three parts stack instead. */
  .fu-row { flex-wrap: wrap; }
  .fu-when { min-width: 0; }
  .fu-who { flex: 1 1 calc(100% - 80px); }
  .fu-acts { margin-left: 0; flex-basis: 100%; padding-left: 15px; }
  .fu-panel { padding-left: 18px; }
  .fu-toasts { right: 12px; left: 12px; bottom: 12px; width: auto; }

  /* Not follow-ups specific: the top bar is a fixed 60px, so any heading that wraps to
     two lines is clipped. Long titles only wrap at this width. */
  .top { height: auto; min-height: var(--top-h); padding-top: 9px; padding-bottom: 9px; }
}

/* ------------------------------------------------- reminder lead times + stepper */

.fu-lab { font-size: 12.6px; font-weight: 700; color: var(--ink); margin: 0 0 9px; }

.fu-leads { display: flex; flex-wrap: wrap; gap: 7px; }
.fu-leads:empty { display: none; }
.fu-lead {
  display: inline-flex; align-items: center; gap: 5px; padding: 4px 5px 4px 11px;
  border-radius: 999px; font-size: 12.4px; color: var(--tone-navy);
  background: var(--tone-navy-bg); border: 1px solid var(--tone-navy-line);
}
.fu-lead b { font-weight: 700; }
.fu-lead-x {
  width: 18px; height: 18px; border: 0; border-radius: 50%; cursor: pointer;
  background: transparent; color: inherit; opacity: .6; font-size: 15px; line-height: 1;
  display: flex; align-items: center; justify-content: center;
}
.fu-lead-x:hover { opacity: 1; background: var(--tone-navy-line); }

.fu-none { font-size: 12.4px; color: var(--ink-3); margin: 0; }

.fu-lead-add { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; margin-top: 11px; }
.fu-lead-add .input { width: 76px; }
.fu-lead-add .select { width: auto; }

#fu-reminders .hint.is-full { color: var(--tone-amber); }

/* The stepper inside a reminder: minus, the span, plus. */
.fu-step {
  display: inline-flex; align-items: center; border: 1px solid var(--line);
  border-radius: 7px; overflow: hidden; background: var(--surface);
}
.fu-step-b {
  width: 26px; height: 26px; border: 0; background: transparent; cursor: pointer;
  color: var(--ink-2); font-size: 15px; line-height: 1; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.fu-step-b:hover:not(:disabled) { background: var(--surface-2); color: var(--o-600); }
.fu-step-b:disabled { opacity: .35; cursor: default; }
.fu-step-n {
  min-width: 48px; text-align: center; font-family: var(--f-mono); font-size: 12px;
  font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums;
  border-left: 1px solid var(--line); border-right: 1px solid var(--line); padding: 0 4px;
  line-height: 26px;
}

/* A count on a tab — only rendered when there is something wrong to look at. */
.tabs .tab-n {
  display: inline-block; margin-left: 6px; padding: 0 6px; border-radius: 999px;
  font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums;
  background: var(--err-bg); color: var(--err); border: 1px solid currentColor;
}

/* A modal asking one short question. No `display` is set on the dialog itself — that
   would override the browser default of display:none and leave it showing on load. */
.fu-dialog {
  padding: 0; border: 1px solid var(--line); border-radius: var(--r-lg);
  background: var(--surface); color: var(--ink); box-shadow: var(--sh-lg);
  width: min(460px, calc(100vw - 32px));
}
.fu-dialog::backdrop { background: rgba(7, 8, 53, .45); }
.fu-dialog .card-head { border-bottom: 1px solid var(--line-2); }

/* Divider inside the bulk bar, separating actions that only change a record from the
   one that sends something to a person. */
.bulkbar .bulk-sep { width: 1px; height: 22px; background: var(--line); margin: 0 4px; }

/* Collapsible sections in the role matrix. The heading row becomes the control, so the
   whole width of it is clickable rather than a small chevron. */
.matrix-group td { padding: 0; }
.matrix-group button {
  display: flex; align-items: center; gap: 9px; width: 100%; padding: 9px 14px;
  border: 0; background: none; cursor: pointer; text-align: left; color: inherit;
  font: inherit; font-family: var(--f-display); font-size: 11px; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
}
.matrix-group button:hover { color: var(--ink); }
.matrix-group .mx-chev { display: flex; transition: transform .15s ease; }
.matrix-group .mx-chev svg { width: 14px; height: 14px; }
.matrix-group.is-closed .mx-chev { transform: rotate(-90deg); }
.matrix-group .mx-count {
  margin-left: auto; font-family: var(--f-body); font-size: 11px; font-weight: 700;
  letter-spacing: 0; text-transform: none; color: var(--ink-3);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 999px; padding: 0 7px;
}
@media (prefers-reduced-motion: reduce) { .matrix-group .mx-chev { transition: none; } }

/* ------------------------------------------------------- ai citations chart */
/* Stacked day columns: the share answering a live question against everything
   that is only indexing. Two colours because that distinction is the page's
   whole argument, and a single bar would hide it. */

.aic-chart { display: flex; align-items: flex-end; gap: 8px; min-height: 196px; overflow-x: auto; padding-bottom: 4px; }
.aic-col { flex: 1 1 0; min-width: 34px; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 6px; }
.aic-n { font-weight: 700; font-size: 12.5px; font-variant-numeric: tabular-nums; }
.aic-stack { width: 100%; max-width: 46px; min-height: 4px; display: flex; flex-direction: column-reverse; border-radius: 5px; overflow: hidden; }
.aic-bar { width: 100%; min-height: 3px; }
.aic-bar.answering { background: var(--o-500); }
.aic-bar.other { background: var(--line-2); }
.aic-x { font-size: 11px; color: var(--ink-3); white-space: nowrap; font-variant-numeric: tabular-nums; }

.aic-key { display: flex; gap: 18px; flex-wrap: wrap; margin-top: 14px; font-size: 12.5px; color: var(--ink-2); }
.aic-key i { display: inline-block; width: 11px; height: 11px; border-radius: 3px; margin-right: 6px; vertical-align: -1px; }
.aic-key i.answering { background: var(--o-500); }
.aic-key i.other { background: var(--line-2); }
