/* ============================================
   DEV CIRCLE — APPLICATION SHELL & COMPONENTS

   Every screen in the product is assembled from this file. A page's own
   <style> block should only ever hold something genuinely unique to that
   screen; if a second page would want it, it belongs here.

   Structure:
     1.  App shell (sidebar + main)
     2.  Sidebar navigation
     3.  Page header, breadcrumbs, tabs
     4.  Toolbar (search / filter / bulk actions)
     5.  Surfaces: card, stat, section
     6.  Data table
     7.  Identity: avatar, orbit ring, badges
     8.  Timeline
     9.  Drawer, modal, popover
     10. Forms
     11. Buttons
     12. Empty, loading, skeleton
     13. Command palette
     14. Toast
     15. Member portal shell
     16. Utilities
   ============================================ */

/* ─────────────────────────────────────────────
   1. APP SHELL
   The console is a fixed sidebar beside a scrolling main column. Nothing
   navigates "back" — every destination is one click away at all times.
   ───────────────────────────────────────────── */

.app {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  min-height: 100vh;
}

.app-main {
  min-width: 0;               /* Lets tables scroll instead of stretching */
  display: flex;
  flex-direction: column;
  /* The brand canvas (a photograph or wash) is painted on <body>; this
     surface stays transparent so it shows through. With no canvas set the
     whole window is the canvas colour anyway. */
  background: transparent;
}

.app-body {
  flex: 1;
  padding: var(--sp-6) var(--sp-8) var(--sp-16);
  max-width: var(--max-content);
  width: 100%;
}

/* ─────────────────────────────────────────────
   2. SIDEBAR
   ───────────────────────────────────────────── */

.sidebar {
  position: sticky;
  top: 0;
  z-index: var(--z-sidebar);
  height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--surface-1);
  border-right: 1px solid var(--line-faint);
}

.sidebar-brand {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  height: var(--topbar-h);
  padding: 0 var(--sp-5);
  flex-shrink: 0;
  text-decoration: none;
}
.sidebar-brand:hover { text-decoration: none; }

.brand-mark {
  font-family: var(--font-display);
  font-weight: var(--fw-black);
  font-size: var(--fs-md);
  letter-spacing: -0.03em;
  color: var(--white);
}
.brand-mark span { color: var(--cd-blue); }

/* A circle's own wordmark replaces the product name in the chrome. It is
   capped to the mark's line-height so a large logo cannot push the bar.

   :has() joins .has-logo because the two arrive by different routes. A circle's
   logo is put in by brand.js, which sets the class on the element it fills. The
   platform's own lockup is substituted into the page by middleware/brand.js,
   which replaces what is *inside* the element and so cannot touch its class —
   without this, that mark would render as inline text and sit off the baseline. */
.brand-mark.has-logo,
.brand-mark:has(.brand-logo-img) { display: inline-flex; align-items: center; }
.brand-mark .brand-logo-img {
  height: 26px; width: auto; max-width: 160px; object-fit: contain; display: block;
}

/* One flat ink cannot serve both themes, so the lockup ships twice and the
   theme picks. Default is dark — matching :root in tokens.css — and the light
   variant is switched in wherever light is actually chosen.

   Both classes are written against .brand-logo-img so these rules outweigh the
   sizing rule above, which also sets display. Without that, `display: block`
   there beat a bare `.brand-logo-on-light` on specificity and both inks
   rendered at once — the lockup appeared twice in dark mode, and only there,
   because light mode's :root prefix carried enough weight to win anyway. */
.brand-logo-img.brand-logo-on-light { display: none; }
.brand-logo-img.brand-logo-on-dark { display: block; }

:root[data-theme="light"] .brand-logo-img.brand-logo-on-light { display: block; }
:root[data-theme="light"] .brand-logo-img.brand-logo-on-dark { display: none; }

.brand-badge {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--blue-ink);
  background: var(--blue-dim);
  padding: 2px 6px;
  border-radius: var(--r-sm);
}

/* Search trigger — opens the command palette. Sits above the nav because
   it is the fastest route to anything in the product. */
.sidebar-search {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin: var(--sp-2) var(--sp-4) var(--sp-4);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  color: var(--ash-dim);
  font-size: var(--fs-sm);
  width: calc(100% - var(--sp-8));
  transition: border-color var(--duration-fast) var(--ease-out);
}
.sidebar-search:hover { border-color: var(--line-strong); color: var(--ash); }
.sidebar-search kbd {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ash-dim);
  background: var(--surface-3);
  padding: 1px 5px;
  border-radius: var(--r-sm);
}

.sidebar-nav {
  flex: 1;
  overflow-y: auto;
  padding: 0 var(--sp-3) var(--sp-4);
}

/* Grouping is what turns twelve flat links into a navigable map. */
.nav-group { margin-bottom: var(--sp-5); }

.nav-group-label {
  font-size: 10px;
  font-weight: var(--fw-semibold);
  color: var(--ash-dim);
  text-transform: uppercase;
  letter-spacing: 0.10em;
  padding: 0 var(--sp-3);
  margin-bottom: var(--sp-2);
}

.nav-item {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-md);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--ash);
  text-decoration: none;
  transition: color var(--duration-fast) var(--ease-out),
              background var(--duration-fast) var(--ease-out);
}
.nav-item:hover { color: var(--white); background: var(--tint-1); text-decoration: none; }

.nav-item.active {
  color: var(--white);
  background: var(--cd-blue-dim);
}
/* The active marker reads at a glance from the far edge of the screen. */
.nav-item.active .nav-icon { color: var(--blue-ink); }

.nav-icon {
  width: 16px;
  text-align: center;
  font-size: var(--fs-sm);
  color: var(--ash-dim);
  flex-shrink: 0;
}

.nav-count {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ash-dim);
  background: var(--tint-2);
  padding: 1px 6px;
  border-radius: var(--r-full);
}
.nav-item.active .nav-count { color: var(--blue-ink); background: var(--blue-dim); }

/* User menu pinned to the bottom — account actions are never hunted for. */
.sidebar-foot {
  flex-shrink: 0;
  border-top: 1px solid var(--line-faint);
  padding: var(--sp-3);
  position: relative;
}

.user-button {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  width: 100%;
  padding: var(--sp-2);
  border-radius: var(--r-md);
  text-align: left;
  transition: background var(--duration-fast) var(--ease-out);
}
.user-button:hover { background: var(--tint-1); }

.user-meta { min-width: 0; flex: 1; }
.user-name {
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--white);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.user-role { font-size: var(--fs-xs); color: var(--ash-dim); }

.user-menu {
  display: none;
  position: absolute;
  bottom: calc(100% + var(--sp-1));
  left: var(--sp-3);
  right: var(--sp-3);
  background: var(--surface-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-lg);
  padding: var(--sp-1);
  z-index: var(--z-sidebar);
}
.user-menu.open { display: block; }

/* ─── What is waiting on somebody ──────────────────────────
   The console's bell opens this. Positioned like the account menu above it and
   built from the same parts, because it is the same gesture in the same corner
   — a second visual language for a second dropdown would be a second thing to
   learn for no reason. */
.attention-menu {
  display: none;
  position: absolute;
  bottom: calc(100% + var(--sp-1));
  left: var(--sp-3);
  right: var(--sp-3);
  background: var(--surface-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-lg);
  padding: var(--sp-1);
  z-index: var(--z-sidebar);
}
.attention-menu.open { display: block; }
.attention-menu a {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-3);
  border-radius: var(--r-sm);
  text-decoration: none;
  color: var(--ink);
}
.attention-menu a:hover { background: var(--tint-2); text-decoration: none; }

/* The number first, because it is what the bell was ringing about. */
.attention-count {
  flex-shrink: 0;
  min-width: 22px;
  height: 22px;
  padding: 0 6px;
  border-radius: var(--r-full);
  background: var(--rose-dim);
  color: var(--rose-ink);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  font-variant-numeric: tabular-nums;
  display: flex;
  align-items: center;
  justify-content: center;
}
.attention-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.attention-label { font-size: var(--fs-sm); font-weight: var(--fw-medium); }
.attention-detail { font-size: var(--fs-xs); color: var(--ash-dim); line-height: var(--lh-loose); }
.attention-empty { padding: var(--sp-4); font-size: var(--fs-sm); color: var(--ash-dim); text-align: center; }
.user-menu button, .user-menu a {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  width: 100%;
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  color: var(--ash);
  text-decoration: none;
}
.user-menu button:hover, .user-menu a:hover { background: var(--tint-2); color: var(--white); text-decoration: none; }
.user-menu .danger:hover { color: var(--rose-ink); }

/* Mobile: the sidebar slides over the content instead of eating it. */
.mobile-bar { display: none; }

.sidebar-scrim {
  display: none;
  position: fixed;
  inset: 0;
  background: var(--scrim);
  z-index: calc(var(--z-sidebar) - 1);
}

@media (max-width: 900px) {
  .app { grid-template-columns: minmax(0, 1fr); }

  .mobile-bar {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    height: var(--topbar-h);
    padding: 0 var(--sp-4);
    background: var(--surface-1);
    border-bottom: 1px solid var(--line-faint);
    position: sticky;
    top: 0;
    z-index: var(--z-sticky);
  }

  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    width: var(--sidebar-w);
    transform: translateX(-100%);
    transition: transform var(--duration-normal) var(--ease-out);
    box-shadow: var(--shadow-xl);
  }
  .sidebar.open { transform: translateX(0); }
  .sidebar.open + .sidebar-scrim { display: block; }

  .app-body { padding: var(--sp-5) var(--sp-4) var(--sp-12); }
}

/* ─────────────────────────────────────────────
   3. PAGE HEADER, BREADCRUMBS, TABS
   ───────────────────────────────────────────── */

.page-head {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  background: var(--surface-0);
  border-bottom: 1px solid var(--line-faint);
  padding: var(--sp-5) var(--sp-8) 0;
}
@media (max-width: 900px) {
  .page-head { position: static; padding: var(--sp-5) var(--sp-4) 0; }
}

.breadcrumb {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-xs);
  color: var(--ash-dim);
  margin-bottom: var(--sp-2);
}
.breadcrumb a { color: var(--ash); text-decoration: none; }
.breadcrumb a:hover { color: var(--white); text-decoration: none; }
.breadcrumb .sep { color: var(--ash-dim); opacity: 0.5; }
/* The page title, when it lives in the breadcrumb on a small screen. */
.breadcrumb .current { color: var(--text-1); font-weight: var(--fw-semibold); }

/* On a phone the big desktop page header is replaced by the breadcrumb
   carrying the title — a hero-sized heading is wasted width on a 360px
   column and pushes the content down. Mark the large header
   .hide-on-mobile and add the title span inside the breadcrumb. */
.breadcrumb .mobile-current { display: none; }
@media (max-width: 600px) {
  .breadcrumb .mobile-current { display: inline; }
  .hide-on-mobile { display: none !important; }
}

.page-head-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-4);
  flex-wrap: wrap;
}

.page-title {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--fs-2xl);
  letter-spacing: -0.03em;
}

.page-subtitle {
  color: var(--ash);
  font-size: var(--fs-sm);
  margin-top: var(--sp-1);
  max-width: 60ch;
}

.page-actions { display: flex; align-items: center; gap: var(--sp-2); flex-shrink: 0; }

/* Tabs sit inside the page header so they read as facets of one thing,
   not as separate destinations. */
.tabs {
  display: flex;
  gap: var(--sp-1);
  margin-top: var(--sp-5);
  overflow-x: auto;
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }

.tab {
  padding: var(--sp-2) var(--sp-3);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--ash);
  border-bottom: 2px solid transparent;
  white-space: nowrap;
  text-decoration: none;
  transition: color var(--duration-fast) var(--ease-out);
}
.tab:hover { color: var(--white); text-decoration: none; }
.tab.active { color: var(--white); border-bottom-color: var(--cd-blue); }
.tab .count { font-family: var(--font-mono); font-size: 10px; color: var(--ash-dim); margin-left: var(--sp-1); }

/* ─────────────────────────────────────────────
   4. TOOLBAR
   Search, filters and bulk actions live directly above the data they act
   on, so a filtered view is always self-explaining.
   ───────────────────────────────────────────── */

.toolbar {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  margin-bottom: var(--sp-4);
}

.search-box {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: var(--sp-2) var(--sp-3);
  min-width: 240px;
  flex: 1;
  max-width: 380px;
  transition: border-color var(--duration-fast) var(--ease-out);
}
.search-box:focus-within { border-color: var(--cd-blue); }
.search-box input { flex: 1; font-size: var(--fs-sm); color: var(--white); }
.search-box input::placeholder { color: var(--ash-dim); }
.search-box .icon { color: var(--ash-dim); font-size: var(--fs-sm); }

/* Filter chips are toggles, not a dropdown maze. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--r-full);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  color: var(--ash);
  white-space: nowrap;
  transition: all var(--duration-fast) var(--ease-out);
}
.chip:hover { color: var(--white); border-color: var(--line-strong); }
.chip.active { color: var(--blue-ink); border-color: var(--cd-blue-40); background: var(--cd-blue-dim); }
.chip .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

.result-count {
  font-size: var(--fs-xs);
  color: var(--ash-dim);
  font-family: var(--font-mono);
  margin-left: auto;
}

/* Appears only when rows are selected. */
.bulk-bar {
  display: none;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  background: var(--cd-blue-dim);
  border: 1px solid var(--cd-blue-40);
  border-radius: var(--r-md);
  margin-bottom: var(--sp-3);
  font-size: var(--fs-sm);
}
.bulk-bar.open { display: flex; }
.bulk-bar .count { font-weight: var(--fw-semibold); color: var(--white); }
.bulk-bar .actions { margin-left: auto; display: flex; gap: var(--sp-2); }

/* ─────────────────────────────────────────────
   5. SURFACES
   ───────────────────────────────────────────── */

.card {
  background: var(--surface-2);
  border: 1px solid var(--line-faint);
  border-radius: var(--r-lg);
  padding: var(--sp-5);
}
.card-flush { padding: 0; overflow: hidden; }

.card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--line-faint);
}
.card-title {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-base);
}
.card-body { padding: var(--sp-5); }

.section { margin-bottom: var(--sp-8); }
.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}
.section-title {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-md);
}
.section-link { font-size: var(--fs-sm); color: var(--ash); }
.section-link:hover { color: var(--blue-ink); }

/* Stat tiles: one number, one label, one trend. Nothing else. */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--sp-4);
}

.stat {
  background: var(--surface-2);
  border: 1px solid var(--line-faint);
  border-radius: var(--r-lg);
  padding: var(--sp-5);
}
.stat-label {
  font-size: var(--fs-xs);
  color: var(--ash);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: var(--fw-medium);
  margin-bottom: var(--sp-2);
}
.stat-value {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--fs-2xl);
  letter-spacing: -0.03em;
  line-height: 1;
}
.stat-value .unit { font-size: var(--fs-md); color: var(--ash); font-weight: var(--fw-medium); }
.stat-foot { font-size: var(--fs-xs); color: var(--ash-dim); margin-top: var(--sp-2); }
.stat-foot .up { color: var(--green-ink); }
.stat-foot .down { color: var(--rose-ink); }

/* Figures — numbers stated typographically, separated by hairlines rather
   than boxed into tiles. Used where a few standing counts genuinely help
   read a page; anything that needs comparing belongs on Analytics. */
.figures {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-8);
  padding-bottom: var(--sp-6);
  border-bottom: 1px solid var(--line-faint);
  margin-bottom: var(--sp-8);
}

.figure-value {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--fs-xl);
  letter-spacing: -0.03em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.figure-value .unit { font-size: var(--fs-base); color: var(--ash); font-weight: var(--fw-medium); }
.figure-label { font-size: var(--fs-xs); color: var(--ash); margin-top: var(--sp-2); }

/* Detail pages: identity rail beside the main story. */
.split {
  display: grid;
  grid-template-columns: 300px minmax(0, 1fr);
  gap: var(--sp-6);
  align-items: start;
}
@media (max-width: 1000px) { .split { grid-template-columns: minmax(0, 1fr); } }

.rail { display: flex; flex-direction: column; gap: var(--sp-4); position: sticky; top: calc(var(--topbar-h) + var(--sp-4)); }
@media (max-width: 1000px) { .rail { position: static; } }

/* Key/value list used throughout detail rails. */
.kv { display: flex; flex-direction: column; gap: var(--sp-3); }
.kv-row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-3); }
.kv-key { font-size: var(--fs-xs); color: var(--ash-dim); text-transform: uppercase; letter-spacing: 0.06em; flex-shrink: 0; }
.kv-val { font-size: var(--fs-sm); color: var(--white); text-align: right; min-width: 0; word-break: break-word; }

/* ─────────────────────────────────────────────
   6. DATA TABLE
   ───────────────────────────────────────────── */

.table-shell {
  background: var(--surface-2);
  border: 1px solid var(--line-faint);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.table-scroll { overflow-x: auto; }

.data-table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }

.data-table th {
  text-align: left;
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-xs);
  color: var(--ash);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
  background: var(--surface-2);
}
.data-table th.sortable { cursor: pointer; user-select: none; }
.data-table th.sortable:hover { color: var(--white); }
.data-table th .arrow { opacity: 0.4; margin-left: 2px; }
.data-table th.sorted .arrow { opacity: 1; color: var(--blue-ink); }

.data-table td {
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--line-faint);
  vertical-align: middle;
}
.data-table tbody tr:last-child td { border-bottom: none; }

/* Whole rows are clickable targets into the detail view. */
.data-table tbody tr.row-link { cursor: pointer; transition: background var(--duration-fast) var(--ease-out); }
.data-table tbody tr.row-link:hover td { background: var(--tint-row); }
.data-table tbody tr.selected td { background: var(--cd-blue-dim); }

.col-tight { width: 1%; white-space: nowrap; }
.col-actions { width: 1%; white-space: nowrap; text-align: right; }

/* Row actions stay hidden until the row is hovered, keeping scans clean. */
.row-actions { display: flex; gap: var(--sp-1); justify-content: flex-end; opacity: 0; transition: opacity var(--duration-fast) var(--ease-out); }
tr:hover .row-actions, tr:focus-within .row-actions { opacity: 1; }
@media (hover: none) { .row-actions { opacity: 1; } }

/* The identity cell — avatar, name, and the one qualifier that matters. */
.identity { display: flex; align-items: center; gap: var(--sp-3); min-width: 0; }
.identity-meta { min-width: 0; }
.identity-name {
  font-weight: var(--fw-semibold);
  color: var(--white);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.identity-sub {
  font-size: var(--fs-xs);
  color: var(--ash-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-top: 1px solid var(--line-faint);
  font-size: var(--fs-xs);
  color: var(--ash-dim);
}
.pagination .pages { display: flex; gap: var(--sp-1); align-items: center; }

/* ─────────────────────────────────────────────
   7. IDENTITY: AVATAR, ORBIT RING, BADGES
   ───────────────────────────────────────────── */

.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--cd-blue-dim);
  color: var(--blue-ink);
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--fs-xs);
  flex-shrink: 0;
  text-transform: uppercase;
}
.avatar-sm { width: 24px; height: 24px; font-size: 10px; }
.avatar-lg { width: 56px; height: 56px; font-size: var(--fs-md); }
.avatar-xl { width: 72px; height: 72px; font-size: var(--fs-lg); }
.avatar-gold { background: var(--gold-dim); color: var(--gold-ink); }
.avatar-teal { background: var(--teal-dim); color: var(--teal-ink); }

/* Orbit ring — engagement depth as concentric arcs around the avatar.
   Level 1 is the outermost, faintest ring; level 4 sits closest in. */
.orbit {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.orbit .ring {
  position: absolute;
  border-radius: 50%;
  border: 2px solid transparent;
  pointer-events: none;
}
.orbit .ring:nth-child(1) { width: 118%; height: 118%; border-color: var(--cohort-1); }
.orbit .ring:nth-child(2) { width: 136%; height: 136%; border-color: var(--cohort-2); }
.orbit .ring:nth-child(3) { width: 154%; height: 154%; border-color: var(--cohort-3); }
.orbit .ring:nth-child(4) { width: 172%; height: 172%; border-color: var(--cohort-4); }

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: var(--fw-medium);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 2px 8px;
  border-radius: var(--r-sm);
  white-space: nowrap;
  background: var(--tint-2);
  color: var(--ash);
}
.badge-sandbox    { color: var(--gold-ink); background: var(--gold-dim); }
.badge-production { color: var(--teal-ink); background: var(--teal-dim); }
.badge-active     { color: var(--green-ink); background: var(--green-dim); }
.badge-inactive   { color: var(--ash); background: var(--tint-2); }
.badge-suspended  { color: var(--rose-ink); background: var(--rose-dim); }
.badge-danger     { color: var(--rose-ink); background: var(--rose-dim); }
.badge-warn       { color: var(--gold-ink); background: var(--gold-dim); }
.badge-info       { color: var(--blue-ink); background: var(--blue-dim); }
.badge-violet     { color: var(--violet); background: var(--violet-dim); }

/* Soft, non-mono label for cohorts and free-form tags. */
.tag {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  font-size: var(--fs-xs);
  padding: 2px var(--sp-2);
  border-radius: var(--r-sm);
  background: var(--tint-1);
  color: var(--ash);
  white-space: nowrap;
}
.tag .dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }

.streak {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--fs-sm);
  color: var(--gold-ink);
}

/* ─────────────────────────────────────────────
   8. TIMELINE
   The activity stream is the centre of every profile, so it gets a real
   component rather than a list of rows.
   ───────────────────────────────────────────── */

.timeline { position: relative; padding-left: var(--sp-6); }
.timeline::before {
  content: '';
  position: absolute;
  left: 7px;
  top: 6px;
  bottom: 6px;
  width: 1px;
  background: var(--line);
}

.tl-item { position: relative; padding-bottom: var(--sp-5); }
.tl-item:last-child { padding-bottom: 0; }

.tl-dot {
  position: absolute;
  left: calc(-1 * var(--sp-6) + 2px);
  top: 4px;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--surface-0);
  border: 2px solid var(--cd-blue);
}
.tl-dot.gold  { border-color: var(--cd-gold); }
.tl-dot.teal  { border-color: var(--teal); }
.tl-dot.rose  { border-color: var(--rose); }
.tl-dot.ash   { border-color: var(--ash-dim); }

.tl-head { display: flex; align-items: baseline; gap: var(--sp-2); flex-wrap: wrap; }
.tl-title { font-size: var(--fs-sm); font-weight: var(--fw-medium); color: var(--white); }
.tl-time { font-size: var(--fs-xs); color: var(--ash-dim); margin-left: auto; white-space: nowrap; }
.tl-body { font-size: var(--fs-sm); color: var(--ash); margin-top: var(--sp-1); }

/* Day separators keep long histories readable. */
.tl-divider {
  font-size: var(--fs-xs);
  color: var(--ash-dim);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: var(--fw-medium);
  margin: var(--sp-4) 0 var(--sp-3);
}
.tl-divider:first-child { margin-top: 0; }

/* ─────────────────────────────────────────────
   9. DRAWER, MODAL
   Creating and editing happens in a right-hand drawer, so the list you
   are working against stays visible behind it. Centred modals are kept
   only for destructive confirmations, where losing context is the point.
   ───────────────────────────────────────────── */

.scrim {
  position: fixed;
  inset: 0;
  background: var(--scrim);
  z-index: var(--z-overlay);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--duration-normal) var(--ease-out);
}
.scrim.open { opacity: 1; pointer-events: auto; }

.drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: var(--drawer-w);
  max-width: 100vw;
  background: var(--surface-1);
  border-left: 1px solid var(--line);
  box-shadow: var(--shadow-xl);
  z-index: var(--z-drawer);
  transform: translateX(100%);
  transition: transform var(--duration-normal) var(--ease-out);
  display: flex;
  flex-direction: column;
}
.drawer.open { transform: translateX(0); }
.drawer-lg { width: var(--drawer-w-lg); }

.drawer-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-5);
  border-bottom: 1px solid var(--line-faint);
  flex-shrink: 0;
}
.drawer-title { font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--fs-lg); }

/* ─── Theme rail sections ──────────────────────────────────
   The appearance controls are a lot at once — colours, type, shape, imagery,
   layout and the opening and closing screens. Grouping them into collapsing
   sections means an author sees headings and opens the part they came for,
   rather than a wall of controls. Each section's summary says what is in it;
   a dot marks a section that is already doing something non-default, so a
   collapsed rail still shows where the customisation lives. */
.theme-section {
  border-top: 1px solid var(--line-faint);
  padding: var(--sp-2) 0;
}
.theme-section:first-child { border-top: none; }
.theme-section > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) 0;
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-sm);
  color: var(--white);
  user-select: none;
}
.theme-section > summary::-webkit-details-marker { display: none; }
.theme-section > summary:hover { color: var(--cd-blue); }
.theme-section > summary .section-caret {
  margin-left: auto;
  color: var(--ash-dim);
  transition: transform var(--duration-fast) var(--ease-out);
  flex-shrink: 0;
}
.theme-section[open] > summary .section-caret { transform: rotate(90deg); }
.theme-section > summary .section-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--cd-blue);
  flex-shrink: 0;
  /* Hidden unless the section carries a custom value; JS sets [data-set] */
  display: none;
}
.theme-section > summary[data-has-custom] .section-dot { display: inline-block; }
.theme-section > summary .section-sub {
  font-weight: var(--fw-regular);
  font-size: var(--fs-xs);
  color: var(--ash-dim);
}
.theme-section .section-body { padding-top: var(--sp-2); }
.theme-section .section-body .card-title { display: none; }
.theme-section .section-body .field:last-child { margin-bottom: 0; }
.drawer-sub { font-size: var(--fs-xs); color: var(--ash); margin-top: 2px; }
.drawer-body { flex: 1; overflow-y: auto; padding: var(--sp-5); }
.drawer-foot {
  display: flex;
  justify-content: flex-end;
  gap: var(--sp-2);
  padding: var(--sp-4) var(--sp-5);
  border-top: 1px solid var(--line-faint);
  background: var(--surface-1);
  flex-shrink: 0;
}

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: var(--r-md);
  color: var(--ash);
  font-size: var(--fs-md);
  line-height: 1;
  flex-shrink: 0;
  transition: all var(--duration-fast) var(--ease-out);
}
.icon-btn:hover { color: var(--white); background: var(--tint-2); }

.modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -48%);
  width: 420px;
  max-width: calc(100vw - var(--sp-8));
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-xl);
  z-index: var(--z-drawer);
  padding: var(--sp-6);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-out);
}
.modal.open { opacity: 1; pointer-events: auto; transform: translate(-50%, -50%); }
.modal-title { font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--fs-md); margin-bottom: var(--sp-2); }
.modal-text { font-size: var(--fs-sm); color: var(--ash); margin-bottom: var(--sp-5); }
.modal-foot { display: flex; justify-content: flex-end; gap: var(--sp-2); }

/* ─────────────────────────────────────────────
   10. FORMS
   ───────────────────────────────────────────── */

.field { margin-bottom: var(--sp-4); }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-3); }
@media (max-width: 560px) { .field-row { grid-template-columns: 1fr; } }

.label {
  display: block;
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  color: var(--ash);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: var(--sp-2);
}

.input {
  width: 100%;
  background: var(--surface-0);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: var(--sp-3);
  color: var(--white);
  font-size: var(--fs-sm);
  transition: border-color var(--duration-fast) var(--ease-out);
}
.input::placeholder { color: var(--ash-dim); }
.input:focus { border-color: var(--cd-blue); }
.input:disabled { opacity: 0.5; cursor: not-allowed; }
/* Read-only fields are facts rather than form controls (the locked phone
   credential): dimmed like disabled but still selectable/copyable. */
.input[readonly] { background: var(--surface-1); color: var(--text-2); cursor: default; }
select.input { cursor: pointer; appearance: none; background-image: linear-gradient(45deg, transparent 50%, var(--ash) 50%), linear-gradient(135deg, var(--ash) 50%, transparent 50%); background-position: calc(100% - 16px) 50%, calc(100% - 11px) 50%; background-size: 5px 5px, 5px 5px; background-repeat: no-repeat; padding-right: var(--sp-8); }
textarea.input { min-height: 90px; line-height: var(--lh-normal); }

.hint { font-size: var(--fs-xs); color: var(--ash-dim); margin-top: var(--sp-2); }
.error-text { font-size: var(--fs-xs); color: var(--rose-ink); margin-top: var(--sp-2); }

/* Segmented control — for two or three mutually exclusive choices that
   deserve to be visible rather than hidden in a select. */
.segmented {
  display: inline-flex;
  background: var(--surface-0);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 2px;
  gap: 2px;
}
.segmented button {
  padding: var(--sp-2) var(--sp-4);
  border-radius: var(--r-sm);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  color: var(--ash);
  transition: all var(--duration-fast) var(--ease-out);
}
.segmented button.active { background: var(--cd-blue); color: var(--on-accent); }

/* Consent and preference toggles. */
.switch-row {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-4) 0;
  border-bottom: 1px solid var(--line-faint);
}
.switch-row:last-child { border-bottom: none; }
.switch-meta { flex: 1; min-width: 0; }
.switch-name { font-size: var(--fs-sm); font-weight: var(--fw-medium); }
.switch-desc { font-size: var(--fs-xs); color: var(--ash-dim); margin-top: 2px; }

.switch {
  position: relative;
  width: 38px;
  height: 22px;
  border-radius: var(--r-full);
  background: var(--surface-4);
  flex-shrink: 0;
  transition: background var(--duration-fast) var(--ease-out);
}
.switch::after {
  content: '';
  position: absolute;
  top: 3px;
  left: 3px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--ash);
  transition: transform var(--duration-fast) var(--ease-out), background var(--duration-fast) var(--ease-out);
}
.switch.on { background: var(--cd-blue); }
.switch.on::after { transform: translateX(16px); background: var(--on-accent); }

.check {
  width: 16px;
  height: 16px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  color: transparent;
  transition: all var(--duration-fast) var(--ease-out);
}
.check.on { background: var(--cd-blue); border-color: var(--cd-blue); color: var(--on-accent); }

/* ─────────────────────────────────────────────
   11. BUTTONS
   ───────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  padding: var(--sp-2) var(--sp-4);
  border-radius: var(--r-md);
  transition: all var(--duration-fast) var(--ease-out);
  white-space: nowrap;
  text-decoration: none;
  border: 1px solid transparent;
}
.btn:hover { text-decoration: none; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

.btn-primary { background: var(--cd-blue); color: var(--on-accent); }
.btn-primary:hover:not(:disabled) { background: var(--cd-blue-deep); }

.btn-secondary { background: var(--surface-3); color: var(--ash); border-color: var(--line); }
.btn-secondary:hover:not(:disabled) { color: var(--white); border-color: var(--line-strong); }

.btn-ghost { color: var(--ash); }
.btn-ghost:hover:not(:disabled) { color: var(--white); background: var(--tint-2); }

.btn-gold { background: var(--cd-gold); color: #1A1A2E; font-weight: var(--fw-semibold); }
.btn-gold:hover:not(:disabled) { background: var(--cd-gold-deep); }

.btn-danger { background: var(--rose); color: var(--on-accent); }
.btn-danger:hover:not(:disabled) { filter: brightness(1.1); }

.btn-sm { font-size: var(--fs-xs); padding: var(--sp-1) var(--sp-3); }
.btn-lg { font-size: var(--fs-base); padding: var(--sp-3) var(--sp-6); }
.btn-block { width: 100%; }

/* The busy state shared by every in-flight action (see busy() in api.js): the
   button disables, shows a spinner beside the busy label, and the label area
   is fixed-width so the button does not jump around between its resting label
   and a shorter "Saving…". */
.btn.is-loading { cursor: progress; }
.btn.is-loading .spinner { width: 14px; height: 14px; flex: none; }
.btn.is-loading .busy-label { display: inline-flex; align-items: center; min-width: 4ch; text-align: left; }

/* ─────────────────────────────────────────────
   12. EMPTY, LOADING
   An empty state always names the thing that is missing and offers the
   action that fills it.
   ───────────────────────────────────────────── */

.empty {
  text-align: center;
  padding: var(--sp-12) var(--sp-6);
  color: var(--ash-dim);
}
.empty-icon { font-size: var(--fs-2xl); opacity: 0.4; margin-bottom: var(--sp-3); }
.empty-title { font-family: var(--font-display); font-weight: var(--fw-semibold); font-size: var(--fs-base); color: var(--ash); margin-bottom: var(--sp-2); }
.empty-text { font-size: var(--fs-sm); max-width: 42ch; margin: 0 auto var(--sp-5); }

.skeleton {
  background: linear-gradient(90deg, var(--tint-1) 25%, var(--tint-3) 37%, var(--tint-1) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.4s ease infinite;
  border-radius: var(--r-sm);
  height: 12px;
}
@keyframes shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* Skeleton rows for list/timeline placeholders — a leading avatar with a
   couple of text lines, so the loading shape reads as the content to come. */
.skeleton-row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) 0;
}
.skeleton-row + .skeleton-row { border-top: 1px solid var(--line-faint); }
.skeleton-avatar { width: 36px; height: 36px; border-radius: 50%; flex: none; }
.skeleton-row-lines { flex: 1; display: flex; flex-direction: column; gap: var(--sp-2); }

.spinner {
  width: 16px;
  height: 16px;
  border: 2px solid var(--line);
  border-top-color: var(--cd-blue);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
  display: inline-block;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ─────────────────────────────────────────────
   13. COMMAND PALETTE
   ⌘K reaches every destination and every member without navigating.
   ───────────────────────────────────────────── */

.palette {
  position: fixed;
  top: 12vh;
  left: 50%;
  transform: translateX(-50%) scale(0.98);
  width: 560px;
  max-width: calc(100vw - var(--sp-8));
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-xl);
  z-index: var(--z-palette);
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-out);
}
.palette.open { opacity: 1; pointer-events: auto; transform: translateX(-50%) scale(1); }

.palette-input {
  width: 100%;
  padding: var(--sp-4) var(--sp-5);
  font-size: var(--fs-md);
  color: var(--text);
  border-bottom: 1px solid var(--line-faint);
}
.palette-input::placeholder { color: var(--ash-dim); }

.palette-list { max-height: 46vh; overflow-y: auto; padding: var(--sp-2); }
.palette-group { font-size: 10px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--ash-dim); padding: var(--sp-3) var(--sp-3) var(--sp-2); }
.palette-item {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  width: 100%;
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-md);
  font-size: var(--fs-sm);
  color: var(--ash);
  text-align: left;
}
.palette-item .sub { margin-left: auto; font-size: var(--fs-xs); color: var(--ash-dim); }
.palette-item.active { background: var(--cd-blue-dim); color: var(--white); }

/* ─────────────────────────────────────────────
   14. TOAST
   ───────────────────────────────────────────── */

.toast-stack {
  position: fixed;
  bottom: var(--sp-6);
  right: var(--sp-6);
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  align-items: flex-end;
}

.toast {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  background: var(--surface-3);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-lg);
  animation: toast-in var(--duration-normal) var(--ease-out);
  max-width: 360px;
}
.toast .mark { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
.toast-success .mark { background: var(--emerald); }
.toast-error   .mark { background: var(--rose); }
.toast-warning .mark { background: var(--cd-gold); }
@keyframes toast-in { from { transform: translateY(8px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }

/* ─────────────────────────────────────────────
   15. MEMBER PORTAL SHELL
   Members get a top bar and a single reading column: five destinations
   do not justify a sidebar, and the focus belongs on one action at a time.
   ───────────────────────────────────────────── */

.portal { min-height: 100vh; display: flex; flex-direction: column; }

.portal-bar {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  background: var(--surface-1);
  border-bottom: 1px solid var(--line-faint);
}
.portal-bar-inner {
  max-width: var(--max-reading);
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  height: var(--topbar-h);
  padding: 0 var(--sp-5);
}
.portal-links { display: flex; gap: var(--sp-1); margin-left: var(--sp-4); flex: 1; overflow-x: auto; scrollbar-width: none; }
.portal-links::-webkit-scrollbar { display: none; }

.portal-link {
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-md);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--ash);
  white-space: nowrap;
  text-decoration: none;
}
.portal-link:hover { color: var(--white); background: var(--tint-1); text-decoration: none; }
.portal-link.active { color: var(--white); background: var(--cd-blue-dim); }

/* The current page label shown in the bar on a phone; desktop shows the full
   link row instead. */
.portal-current {
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--text-1);
  white-space: nowrap;
}
.mobile-only { display: none; }

/* Thumb navigation: a fixed bottom tab bar on phones, hidden where the link
   row fits in the top bar. */
.portal-tabbar { display: none; }

.portal-body {
  flex: 1;
  max-width: var(--max-reading);
  width: 100%;
  margin: 0 auto;
  padding: var(--sp-8) var(--sp-5) var(--sp-16);
}
@media (max-width: 640px) {
  .portal-body { padding: var(--sp-6) var(--sp-4) calc(var(--sp-12) + 64px); }

  /* The link row moves to the bottom tab bar; the bar instead names the page,
     so it is the member's mobile breadcrumb and the in-content breadcrumb is
     hidden to avoid showing "Home / Page" twice. */
  .portal-links { display: none; }
  .portal-current { display: inline-block; flex: 1; text-align: center; }
  .mobile-only { display: inline; }
  .portal-body .breadcrumb { display: none; }

  .portal-tabbar {
    display: flex;
    position: fixed;
    bottom: 0; left: 0; right: 0;
    z-index: var(--z-sticky);
    background: var(--surface-1);
    border-top: 1px solid var(--line-faint);
    padding: var(--sp-1) 0 calc(var(--sp-1) + env(safe-area-inset-bottom, 0px));
  }
  .portal-tab {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    padding: var(--sp-1) 0;
    color: var(--ash-dim);
    text-decoration: none;
    font-size: 10px;
    font-weight: var(--fw-medium);
  }
  .portal-tab-icon { display: flex; align-items: center; justify-content: center; height: 22px; }
  .portal-tab.active { color: var(--cd-blue); }
  .portal-tab.active .portal-tab-icon svg { stroke: var(--cd-blue); }
}

/* Notification bell with unread marker. */
.bell { position: relative; }
.bell .unread {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--rose);
  border: 2px solid var(--surface-1);
}

/* Account menu — profile and consent settings live here rather than eating a
   slot in the bar, which belongs to the things a developer came to do. */
.account { position: relative; flex-shrink: 0; }
.account-button {
  display: flex;
  align-items: center;
  padding: var(--sp-1);
  border-radius: var(--r-full);
  transition: opacity var(--duration-fast) var(--ease-out);
}
.account-button:hover { opacity: 0.8; }

.account-menu {
  display: none;
  position: absolute;
  top: calc(100% + var(--sp-2));
  right: 0;
  min-width: 220px;
  background: var(--surface-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-lg);
  padding: var(--sp-1);
  z-index: var(--z-sidebar);
}
.account-menu.open { display: block; }
.account-head { padding: var(--sp-3); border-bottom: 1px solid var(--line-faint); margin-bottom: var(--sp-1); }
.account-name { font-size: var(--fs-sm); font-weight: var(--fw-semibold); }
.account-mail { font-size: var(--fs-xs); color: var(--ash-dim); overflow-wrap: anywhere; }
.account-menu a, .account-menu button {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  width: 100%;
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  color: var(--ash);
  text-decoration: none;
  text-align: left;
}
.account-menu a:hover, .account-menu button:hover { background: var(--tint-2); color: var(--white); text-decoration: none; }
.account-menu .danger:hover { color: var(--rose-ink); }

/* ── Developer-facing pieces ─────────────────────────────── */

/* The masthead. A developer arriving should see who the product thinks they
   are before anything else — name, company, and the two facts that define
   their relationship with the platform. */
.masthead {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  padding: var(--sp-8) 0 var(--sp-6);
}
.masthead-name {
  font-family: var(--font-display);
  font-weight: var(--fw-black);
  font-size: var(--fs-3xl);
  letter-spacing: -0.04em;
  line-height: 1.05;
}
.masthead-line {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  margin-top: var(--sp-3);
  font-size: var(--fs-sm);
  color: var(--text-2);
}
@media (max-width: 600px) {
  .masthead { gap: var(--sp-4); padding-top: var(--sp-6); }
  .masthead-name { font-size: var(--fs-2xl); }
}

/* Engagement, twelve weeks at a time. Deliberately a record rather than a
   score: one cell per day, darker where more happened. Precise and earned —
   the opposite of a badge wall, and legible to anyone who has used a commit
   graph. */
.heat {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  grid-auto-flow: column;
  grid-template-rows: repeat(7, 1fr);
  gap: 3px;
  max-width: 100%;
}
.heat-cell {
  aspect-ratio: 1;
  border-radius: 2px;
  background: var(--tint-2);
  min-width: 0;
}
.heat-cell.l1 { background: var(--blue-line); }
.heat-cell.l2 { background: var(--cd-blue); opacity: 0.75; }
.heat-cell.l3 { background: var(--cd-blue); }
.heat-cell.gold { background: var(--cd-gold); }

.heat-legend {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-top: var(--sp-3);
  font-size: var(--fs-xs);
  color: var(--text-3);
}
.heat-key { display: inline-flex; gap: 3px; align-items: center; }
.heat-key span { width: 10px; height: 10px; border-radius: 2px; }

/* A number stated with enough size to be read as a fact, not a label. */
.big-figure {
  font-family: var(--font-display);
  font-weight: var(--fw-black);
  font-size: var(--fs-3xl);
  letter-spacing: -0.04em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.big-figure .unit { font-size: var(--fs-md); font-weight: var(--fw-medium); color: var(--text-2); letter-spacing: 0; }

/* Survey invitations carry weight: this is the main thing we ask of a
   developer, so it is a real surface rather than another list row. */
.invite {
  display: block;
  padding: var(--sp-6);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  background: var(--surface-2);
  margin-bottom: var(--sp-3);
  text-decoration: none;
  transition: border-color var(--duration-fast) var(--ease-out),
              transform var(--duration-fast) var(--ease-out),
              box-shadow var(--duration-fast) var(--ease-out);
}
.invite:hover {
  text-decoration: none;
  border-color: var(--blue-line);
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
}
.invite-title { font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--fs-md); margin-bottom: var(--sp-2); }
.invite-desc { font-size: var(--fs-sm); color: var(--text-2); line-height: var(--lh-loose); margin-bottom: var(--sp-4); }
.invite-foot { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.invite-cost { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--text-3); }

/* The integration journey: sandbox → production, stated as a real position
   rather than a badge. This is the fact a developer cares most about. */
.journey {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin: var(--sp-4) 0;
}
.journey-step {
  flex: 1;
  padding: var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  font-size: var(--fs-xs);
  color: var(--ash-dim);
  text-align: center;
  position: relative;
}
.journey-step .step-name { font-weight: var(--fw-semibold); color: var(--ash); display: block; }
.journey-step.done { border-color: var(--teal); color: var(--teal-ink); }
.journey-step.done .step-name { color: var(--teal-ink); }
.journey-step.current { border-color: var(--gold-ink); background: var(--gold-dim); }
.journey-step.current .step-name { color: var(--gold-ink); }
.journey-arrow { color: var(--ash-dim); flex-shrink: 0; font-size: var(--fs-xs); }
@media (max-width: 560px) { .journey { flex-direction: column; align-items: stretch; } .journey-arrow { display: none; } }

/* A row in any member-facing list: survey, session, reward, submission. */
.row-item {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-4) 0;
  border-bottom: 1px solid var(--line-faint);
  text-decoration: none;
}
.row-item:last-child { border-bottom: none; }
.row-item:hover { text-decoration: none; }
.row-item-title { font-size: var(--fs-sm); font-weight: var(--fw-medium); color: var(--white); }
.row-item-meta { font-size: var(--fs-xs); color: var(--ash-dim); margin-top: 2px; }

/* Where a scheduled session sits against the hours the member chose. */
.clash { color: var(--gold-ink); }

.when-chip {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--blue-ink);
  background: var(--cd-blue-dim);
  padding: var(--sp-1) var(--sp-2);
  border-radius: var(--r-sm);
  white-space: nowrap;
  flex-shrink: 0;
}

/* Circles and cohorts a member belongs to. This decides which surveys and
   sessions reach them, so it is shown to them, not only to the admin. */
.membership { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center; }

/* Quoting the member's own words back to them — their feedback, their
   complaint — with what happened to it. */
.submission {
  padding: var(--sp-5) 0;
  border-bottom: 1px solid var(--line-faint);
}
.submission:last-child { border-bottom: none; }
.submission-text { font-size: var(--fs-sm); line-height: var(--lh-loose); margin-bottom: var(--sp-3); }
.submission-meta { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; font-size: var(--fs-xs); color: var(--ash-dim); }

/* The single most important thing a member should do next. */
.next-action {
  background: linear-gradient(135deg, var(--cd-blue-dim), transparent 70%), var(--surface-2);
  border: 1px solid var(--cd-blue-40);
  border-radius: var(--r-lg);
  padding: var(--sp-6);
  margin-bottom: var(--sp-6);
}
.next-action .eyebrow {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--blue-ink);
  font-weight: var(--fw-semibold);
  margin-bottom: var(--sp-2);
}
.next-action .headline { font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--fs-lg); margin-bottom: var(--sp-2); }
.next-action .detail { font-size: var(--fs-sm); color: var(--ash); margin-bottom: var(--sp-5); }

/* ─────────────────────────────────────────────
   16. UTILITIES
   ───────────────────────────────────────────── */

.row { display: flex; align-items: center; gap: var(--sp-3); }
.row-tight { display: flex; align-items: center; gap: var(--sp-2); }
/* The control every paged feed ends with. Centred and quiet: it is the end of
   the list, not an action anybody came for. */
.load-more { display: flex; justify-content: center; margin-top: var(--sp-5); }
.load-more:empty { display: none; }
/* The chevron points at what it fetches — down the page, not along it. */
.load-more svg { transform: rotate(90deg); }
.load-more .btn { animation: load-more-in var(--duration-normal) var(--ease-out); }
@keyframes load-more-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .load-more .btn { animation: none; } }

.stack { display: flex; flex-direction: column; gap: var(--sp-4); }
.stack-tight { display: flex; flex-direction: column; gap: var(--sp-2); }
.spacer { flex: 1; }
.wrap { flex-wrap: wrap; }

.muted { color: var(--ash); }
.dim { color: var(--ash-dim); }
.mono { font-family: var(--font-mono); }
.tnum { font-variant-numeric: tabular-nums; }
.truncate { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.text-xs { font-size: var(--fs-xs); }
.text-sm { font-size: var(--fs-sm); }
.text-right { text-align: right; }
.nowrap { white-space: nowrap; }

.mt-0 { margin-top: 0; }
.mt-2 { margin-top: var(--sp-2); }
.mt-4 { margin-top: var(--sp-4); }
.mt-6 { margin-top: var(--sp-6); }
.mb-2 { margin-bottom: var(--sp-2); }
.mb-4 { margin-bottom: var(--sp-4); }
.mb-6 { margin-bottom: var(--sp-6); }

.grid-2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--sp-4); }
.grid-3 { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--sp-4); }

.hide { display: none !important; }
@media (max-width: 700px) { .hide-sm { display: none !important; } }

/* Progress bar, used by surveys and cohort previews. */
.progress { height: 4px; background: var(--tint-3); border-radius: var(--r-full); overflow: hidden; }
.progress .fill { height: 100%; background: var(--cd-blue); border-radius: var(--r-full); transition: width var(--duration-normal) var(--ease-out); }
.progress .fill.gold { background: var(--cd-gold); }

/* ─── Criteria builder ──────────────────────────────────────
   One row per criterion: what to test, how, and against what. The value
   control is whatever the field's type calls for, so the row has to tolerate
   a select, a number box or a plain input sitting in the same slot. */
.criterion {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-2);
}
.criterion .input { padding: 6px 8px; font-size: var(--fs-xs); }
.criterion-field { flex: 1 1 40%; min-width: 0; }
.criterion-op { flex: 0 0 auto; width: 118px; }
.criterion-value { flex: 1 1 40%; min-width: 0; display: flex; }
.criterion-value .input { width: 100%; }

.criterion-empty {
  font-size: var(--fs-xs);
  color: var(--ash-dim);
  font-style: italic;
  padding: 6px 0;
}

.criterion-remove {
  flex: 0 0 auto;
  background: none;
  border: none;
  color: var(--ash-dim);
  cursor: pointer;
  font-size: 18px;
  line-height: 1;
  padding: 2px 6px;
  border-radius: var(--r-sm);
}
.criterion-remove:hover { color: var(--rose); background: var(--rose-dim, rgba(225,29,72,0.10)); }
.criterion-remove:focus-visible { outline: 2px solid var(--cd-blue); outline-offset: 1px; }

@media (max-width: 640px) {
  .criterion { flex-wrap: wrap; }
  .criterion-field, .criterion-value { flex: 1 1 100%; }
  .criterion-op { flex: 1 1 auto; width: auto; }
}

/* The question a verbatim answered. Without it, "about a week" says nothing —
   so it sits above the quote, quieter than the words the member chose. */
.fb-prompt {
  font-size: var(--fs-xs);
  color: var(--ash-dim);
  margin-bottom: var(--sp-1);
}
.fb-item.survey { border-left: 2px solid var(--cd-blue-40, var(--cd-blue)); }
.quote-prompt { font-size: var(--fs-xs); color: var(--ash-dim); margin-bottom: 2px; }

/* ─── Questions: the evidence base ──────────────────────────
   Answers read together under the question that drew them out. The developer
   leads each answer, because comparing who said what is the whole reason to
   read them side by side rather than as a stream. */
.q-card {
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  margin-bottom: var(--sp-3);
  background: var(--surface-2);
  overflow: hidden;
}
.q-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-5);
  cursor: pointer;
}
.q-head:hover { background: var(--surface-2, rgba(160,160,184,0.03)); }
.q-text {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-md);
  letter-spacing: -0.01em;
  flex: 1;
  min-width: 0;
}
.q-facts {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  flex-shrink: 0;
  font-size: var(--fs-xs);
  color: var(--ash-dim);
}
/* The number that matters: distinct developers, not messages */
.q-count {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--fs-lg);
  color: var(--cd-blue);
  letter-spacing: -0.02em;
}
.q-repeat, .q-ext {
  font-size: 10px;
  font-family: var(--font-mono);
  padding: 2px 6px;
  border-radius: var(--r-sm);
  background: rgba(160,160,184,0.08);
  color: var(--ash);
}
.q-ext { background: var(--cd-blue-dim); color: var(--blue-ink, var(--cd-blue)); }

.q-answers { display: none; }
.q-answers.open { display: block; border-top: 1px solid var(--line); }

.q-occasions {
  padding: var(--sp-2) var(--sp-5);
  font-size: var(--fs-xs);
  color: var(--ash-dim);
  border-bottom: 1px solid var(--line);
}

.q-answer {
  display: flex;
  gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--line);
}
.q-answer:last-child { border-bottom: none; }
.q-who {
  flex: 0 0 140px;
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--white);
  text-decoration: none;
}
.q-who:hover { color: var(--cd-blue); }
.q-body { flex: 1; min-width: 0; }
.q-quote { font-size: var(--fs-sm); line-height: 1.55; margin-bottom: var(--sp-1); }
.q-meta {
  display: flex;
  gap: var(--sp-3);
  flex-wrap: wrap;
  font-size: var(--fs-xs);
  color: var(--ash-dim);
}

@media (max-width: 640px) {
  .q-head { flex-wrap: wrap; }
  .q-answer { flex-direction: column; gap: var(--sp-1); }
  .q-who { flex: none; }
}

/* ─── Everything: one developer, whole ──────────────────────
   What they did and what they said in one stream. Said entries carry weight,
   because their words are the thing worth reading; milestones stay quiet and
   act as the spine the words hang from. */
.ev-summary {
  display: flex;
  gap: var(--sp-5);
  flex-wrap: wrap;
  padding: 0 0 var(--sp-4);
  margin-bottom: var(--sp-4);
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-xs);
  color: var(--ash-dim);
}
.ev-summary strong {
  font-family: var(--font-display);
  font-size: var(--fs-md);
  color: var(--white);
  margin-right: 4px;
}

.ev { display: flex; gap: var(--sp-4); padding: var(--sp-3) 0; }
.ev-when {
  flex: 0 0 76px;
  font-size: var(--fs-xs);
  color: var(--ash-dim);
  font-family: var(--font-mono);
  padding-top: 2px;
}
.ev-body { flex: 1; min-width: 0; }

.ev-did .ev-line, .ev-sent .ev-line { font-size: var(--fs-sm); color: var(--ash); }
.ev-detail { color: var(--ash-dim); }
.ev-sent { opacity: .72; }

.ev-said {
  border-left: 2px solid var(--cd-blue);
  padding-left: var(--sp-4);
  margin: var(--sp-2) 0 var(--sp-2) calc(76px + var(--sp-4));
}
.ev-said .ev-when { display: none; }
.ev-prompt { font-size: var(--fs-xs); color: var(--ash-dim); margin-bottom: 2px; }
.ev-quote { font-size: var(--fs-sm); line-height: 1.55; margin-bottom: var(--sp-1); }
.ev-meta { display: flex; gap: var(--sp-3); flex-wrap: wrap; font-size: var(--fs-xs); color: var(--ash-dim); }
.ev-meta a { color: var(--cd-blue); text-decoration: none; }
.ev-meta a:hover { text-decoration: underline; }

@media (max-width: 640px) {
  .ev { flex-direction: column; gap: 2px; }
  .ev-when { flex: none; }
  .ev-said { margin-left: 0; }
}
.inline-field { display:flex; align-items:center; gap:var(--sp-2); font-size:var(--fs-xs); color:var(--ash-dim); }
.inline-field .input { width:auto; padding:var(--sp-1) var(--sp-2); font-size:var(--fs-xs); }
.q-context { font-weight:400; color:var(--ash-dim); font-size:var(--fs-xs); }
.seg { display:inline-flex; border:1px solid var(--line); border-radius:var(--r-md); overflow:hidden; }
.seg-btn { background:none; border:none; padding:var(--sp-1) var(--sp-3); font-size:var(--fs-xs); color:var(--ash); cursor:pointer; font-family:var(--font-body); }
.seg-btn.active { background:var(--cd-blue-dim); color:var(--blue-ink, var(--cd-blue)); }
.data-table th[data-sort] { cursor:pointer; user-select:none; white-space:nowrap; }
.data-table th[data-sort]:hover { color:var(--white); }
.data-table th.sorted { color:var(--cd-blue); }
.data-table tr.group-row td { background: var(--cd-blue-dim); padding: var(--sp-2) var(--sp-3); }
.group-label { font-family: var(--font-display); font-weight: var(--fw-semibold); font-size: var(--fs-sm); }
.group-count { font-size: var(--fs-xs); color: var(--ash-dim); margin-left: var(--sp-3); }
/* A notification that goes somewhere reads as something you can open */
.note.actionable { cursor: pointer; }
.note.actionable:hover { background: var(--cd-blue-dim); }
.note.actionable:focus-visible { outline: 2px solid var(--cd-blue); outline-offset: -2px; }
.note-go { color: var(--ash-dim); flex-shrink: 0; align-self: center; }
.note.actionable:hover .note-go { color: var(--cd-blue); }

/* ─── Circle switcher ───────────────────────────────────────
   Which workspace you are in, sat with your account. Named in full rather
   than shown as an icon: the one thing this control has to communicate is
   where you are, and an icon cannot say "Merchant Circle". */
.circle-switch { position: relative; margin-bottom: var(--sp-2); }

.circle-button {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  width: 100%;
  padding: var(--sp-2) var(--sp-3);
  background: none;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  cursor: pointer;
  text-align: left;
  font-family: var(--font-body);
  transition: border-color var(--duration-fast) var(--ease-out);
}
.circle-button:hover { border-color: var(--line-strong); }
.circle-button:focus-visible { outline: 2px solid var(--cd-blue); outline-offset: 1px; }

.circle-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.circle-current { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.circle-label {
  font-size: 10px;
  color: var(--ash-dim);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.circle-name {
  font-size: var(--fs-sm);
  color: var(--white);
  font-weight: var(--fw-medium);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.circle-caret { color: var(--ash-dim); flex-shrink: 0; display: flex; transform: rotate(90deg); }

/* The menu opens upward: the control sits at the foot of the sidebar */
.circle-menu {
  display: none;
  position: absolute;
  bottom: calc(100% + 6px);
  left: 0;
  right: 0;
  z-index: 50;
  background: var(--surface-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.32);
  padding: var(--sp-1);
  max-height: 60vh;
  overflow-y: auto;
}
.circle-menu.open { display: block; }

.circle-menu-head {
  font-size: 10px;
  color: var(--ash-dim);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding: var(--sp-2) var(--sp-3) var(--sp-1);
}

.circle-option {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  width: 100%;
  padding: var(--sp-2) var(--sp-3);
  background: none;
  border: none;
  border-radius: var(--r-sm);
  cursor: pointer;
  text-align: left;
  font-family: var(--font-body);
}
.circle-option:hover { background: var(--cd-blue-dim); }
.circle-option:focus-visible { outline: 2px solid var(--cd-blue); outline-offset: -2px; }

/* A tick, not a highlight: which one you are in should be readable at a
   glance and survive being colour-blind or looking away. */
.circle-check {
  width: 14px;
  flex-shrink: 0;
  color: var(--cd-blue);
  font-size: var(--fs-sm);
}
.circle-option-body { display: flex; flex-direction: column; min-width: 0; }
.circle-option-name {
  font-size: var(--fs-sm);
  color: var(--white);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.circle-option.current .circle-option-name { font-weight: var(--fw-medium); }
.circle-option-meta { font-size: var(--fs-xs); color: var(--ash-dim); }

.circle-menu-divider { height: 1px; background: var(--line); margin: var(--sp-1) 0; }

.circle-manage {
  display: block;
  padding: var(--sp-2) var(--sp-3);
  font-size: var(--fs-sm);
  color: var(--ash);
  text-decoration: none;
  border-radius: var(--r-sm);
}
.circle-manage:hover { background: var(--cd-blue-dim); color: var(--white); }

/* ─── Survey controls ────────────────────────────────────────
   The controls a member answers with, and the same ones the builder previews
   with. They live here rather than in either page because a preview that is
   styled separately from the real thing is a preview of something else.

   Sizing is set by the smallest screen a developer will answer on: hit targets
   stay above 44px, and nothing depends on hover to be discoverable. Everything
   colours from --cd-blue, which a themed survey overrides per page, so a
   circle's accent reaches every control without a second set of rules.
   ─────────────────────────────────────────────────────────── */

.sv-ask {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--fs-xl);
  letter-spacing: -0.02em;
  line-height: var(--lh-tight);
  margin-bottom: var(--sp-3);
}
.sv-note { color: var(--ash); font-size: var(--fs-sm); line-height: var(--lh-loose); margin-bottom: var(--sp-5); }
.sv-ask + .sv-control, .sv-note + .sv-control { margin-top: var(--sp-6); }
.sv-number-kicker { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--cd-blue); margin-bottom: var(--sp-3); }

/* An asterisk alone has never told anyone anything, so it is always paired
   with a legend where the questions start. */
.sv-required { color: var(--rose-ink); margin-left: 4px; font-weight: var(--fw-regular); }

.sv-options { display: flex; flex-direction: column; gap: var(--sp-2); }

.sv-option {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  width: 100%;
  min-height: 48px;
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: transparent;
  color: inherit;
  font-size: var(--fs-base);
  text-align: left;
  cursor: pointer;
  transition: border-color var(--duration-fast) var(--ease-out),
              background var(--duration-fast) var(--ease-out);
}
.sv-option:hover { border-color: var(--line-strong); }
/* An option with subtext under the word: the mark sits with the top line */
.sv-option:has(.sv-option-subtext) { align-items: flex-start; }
.sv-option:has(.sv-option-subtext) .sv-mark { margin-top: 3px; }
.sv-option-copy { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; min-width: 0; flex: 1; }
.sv-option-label { line-height: 1.35; }
.sv-option-subtext { font-size: var(--fs-sm); line-height: 1.4; color: var(--text-3); }
.sv-option-subtext a { color: var(--cd-blue); }
/* A picture in wording — under an option, in a note, in a heading — is
   content, not decoration: it gets a footing and a ceiling */
img.sv-wording-img { max-width: 100%; max-height: 160px; border-radius: 8px; margin-top: 4px; display: block; background: var(--surface-2); }
.sv-ask img.sv-wording-img, .sv-note img.sv-wording-img { max-height: 120px; }


.sv-option.picked { border-color: var(--cd-blue); background: var(--cd-blue-dim); }
.sv-option:focus-visible { outline: 2px solid var(--cd-blue); outline-offset: 2px; }

.sv-mark {
  width: 18px; height: 18px;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: all var(--duration-fast) var(--ease-out);
}
.sv-mark.box { border-radius: var(--r-sm); }
.sv-option.picked .sv-mark { border: 5px solid var(--cd-blue); }
.sv-option.picked .sv-mark.box { border: 1px solid var(--cd-blue); background: var(--cd-blue); }
.sv-option.picked .sv-mark.box::after { content: '✓'; color: var(--on-accent); font-size: 11px; }

.sv-other { padding-right: var(--sp-3); }
.sv-other-input {
  flex: 1;
  background: transparent;
  border: none;
  color: var(--white);
  font-size: var(--fs-base);
  min-width: 0;
}
.sv-other-input::placeholder { color: var(--ash-dim); }
.sv-other-input:focus { outline: none; }

.sv-count { text-align: right; font-size: var(--fs-xs); color: var(--ash-dim); margin-top: var(--sp-2); }

/* Rating and NPS: the numbers are the control. NPS is eleven wide, so it
   wraps rather than shrinking below a thumb. */
.sv-rating { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.sv-rate {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
  background: transparent;
  cursor: pointer;
}
.sv-rate-mark {
  width: 52px; height: 52px;
  border: 1px solid var(--line);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-md);
  color: var(--ash);
  transition: all var(--duration-fast) var(--ease-out);
}
.sv-rate:hover .sv-rate-mark { border-color: var(--cd-blue-40); color: var(--white); }
.sv-rate.picked .sv-rate-mark,
.sv-rate.lit .sv-rate-mark { background: var(--cd-blue); border-color: var(--cd-blue); color: var(--on-accent); }
.sv-rate.star .sv-rate-mark { border: none; background: transparent; font-size: var(--fs-2xl); color: var(--line-strong); }
.sv-rate.star.lit .sv-rate-mark,
.sv-rate.star.picked .sv-rate-mark { background: transparent; color: var(--cd-gold); }
.sv-rate-label { font-size: 10px; color: var(--ash-dim); max-width: 64px; text-align: center; }

.sv-nps-row { display: flex; gap: var(--sp-1); flex-wrap: wrap; }
.sv-nps {
  flex: 1 1 52px;
  min-width: 44px;
  height: 48px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: transparent;
  color: var(--ash);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  cursor: pointer;
  transition: all var(--duration-fast) var(--ease-out);
}
.sv-nps:hover { border-color: var(--cd-blue-40); color: var(--white); }
.sv-nps.picked { background: var(--cd-blue); border-color: var(--cd-blue); color: var(--on-accent); }

.sv-ends {
  display: flex;
  justify-content: space-between;
  gap: var(--sp-4);
  font-size: var(--fs-xs);
  color: var(--ash-dim);
  margin-top: var(--sp-3);
}

/* A grid is the one control that cannot be made to fit a phone, so it scrolls
   sideways with the row labels holding their place. */
.sv-matrix-scroll { overflow-x: auto; margin: 0 calc(-1 * var(--sp-2)); padding: 0 var(--sp-2); }
.sv-matrix { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.sv-matrix th {
  font-weight: var(--fw-medium);
  color: var(--ash);
  padding: var(--sp-2) var(--sp-3);
  text-align: center;
  font-size: var(--fs-xs);
}
.sv-matrix th[scope="row"] {
  text-align: left;
  color: var(--white);
  font-size: var(--fs-sm);
  position: sticky;
  left: 0;
  background: var(--surface-0);
  min-width: 130px;
}
.sv-matrix td { text-align: center; padding: var(--sp-2); border-top: 1px solid var(--line-faint); }
.sv-matrix tbody tr:hover { background: var(--tint-1); }
.sv-matrix .sv-mark { cursor: pointer; margin: 0 auto; }
.sv-matrix .sv-mark.on { border: 5px solid var(--cd-blue); }
.sv-matrix .sv-mark.box.on { border: 1px solid var(--cd-blue); background: var(--cd-blue); }
.sv-matrix .sv-mark.box.on::after { content: '✓'; color: var(--on-accent); font-size: 11px; }

/* Ranking moves by button rather than by drag: a drag that has to work on a
   phone, with a keyboard and with a screen reader is three implementations,
   and this one is all three. */
.sv-rank { list-style: none; display: flex; flex-direction: column; gap: var(--sp-2); }
.sv-rank-item {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}
.sv-rank-n {
  width: 24px; height: 24px;
  border-radius: 50%;
  background: var(--cd-blue-dim);
  color: var(--blue-ink);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.sv-rank-text { flex: 1; min-width: 0; font-size: var(--fs-base); }
.sv-rank-moves { display: flex; gap: var(--sp-1); flex-shrink: 0; }
/* These are the only way to answer a ranking, so they are sized as a control
   rather than as an icon — a 28px target is a miss on a phone. */
.sv-rank-moves .icon-btn { width: 40px; height: 40px; }
@media (pointer: coarse) { .sv-rank-moves .icon-btn { width: 44px; height: 44px; } }

.sv-number { display: flex; align-items: center; gap: var(--sp-3); }
.sv-number .input { max-width: 200px; }
.sv-unit { color: var(--ash); font-size: var(--fs-sm); }

.sv-boolean { flex-direction: row; }
.sv-boolean .sv-option { flex: 1; justify-content: center; }

/* A section is a rest, not a question: it says where you are and how much is
   left, which is the only thing a long survey can offer in exchange. */
.sv-section-mark {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--cd-blue);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: var(--sp-3);
}

.sv-error {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  font-size: var(--fs-sm);
  color: var(--rose-ink);
  margin-top: var(--sp-4);
}
