/* =====================================================   Gantry — Explore styles
   Map hero + org list landing, org detail page, and the
   3D hierarchy tab.
   ============================================================ */

/* ------------------------------------------------------------
   Landing — map hero + sticky org list
   ------------------------------------------------------------ */

.cg-dash {
  position: relative;
}

/* The hero is sticky so it stays under the scrolling list */
.cg-map-hero {
  position: sticky;
  top: 57px;        /* below top nav */
  height: calc(100vh - 57px);
  min-height: 640px;
  z-index: 1;
  overflow: hidden;
  /* var(--bg) doubles as the flash-free backdrop during the theme swap —
     the CARTO basemaps were picked to match the app themes. */
  background: var(--bg); /* fallback where color-mix is unsupported */
  background:
    radial-gradient(60% 40% at 50% 0%, color-mix(in oklab, var(--brand) 8%, transparent), transparent 60%),
    var(--bg);
  border-bottom: 1px solid var(--line);
}
[data-sandbox="true"] .cg-map-hero { top: 96px; height: calc(100vh - 96px); }
[data-sandbox="true"] .cg-dash-list { min-height: calc(100vh - 96px); }

/* MapLibre container. Fades in over the var(--bg) backdrop once the style
   is live, so theme rebuilds crossfade instead of flashing white/black. */
.cg-map-hero-canvas {
  position: absolute;
  inset: 0;
  opacity: 0;
  /* .28s, not .5s: the globe cold-open only holds for ~300ms before the
     descent starts, and a half-second fade meant the globe was still
     translucent for most of the one beat it gets. Still long enough to keep
     the theme-swap rebuild from flashing. */
  transition: opacity .28s var(--ease);
}
.cg-map-hero-canvas.ready { opacity: 1; }
.cg-map-hero-canvas canvas { display: block; }
.cg-map-hero-canvas .maplibregl-canvas { outline: none; }

.cg-map-error {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--fg-3); font-family: var(--font-mono); font-size: 12px;
}

.cg-map-hero-loading {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none;
}

.cg-map-scrollhint {
  position: absolute;
  /* clear the org list's -32px slide-over lip so the hint stays visible */
  bottom: 46px;
  left: 50%;
  transform: translateX(-50%);
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 10.5px;
  color: var(--fg-4);
  letter-spacing: .1em;
  text-transform: uppercase;
  animation: cg-bob 2.4s var(--ease) infinite;
  pointer-events: none;
  z-index: 5;
}
@keyframes cg-bob { 0%,100% { transform: translateX(-50%) translateY(0); } 50% { transform: translateX(-50%) translateY(6px); } }

/* MapLibre's cooperative-gesture hint, restyled to the app tokens. TOUCH ONLY
   since 2026-09-10: a fine pointer now zooms the map on a plain wheel and the
   handler that shows this screen is off (map-hero.jsx, heroWheelZooms), so on
   a mouse or trackpad it never renders. It is still live on touch, where one
   finger scrolls the page and two drive the map. */
.cg-map-hero .maplibregl-cooperative-gesture-screen {
  background: color-mix(in oklab, var(--bg) 45%, transparent);
  color: var(--fg-2);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: .04em;
}

/* ------------------------------------------------------------
   Floating map filters bar (PROD-120 — filters-bar.jsx).
   Top-left over the map hero: a chip row (Filters toggle + one
   FilterChip per active kind + the org-context chip) above an
   animated expand/collapse panel of DS filter controls. The
   org-context HUD (.cg-map-hud, map.css) starts at top:64px to
   clear the collapsed row. Layers above the deck canvas + HUD
   (5/6) and the map popup (7), under modals (220); the export
   popover it opens is fixed at z 50.
   ------------------------------------------------------------ */

.cg-filtersbar {
  /* FIXED, and a sibling of the hero rather than a child of it — the hero is
     position: sticky, so anything inside it is trapped in that stacking
     context and the drawer (z-index 2) paints over it the moment it scrolls
     up. Out here z-index 8 beats the drawer, so the bar stays reachable at
     every drawer position, including fully expanded. Offset by the nav's
     height so it still sits in the map's top-left corner. */
  position: fixed;
  top: 69px;   /* 57px nav + 12px */
  left: 12px;
  z-index: 8;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  /* clear the MapLibre nav control pinned top-right */
  max-width: min(720px, calc(100% - 70px));
  /* the root box may span map area — only its children take pointer events,
     so map gestures keep working everywhere outside the actual controls */
  pointer-events: none;
}
/* EXPANDED, the bar is the foreground of the whole app (2026-09-16). At
   z-index 8 it tied with the section bar (chrome.css, also 8, fixed top-
   right) — the wider rail-and-pane panel reaches under it — and it sat below
   the top nav (50), the sandbox banner (40) and the account menu (60), so
   the topic-browser modal it mounts rendered beneath the nav. 70 clears all
   of them; the search overlay (80) still wins, and opening it collapses the
   panel anyway (click-outside). Collapsed it drops back to 8, so the chip row
   never covers a menu. */
.cg-filtersbar[data-expanded="true"] { z-index: 70; }

.cg-filtersbar-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  /* Clamp to the bar. Without it a chip's nowrap tokens set the row's
     min-content, the row overflows the bar's max-width, and on a phone a
     wide chip runs under the map's zoom buttons; with it the chip's
     max-width: 100% is real and its tokens ellipsize instead. */
  max-width: 100%;
  pointer-events: auto;
}
/* Frosted treatment over the busy basemap — same family as the HUD pills
   (.cg-map-hud .cg-pill, map.css). Scoped cosmetic override, not a DS edit. */
.cg-filtersbar .cg-filter-chip,
.cg-filtersbar .cg-filtersbar-toggle {
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  background: color-mix(in oklab, var(--bg-2) 82%, transparent);
}
/* Long value tokens (service-area labels, org names) truncate instead of
   pushing a chip past the viewport on narrow screens. */
.cg-filtersbar .cg-filter-chip { max-width: 100%; }
.cg-filtersbar .cg-filter-chip-value {
  max-width: min(240px, 56vw);
  overflow: hidden;
  text-overflow: ellipsis;
}
.cg-filtersbar .cg-filter-chip:hover:not([aria-disabled="true"]),
.cg-filtersbar .cg-filtersbar-toggle:hover {
  background: color-mix(in oklab, var(--bg-hover) 88%, transparent);
}
.cg-filtersbar-count {
  min-width: 18px;
  padding: 1px 6px;
  border-radius: var(--r-pill);
  background: var(--brand);
  color: var(--on-brand);
  font-size: 10.5px;
  line-height: 1.5;
  text-align: center;
}

/* Panel wrap — the "genie" toggle target. The panel stays at its NATURAL
   size at all times and only `transform` animates, scaled out of / back into
   the Filters button at the top-left (hence transform-origin). That is what
   replaced the old JS height animation: driving height meant measuring
   scrollHeight, animating px-by-px, then swapping to height:auto on
   transitionend purely to stop clipping the MultiSelect dropdowns. Scaling
   reflows nothing and clips nothing.
   `visibility` is delayed to the end of the close so the panel stays hit-
   testable until it has actually shrunk away. */
.cg-filtersbar-panel-wrap {
  transform: scale(0.04);
  transform-origin: top left;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  /* Explicit (viewport-based) width: the absolutely-positioned root
     shrink-wraps its content, so a %-width here would collapse to the
     chip row's width instead of a usable panel. Wide enough for the rail
     plus a two-column Market grid (2026-09-16). */
  width: min(940px, calc(100vw - 24px));
  transition:
    transform .26s var(--ease),
    opacity .16s var(--ease),
    visibility 0s linear .26s;
}
.cg-filtersbar-panel-wrap.open {
  transform: scale(1);
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  /* Slight overshoot on the way OUT only — it reads as popping out of the
     button. The close stays on the plain ease above; a bouncy close feels
     like a mistake rather than a dismissal. */
  transition:
    transform .28s cubic-bezier(.2, .9, .25, 1.06),
    opacity .16s var(--ease),
    visibility 0s;
}
/* First paint, hidden tab, reduced motion: no animation at all. */
.cg-filtersbar-panel-wrap.instant { transition: none; }

/* The panel is a RAIL-AND-PANE since 2026-09-16: the org row (in an org
   context), then the section rail beside the chosen section's pane, then the
   footer. Only the PANE scrolls — the rail and the footer (with its live
   "what this matches" line and Done) stay put however long a section is.
   The height is FIXED rather than content-sized so switching sections never
   makes the panel jump. Opaque, not frosted: a busy basemap behind nine
   histograms made the bars unreadable. */
.cg-filtersbar-panel {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: min(80vh, 720px);
  overflow: hidden;
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-lg);
}

.cg-filtersbar-orgrow {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--line);
  flex: 0 0 auto;
}

.cg-fpanel-body {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: 168px minmax(0, 1fr);
}
.cg-fpanel-rail {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 12px 8px;
  border-right: 1px solid var(--line);
  background: var(--bg);
  overflow-y: auto;
}
.cg-fpanel-tab {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  padding: 9px 10px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--fg-3);
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  transition: background .15s var(--ease), color .15s var(--ease);
}
.cg-fpanel-tab:hover { background: var(--bg-hover); color: var(--fg); }
.cg-fpanel-tab:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
/* The chosen section carries a hairline ink bar on its leading edge — the
   structure-by-hairline voice, not a filled pill. */
.cg-fpanel-tab[aria-selected="true"] {
  background: var(--bg-2);
  color: var(--fg);
  box-shadow: inset 2px 0 0 var(--fg);
}
.cg-fpanel-tab-count {
  min-width: 18px;
  padding: 1px 6px;
  border-radius: var(--r-pill);
  background: var(--brand);
  color: var(--on-brand);
  font-size: 10.5px;
  line-height: 1.5;
  text-align: center;
}
.cg-fpanel-pane {
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 16px 18px 20px;
}
.cg-fpanel-sechead {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin-bottom: 4px;
}
.cg-fpanel-sechint {
  font-size: 12px;
  color: var(--fg-3);
}
/* "Your lists" — one picker per KIND, side by side, because which
   kind a list is about decides which tab it narrows. Two columns keeps that
   split visible; stacking them would read as one long list of lists. */
.cg-fpanel-rlists {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 18px;
  align-items: start;
  margin-top: 10px;
}
.cg-fpanel-rlgroup {
  display: flex;
  flex-direction: column;
  gap: 7px;
  min-width: 0;
}
.cg-fpanel-rlgroup .cg-mselect,
.cg-fpanel-rlgroup .cg-mselect-trigger { width: 100%; }
.cg-fpanel-rlgroup .cg-mselect-trigger { justify-content: space-between; }
.cg-fpanel-rlnote {
  margin: 12px 0 0;
  max-width: 62ch;
  font-size: 12px;
  line-height: 1.5;
  color: var(--fg-3);
}
.cg-fpanel-rlnote.mono { margin-top: 6px; font-size: 11px; color: var(--fg-4); }

@media (max-width: 720px) {
  .cg-fpanel-rlists { grid-template-columns: 1fr; }
}

.cg-fpanel-geo {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
  gap: 18px;
  align-items: start;
}
.cg-fpanel-geo-side {
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.cg-fpanel-match {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 11.5px;
  color: var(--fg-2);
}
.cg-fpanel-foot-actions {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  flex: 0 0 auto;
}
.cg-fpanel-done { padding-top: 6px; padding-bottom: 6px; }

/* ---- Market section (filters-bar.jsx MarketFiltersSection) ---- */
.cg-mkt { display: flex; flex-direction: column; gap: 10px; }
.cg-mkt-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 16px;
}
.cg-mkt-summary {
  flex: 1 1 260px;
  display: inline-flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0 4px;
  font-size: 13px;
  color: var(--fg-2);
}
.cg-mkt-summary-num {
  font-family: var(--font-serif);
  font-size: 20px;
  line-height: 1.1;
  color: var(--fg);
}
/* A quiet pulse while fresher counts load behind the ones on screen. */
.cg-mkt-busy {
  display: inline-block;
  vertical-align: middle;
  width: 6px;
  height: 6px;
  margin-left: 6px;
  border-radius: 50%;
  background: var(--brand);
  align-self: center;
  animation: cg-mkt-pulse 1s var(--ease) infinite alternate;
}
@keyframes cg-mkt-pulse { from { opacity: .25; } to { opacity: 1; } }
.cg-mkt-unit {
  display: inline-flex;
  padding: 2px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
}
.cg-mkt-unit-btn {
  padding: 3px 10px;
  border: 0;
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--fg-3);
  font-family: var(--font-sans);
  font-size: 11.5px;
  cursor: pointer;
}
.cg-mkt-unit-btn[aria-pressed="true"] { background: var(--fg); color: var(--bg); }
.cg-mkt-note {
  margin: 0;
  font-size: 12px;
  line-height: 1.45;
  color: var(--fg-3);
}
.cg-mkt-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}
.cg-mkt-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
  padding: 11px 13px 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--bg-2);
  transition: border-color .15s var(--ease);
}
.cg-mkt-card[data-wide="true"] { grid-column: 1 / -1; }
.cg-mkt-card[data-active="true"] {
  border-color: color-mix(in oklab, var(--brand) 55%, var(--line));
}
.cg-mkt-card-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
}
.cg-mkt-card-title {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--fg);
  white-space: nowrap;
  cursor: help;
}
.cg-mkt-card-value {
  margin-left: auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 11px;
  color: var(--fg-3);
}
.cg-mkt-card[data-active="true"] .cg-mkt-card-value { color: var(--brand-text); }
.cg-mkt-reset {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--fg-3);
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
}
.cg-mkt-reset:hover {
  background: color-mix(in oklab, var(--bad) 12%, var(--bg-2));
  color: var(--bad);
}
.cg-mkt-card .cg-hrange { padding-top: 20px; }
.cg-mkt-card .cg-hrange-track { height: 40px; }
.cg-mkt-card-foot { display: flex; align-items: center; min-height: 16px; }
.cg-mkt-count { font-size: 11px; color: var(--fg-2); }
.cg-mkt-count[data-loading="true"] { color: var(--fg-4); }
.cg-mkt-hint { font-size: 11.5px; color: var(--fg-3); }
/* A card's one-line subtitle under its title (Health concerns: what each
   score means). Sits tight to the title rather than a full card-gap below. */
.cg-mkt-card-sub { display: block; margin-top: -4px; line-height: 1.35; }
.cg-mkt-skeleton {
  height: 62px;
  border-radius: var(--r-sm);
  background: linear-gradient(90deg, var(--bg-3), var(--bg-hover), var(--bg-3));
  background-size: 200% 100%;
  animation: cg-mkt-shimmer 1.2s linear infinite;
}
@keyframes cg-mkt-shimmer { from { background-position: 200% 0; } to { background-position: 0 0; } }
.cg-filtersbar-orgname {
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cg-filtersbar-orgrow .cg-filtersbar-clear { margin-left: auto; }

.cg-filtersbar-field {
  display: flex;
  flex-direction: column;
  gap: 7px;
}
/* Stretch the DS dropdown triggers to the panel column (contextual layout,
   same pattern as .cg-map-hud .cg-pill / .cg-dash-list .cg-table). */
.cg-filtersbar-field .cg-mselect { display: block; }
.cg-filtersbar-field .cg-mselect-trigger {
  width: 100%;
  justify-content: space-between;
}
/* An open dropdown fills the room it is given. The DS caps the list at a flat
   260px; here the dropdown as a whole caps against the VIEWPORT and the list
   flexes into whatever is left under the search box, so a long vocabulary
   (the service areas) shows as many rows as the screen can hold instead of a
   fixed handful. `min-height: 0` is what lets the list shrink inside the flex
   column — without it the list keeps its content height and the cap does
   nothing. Scoped cosmetic override, not a DS edit — same family as the
   frosted chip treatment above. */
.cg-filtersbar-panel .cg-mselect-panel {
  display: flex;
  flex-direction: column;
  max-height: min(52vh, 460px);
}
.cg-filtersbar-panel .cg-mselect-list {
  flex: 1 1 auto;
  min-height: 0;
  max-height: none;
}

/* Where the dropdown is allowed to hang. The panel is sized by its CONTENT
   (~355px), not by its max-height, and a dropdown is absolutely positioned —
   so it adds no content height, hangs past the panel's natural bottom, and
   `overflow-y: auto` clips it into a second scroll region (the double-scroll
   John reported). The fix used to be growing the panel by roughly a
   dropdown's height while one was open. That worked for the LAST field but
   left a slab of unreachable dead panel under a dropdown opened from the
   FIRST — the padding lands below all the content, while a top field's
   dropdown ends near the top. So: let the dropdown hang OUT of the panel
   instead, which is what an overlay should do anyway. It paints over the map
   (.cg-filtersbar is z-index 8, above the drawer) and the panel never needs
   its own scrollbar.
   Below ~640px of viewport the panel genuinely can need to scroll, and
   `overflow: visible` would spill its content instead — so short viewports
   keep the old make-room behaviour. Browsers without :has() do too. */
@supports selector(:has(*)) {
  /* The PANE is the scroller since the rail-and-pane layout, so it is the
     one that makes room / lets the dropdown hang — and the panel has to
     stop clipping too, or the hanging dropdown is cut at its edge. */
  .cg-fpanel-pane:has(.cg-mselect-panel) { padding-bottom: 272px; }
  @media (min-height: 640px) {
    .cg-filtersbar-panel:has(.cg-mselect-panel),
    .cg-filtersbar-panel:has(.cg-mselect-panel) .cg-fpanel-pane {
      overflow: visible;
    }
    .cg-fpanel-pane:has(.cg-mselect-panel) { padding-bottom: 20px; }
  }
}

.cg-filtersbar-geo {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

/* ZIP token entry */
.cg-filtersbar-zips {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
}
.cg-filtersbar-zip {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 3px 4px 3px 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--bg-3);
  color: var(--fg);
  font-size: 11.5px;
}
.cg-filtersbar-zip-x {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--fg-3);
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
  transition: background .15s var(--ease), color .15s var(--ease);
}
.cg-filtersbar-zip-x:hover {
  background: color-mix(in oklab, var(--bad) 12%, var(--bg-3));
  color: var(--bad);
}
.cg-filtersbar-zip-input {
  width: 118px;
  padding: 8px 10px;
  font-size: 12.5px;
}
.cg-filtersbar-zip-input[aria-invalid="true"] {
  border-color: color-mix(in oklab, var(--bad) 55%, var(--line));
  background: color-mix(in oklab, var(--bad) 8%, var(--bg-1));
}
.cg-filtersbar-zip-input[data-shake="true"] {
  animation: cg-fb-shake .28s var(--ease);
}
@keyframes cg-fb-shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-4px); }
  60% { transform: translateX(4px); }
  85% { transform: translateX(-2px); }
}

.cg-filtersbar-hint {
  font-size: 10.5px;
  color: var(--bad);
  letter-spacing: .03em;
}

.cg-filtersbar-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex: 0 0 auto;
  padding: 10px 16px;
  border-top: 1px solid var(--line);
  background: var(--bg-1);
}
.cg-filtersbar-clear {
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  font-size: 11px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--fg-3);
}
.cg-filtersbar-clear:hover { color: var(--fg); text-decoration: underline; }

[data-sandbox="true"] .cg-filtersbar { top: 108px; } /* 96px banner+nav + 12px */

/* The map's zoom/compass control shares the hero's top-right corner with the
   floating section bar (chrome.css .cg-sectionbar, 12px in from the top) —
   drop it under the bar so the two never overlap. */
.cg-map-hero .maplibregl-ctrl-top-right { top: 52px; }

/* Narrow viewports: the bar spans the hero (minus the nav control) and the
   panel goes near-full-width with stacked geography controls. */
/* Below ~760px the rail turns into a scrolling row of tabs above the pane,
   and the Market grid and the geography split go to one column. */
@media (max-width: 760px) {
  .cg-fpanel-body {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr);
  }
  .cg-fpanel-rail {
    flex-direction: row;
    overflow-x: auto;
    overflow-y: hidden;
    padding: 6px 8px;
    border-right: 0;
    border-bottom: 1px solid var(--line);
  }
  .cg-fpanel-tab { width: auto; flex: 0 0 auto; white-space: nowrap; }
  .cg-fpanel-tab[aria-selected="true"] { box-shadow: inset 0 -2px 0 var(--fg); }
  .cg-mkt-grid { grid-template-columns: minmax(0, 1fr); }
  .cg-fpanel-geo { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 640px) {
  .cg-filtersbar { max-width: calc(100vw - 62px); }
  .cg-filtersbar-panel-wrap { width: calc(100vw - 24px); }
  .cg-filtersbar-panel { height: 72vh; }
  .cg-filtersbar-geo { grid-template-columns: 1fr; }
  /* A multi-value chip must fit the phone viewport: tokens truncate hard
     (two ~26vw tokens + label + × ≈ the bar's max-width). */
  .cg-filtersbar .cg-filter-chip-value { max-width: 26vw; }
}

@media (prefers-reduced-motion: reduce) {
  .cg-filtersbar-panel-wrap,
  .cg-filtersbar-panel-wrap.open { transition: none; }
  .cg-filtersbar-zip-input[data-shake="true"] { animation: none; }
  .cg-mkt-busy, .cg-mkt-skeleton { animation: none; }
  /* The scroll hint holds still (its continuous bob is pure motion). */
  .cg-map-scrollhint { animation: none; }
}

/* ============================================================
   The drawer — rests over the map, scrolls up in front of it
   ------------------------------------------------------------
   Geometry (Flighty's airports view is the reference):

   - It RESTS with its top edge at --drawer-rest-vh of the
     viewport, so the map keeps the strip above it and the
     country frames into the top quarter. The hero's camera
     reads this exact custom property (map-hero.jsx,
     heroDrawerRestFrac) to compute its padding — change the
     number here and the camera follows. Do NOT hard-code the
     fraction anywhere else.
   - It can never sit LOWER than that. The rest position is
     scroll offset 0, and scrolling only ever moves it up, so
     the clamp is structural rather than a scroll handler
     fighting the user.
   - Scrolling up, the panel's CHROME (side gutters + top
     radius) melts away into a full-bleed background while the
     CONTENT column keeps its width — .cg-dash-inner owns the
     content measure, .cg-dash-list owns the chrome, which is
     what lets the two move independently. --drawer-expand is
     the 0→1 progress driving it (set by explore.jsx).
   ============================================================ */
:root {
  /* Read by map-hero.jsx — see above. */
  --drawer-rest-vh: 52;
  /* Horizontal breathing room at rest; collapses to 0 when expanded. */
  --drawer-gutter: 24px;
  --drawer-radius: 20px;
  /* 0 = resting (gutters, rounded, map visible around it)
     1 = expanded (full-bleed solid background over the map) */
  --drawer-expand: 0;
}

.cg-dash-list {
  position: relative;
  z-index: 2;
  background: var(--bg);
  padding: 28px 22px 80px;
  /* Rest with the top edge at --drawer-rest-vh. The hero occupies
     100vh - navH of flow and starts navH down, so its bottom edge sits at
     exactly 100vh — pulling up by (100vh - rest) lands the top on the mark,
     with no dependence on the nav height. */
  margin-top: calc((var(--drawer-rest-vh) * 1vh) - 100vh);
  /* The drawer must ALWAYS be tall enough to scroll its own top up to the
     nav — otherwise a short result set (one org, an empty filter) leaves the
     page unscrollable and the panel can never expand. One viewport of body
     is exactly the amount of travel that guarantees it. */
  min-height: calc(100vh - 57px);
  /* Chrome that animates away as the drawer takes the screen. */
  margin-left: calc(var(--drawer-gutter) * (1 - var(--drawer-expand)));
  margin-right: calc(var(--drawer-gutter) * (1 - var(--drawer-expand)));
  border-radius: calc(var(--drawer-radius) * (1 - var(--drawer-expand)))
                 calc(var(--drawer-radius) * (1 - var(--drawer-expand))) 0 0;
  border-top: 1px solid
    color-mix(in oklab, var(--line) calc((1 - var(--drawer-expand)) * 100%), transparent);
  box-shadow: 0 -16px 40px -12px rgba(0, 0, 0, calc(0.34 * (1 - var(--drawer-expand))));
  /* Nothing here transitions: the gutter/radius/shadow are driven straight
     off scroll position, so a CSS transition would lag the finger. The one
     animated move is the entrance below. */
}

/* The content measure, held CONSTANT while the chrome expands around it —
   the text must not reflow just because the panel reached the top of the
   screen (the giveaway detail in Flighty's version). Compensates its own
   padding so the column lands in the same place at both extremes. */
.cg-dash-inner {
  box-sizing: border-box;
  width: 100%;
  margin: 0 auto;
  /* Hold the content column PERFECTLY still while the chrome expands around
     it — the giveaway detail in Flighty's version is that the headline never
     moves, only the panel behind it grows. The panel gains 2×gutter of width
     on the way to full-bleed, so give exactly that back:
       - as padding, for viewports narrower than the measure (the column is
         tracking the panel's width, so it would otherwise widen);
       - added to max-width, for viewports wider than it (the column is
         capped and centred, so the padding alone would wrongly SHRINK it).
     Both terms scale with --drawer-expand, so they are zero at rest. */
  padding-left: calc(var(--drawer-gutter) * var(--drawer-expand));
  padding-right: calc(var(--drawer-gutter) * var(--drawer-expand));
  max-width: calc(1640px + var(--drawer-gutter) * 2 * var(--drawer-expand));
}

/* ---- Entrance: up from offscreen with an elastic landing ----
   Runs once, cued by the hero's camera flight landing (the
   cg-hero-intro-done handshake). Starts fully below the fold and
   overshoots slightly so it snaps into place. The transform is REMOVED on
   completion (the .cg-dash-list-in class is dropped) because a lingering
   transform makes this element a containing block, which would break the
   position: sticky section headers nested inside it. */
.cg-dash-list-pre { transform: translateY(calc(100vh - (var(--drawer-rest-vh) * 1vh))); }
.cg-dash-list-in {
  animation: cg-drawer-rise 620ms cubic-bezier(0.18, 0.89, 0.32, 1.22) both;
  will-change: transform;
}
@keyframes cg-drawer-rise {
  from { transform: translateY(calc(100vh - (var(--drawer-rest-vh) * 1vh))); }
  to   { transform: translateY(0); }
}

/* Reduced motion: no rise, no overshoot — it is simply there. */
@media (prefers-reduced-motion: reduce) {
  .cg-dash-list-pre { transform: none; }
  .cg-dash-list-in { animation: none; }
}

/* Narrow viewports: the gutter is a luxury, and the drawer needs to rest a
   little lower so the map still reads on a short screen. */
@media (max-width: 640px) {
  :root { --drawer-gutter: 10px; --drawer-radius: 16px; --drawer-rest-vh: 58; }
  .cg-dash-list { padding: 22px 14px 80px; }
}

/* ------------------------------------------------------------
   Drawer stats line — the same five numbers (four filter-reactive
   counts plus the graph-wide 24h activity count), collapsed on
   2026-07-29 from a row of stacked DS Cards into ONE line of small
   muted text. The cards were the reason the drawer's results list
   started below the fold on a phone; nothing about the numbers
   changed, only the amount of drawer they cost. Every value a token.
   ------------------------------------------------------------ */
.cg-drawer-stats {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: 9px;
  row-gap: 2px;
  font-size: 12px;
  line-height: 1.55;
  color: var(--fg-3);
  margin-bottom: 14px;
}
/* The four counts re-fetch with the filters; dim rather than blank them so
   the line doesn't jump while a filtered universe is in flight. */
.cg-drawer-stats.is-busy .cg-dstat:not(.cg-dstat-accent) {
  opacity: 0.55;
  transition: opacity 0.2s var(--ease);
}
/* A number + its label are one unit — they wrap together or not at all. */
.cg-dstat { white-space: nowrap; }
/* Middot between items, carried by the item BEFORE it: the line wraps on a
   phone, and a leading separator dangling at the start of a row reads as a
   list bullet. Trailing it keeps every row starting on a number. */
.cg-dstat:not(:last-child)::after {
  content: "·";
  margin-left: 9px;
  color: var(--fg-4);
}
.cg-dstat-num {
  font-size: 12.5px;
  color: var(--fg);
  letter-spacing: -0.01em;
}
/* The 24h count is deliberately NOT one of the reactive four — it stays
   graph-wide while they narrow, so it keeps the brand tint that marked out
   its box, rather than reading as a count that forgot to update. */
.cg-dstat-accent .cg-dstat-num { color: var(--brand); }

/* (.cg-dash-list-head — the drawer's heading + count row — retired
   2026-08-07 with the tab bar below, which is the drawer's list header now.) */
.cg-dash-controls { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.cg-dash-search {
  position: relative;
  display: flex; align-items: center; gap: 8px;
  padding: 0 12px;
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  height: 38px;
  width: 280px;
  color: var(--fg-3);
}

.cg-load-more, .cg-load-done {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 20px;
  border-top: 1px solid var(--line);
}

/* Scoped to the dash list table — denser look + numbers right-aligned */
.cg-dash-list .cg-table tbody td:first-child { padding-left: 18px; }
.cg-dash-list .cg-table thead th:first-child { padding-left: 18px; }


/* ------------------------------------------------------------
   Top-level drawer tab bar (2026-08-07). The drawer's list is
   one tabbed surface over Organizations / Facilities / People,
   in both the unfiltered and the filtered state — replacing the
   old "Organizations" heading and, under a filter, the "Results"
   heading over three stacked sections (PROD-123). The tab rail
   is the DS .cg-tabs; this adds the right-hand end of the row,
   which carries the "showing X of Y" line for the active tab
   and the export button.

   The row PINS below the top nav so the tabs and the count stay
   reachable while a 200-row list scrolls (96px clears the
   sandbox banner variant — same offset family as .cg-map-hero).
   ------------------------------------------------------------ */

.cg-dash-tabbar {
  position: sticky;
  top: 57px;
  z-index: 3;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 18px;
  padding-top: 8px;
  background: var(--bg);
  /* The rail belongs to the ROW, not to the tab strip: the flex gap between
     the strip and the right-hand end would otherwise punch a 16px hole in the
     hairline (and a second stray one when the row wraps on a phone). The DS
     strip's own border is dropped here for the same reason — a contextual
     layout override, not a design-system edit. The active tab's -1px bottom
     margin still lands its underline exactly on this border. */
  border-bottom: 1px solid var(--line);
}
[data-sandbox="true"] .cg-dash-tabbar { top: 96px; }
.cg-dash-tabbar .cg-tabs { flex: 1 1 auto; border-bottom: 0; }
.cg-dash-tabbar-end {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding-bottom: 6px;
  flex: 0 0 auto;
}
.cg-dash-showing {
  font-size: 11px;
  color: var(--fg-3);
  white-space: nowrap;
}

/* ------------------------------------------------------------
   Org-context drawer (PROD-118 — drawer ↔ map tandem).
   Replaces the top-level org table while the map holds an org.
   ------------------------------------------------------------ */

.cg-orgctx-back { font-size: 11px; }
.cg-orgctx-back .cg-crumb-link { font-size: 11.5px; letter-spacing: .02em; }

.cg-orgctx-head {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin-top: 14px;
}
.cg-orgctx-title-wrap { min-width: 0; }
/* Entity display name — editorial serif (skin only; size/position untouched). */
.cg-orgctx-title {
  font-family: var(--font-serif);
  font-size: 22px;
  font-weight: 500;
  letter-spacing: -0.005em;
  line-height: 1.15;
}
.cg-orgctx-meta {
  display: inline-flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 4px;
  font-size: 11.5px; color: var(--fg-3);
}
.cg-orgctx-actions {
  margin-left: auto;
  display: inline-flex; gap: 8px; flex-wrap: wrap;
}
.cg-orgctx-loading {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 10px 0;
}

/* Keyboard-activatable list rows (drawer sections + profile tabs share the
   extracted row components, so both surfaces pick up the focus ring). */
.cg-table tr[role="link"]:focus-visible,
.cg-people-card:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: -2px;
}


/* ------------------------------------------------------------
   Org detail page
   ------------------------------------------------------------ */

.cg-crumbs {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 11px; color: var(--fg-3);
  margin-top: 22px;
}
.cg-crumb-link {
  background: none; border: 0; cursor: pointer;
  color: var(--fg-3); font-family: var(--font-mono);
  font-size: 11px; padding: 0;
}
.cg-crumb-link:hover { color: var(--fg); }

.cg-org-head {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: 16px; flex-wrap: wrap;
  margin: 14px 0 24px;
}
.cg-org-head-left { display: flex; align-items: flex-start; gap: 18px; min-width: 0; }

/* The ORGANIZATION profile's identity block is a GRID instead (2026-08-07) —
   a modifier, because the facility and person headers keep the plain flex
   shape (badge + one wrapper) and auto-placing them into these tracks would
   scatter their lines. The grid exists for exactly one reason: the monogram
   tile can then SPAN kicker → name → meta and stretch to their combined
   height, so its bottom edge lines up with the bottom of the URL /
   anchor-cities line instead of floating above it. Height comes from the row
   span (the JSX passes `height: auto` over the component's square default);
   the width stays fixed, so the tile reads as a spine beside the block.
   Ratings/socials land in row 4 of column 2 — deliberately BELOW the tile. */
.cg-org-head-grid {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: 18px;
  /* .cg-org-head-left's flex `gap: 18px` also sets row-gap, which would push
     the three identity lines apart. The column gap is the only one wanted. */
  row-gap: 0;
  align-items: start;
}
.cg-org-head-grid > .cg-org-head-logo {
  grid-column: 1;
  grid-row: 1 / 4;
  align-self: stretch;
}
.cg-org-head-grid > :not(.cg-org-head-logo) { grid-column: 2; }
/* Profile display name — editorial serif. Margins are symmetric so the name
   sits centred between the kicker above it and the meta line below. */
.cg-org-h1 {
  font-family: var(--font-serif);
  font-size: 32px;
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.1;
  margin: 6px 0;
}
.cg-org-meta {
  display: inline-flex; align-items: center; gap: 10px;
  color: var(--fg-3); font-size: 12px;
}
.cg-org-head-actions { display: inline-flex; gap: 8px; flex-wrap: wrap; }

.cg-org-statgrid {
  display: grid; grid-template-columns: repeat(6, 1fr); gap: 12px;
  margin-bottom: 22px;
}
@media (max-width: 1100px) {
  .cg-org-statgrid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 900px) {
  .cg-org-statgrid { grid-template-columns: repeat(2, 1fr); }
  /* The lead stat takes the first row whole rather than orphaning one. */
  .cg-org-statgrid > .cg-bigstat-lead { grid-column: span 2; }
}
.cg-bigstat { padding: 16px 18px; }
/* The lead stat: a brand hairline on the leading edge — structure, not a
   fill; buttons stay ink. */
.cg-bigstat-lead { border-left: 3px solid var(--brand); }

/* Signal tiles (2026-09-08). Each tile IS the way into its section, so it
   reads and behaves as a control: hairline moves on hover, focus ring from
   the token, and the whole tile is one tab stop. */
.cg-signal-tile { cursor: pointer; transition: border-color .18s var(--ease); }
.cg-signal-tile:hover { border-color: var(--fg-4); }
.cg-signal-tile:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
/* A signal we hold nothing for says so in words, quietly — never as a zero,
   which would read as a measured absence of activity. */
.cg-signal-tile-empty { color: var(--fg-4); font-family: var(--font-serif); }
.cg-signal-tile-sub {
  font-size: 11px; color: var(--fg-3); margin-top: 4px;
  display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap;
}
.cg-signal-delta.is-up { color: var(--good); }
.cg-signal-delta.is-down { color: var(--bad); }
.cg-signal-delta.is-flat { color: var(--fg-4); }
/* The scroll target a tile lands on. Zero-height, so it takes no grid row of
   its own visually; the offset keeps the card's own head clear of the
   sticky chrome above it. */
.cg-sec-anchor { grid-column: 1 / -1; height: 0; scroll-margin-top: 90px; }
@media (prefers-reduced-motion: reduce) {
  .cg-signal-tile { transition: none; }
}

/* Business health (2026-09-09): the three composite readings, above the
   measures they were folded from. Three columns because there are exactly
   three readings; they collapse to one on a narrow viewport rather than
   leaving an orphan. Order is the SERVER'S — the entity's own discipline
   decides which reading leads — so nothing here re-orders them. */
.cg-health-strip {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px;
  margin-bottom: 14px;
}
@media (max-width: 900px) {
  .cg-health-strip { grid-template-columns: 1fr; }
}
.cg-health-card { padding: 16px 18px; }
/* The verdict is the reading. Serif, because it is a sentence's subject and
   not a measurement — the numbers on this page are mono. */
.cg-health-verdict {
  font-family: var(--font-serif); font-size: 26px; line-height: 1.15;
  letter-spacing: -0.01em; margin: 8px 0 0; color: var(--fg-1);
}
.cg-health-verdict.is-up { color: var(--good); }
.cg-health-verdict.is-down { color: var(--bad); }
.cg-health-because {
  font-size: 12.5px; line-height: 1.5; color: var(--fg-2); margin: 8px 0 0;
}
.cg-health-basis { font-size: 10.5px; color: var(--fg-4); margin-top: 8px; }
/* A reading we cannot make says so, in the same quiet serif a not-held
   signal tile uses — never a zero, which would read as "flat". */
.cg-health-unread {
  font-family: var(--font-serif); font-size: 14px; line-height: 1.5;
  color: var(--fg-4); margin: 10px 0 0;
}

.cg-org-tabs { margin: 6px 0 22px; }

.cg-pad { padding: 18px 18px 20px; }
.cg-card-head {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 6px;
}

.cg-overview-grid {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 14px;
}
@media (max-width: 1000px) {
  .cg-overview-grid { grid-template-columns: 1fr; }
  .cg-overview-grid > .cg-card[style*="span 2"] { grid-column: auto !important; }
}

/* Organization settings — the discipline checkbox grid. Layout only; every
   color, radius and font comes from a token (see CLAUDE.md § Design system).
   Three columns at desktop so the fourteen disciplines read as one block
   rather than a long scroll. */
.cg-disc-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px 14px;
  margin-top: 10px;
}
@media (max-width: 900px) { .cg-disc-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .cg-disc-grid { grid-template-columns: 1fr; } }

.cg-disc-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  font-size: 13px;
  color: var(--fg-2);
  cursor: pointer;
  background: transparent;
}
.cg-disc-row:hover { border-color: var(--line-2); }
.cg-disc-row.on { color: var(--fg); border-color: var(--fg-4); }
/* A member (not an owner) reads the same rows; they just cannot move them. */
.cg-disc-row.ro { cursor: default; opacity: 0.72; }
.cg-disc-row.ro:hover { border-color: var(--line); }
.cg-disc-row input { accent-color: var(--brand); cursor: inherit; }

/* Industry payments — the year bars, the two mixes, and who moved.
   Layout only; every colour, radius, font and easing is a token. */
.cg-pay-note { font-size: 10.5px; color: var(--fg-4); }
.cg-pay-years { margin-top: 4px; }
.cg-pay-axis {
  display: flex; justify-content: space-between;
  font-size: 10px; color: var(--fg-4); padding: 0 4px;
}
.cg-pay-split {
  display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin-top: 16px;
}
@media (max-width: 800px) { .cg-pay-split { grid-template-columns: 1fr; } }
/* Both mixes align on one label column, so the two halves read as a pair. */
.cg-pay-meters { --meter-label-w: 44%; margin-top: 8px; }
.cg-pay-shift { margin-top: 18px; border-top: 1px solid var(--line); padding-top: 14px; }
.cg-pay-shift-rows { list-style: none; padding: 0; margin: 8px 0 0; }
.cg-pay-shift-rows li {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: baseline;
  gap: 12px;
  padding: 6px 0;
  border-bottom: 1px dashed var(--line);
}
.cg-pay-shift-rows li:last-child { border-bottom: 0; }
.cg-pay-shift-name { font-size: 13px; }
.cg-pay-shift-note { font-size: 10.5px; color: var(--fg-4); }

/* Compliance — one row per exact-key event, or the clean state. There is no
   composite score here on purpose (see the card's own note). */
.cg-comp-clean {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 10px; font-size: 13px; color: var(--fg-2);
}
.cg-comp-rows { list-style: none; padding: 0; margin: 12px 0 0; }
.cg-comp-row {
  display: grid;
  grid-template-columns: minmax(0, auto) 1fr;
  gap: 12px;
  align-items: start;
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
  animation: cg-comp-in .36s var(--ease) both;
  animation-delay: calc(var(--i, 0) * 24ms);
}
.cg-comp-row:last-child { border-bottom: 0; }
@media (max-width: 700px) { .cg-comp-row { grid-template-columns: 1fr; } }
@keyframes cg-comp-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) { .cg-comp-row { animation: none; } }
.cg-comp-body { min-width: 0; }
.cg-comp-title { font-size: 13.5px; }
.cg-comp-summary { font-size: 12.5px; color: var(--fg-2); margin-top: 2px; }
/* Which location a record is against. Sits directly under the headline
   because an adverse record read without its subject is a different and
   much more serious claim than the one on the public record. */
.cg-comp-about { font-size: 12.5px; color: var(--fg-1); margin-top: 2px; }
.cg-comp-meta { font-size: 10.5px; color: var(--fg-4); margin-top: 4px; }

.cg-feed { list-style: none; padding: 0; margin: 14px 0 0; display: flex; flex-direction: column; gap: 4px; }
.cg-feed li {
  display: grid;
  grid-template-columns: 14px 1fr;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 4px;
  border-bottom: 1px dashed var(--line);
}
.cg-feed li:last-child { border-bottom: 0; }
.cg-feed li .cg-dot { margin-top: 6px; }

/* Building-activity feed (PROD-199): permit description snippet, clamped so
   long municipal text can't swallow the card. */
.cg-sig-desc {
  margin-top: 2px;
  font-size: 12px;
  color: var(--fg-3);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
}

/* People grid */
.cg-people-grid {
  margin-top: 14px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 12px;
}
.cg-people-card {
  display: flex; gap: 12px;
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 14px;
  cursor: pointer;
  transition: background .12s var(--ease), border-color .12s var(--ease);
}
.cg-people-card:hover { background: var(--bg-2); border-color: var(--line-2); }

/* Key people — the lead block of the org Overview (2026-09-08): who runs the
   organization, as it states itself. A compact rail of rows; a row that has a
   person page behind it reads and behaves as a link. Tokens only. */
.cg-key-people-count {
  font-size: 12px;
  color: var(--fg-2);
}
.cg-key-people-list {
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 8px 16px;
}
.cg-key-people-row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--bg-1);
  transition: background .12s var(--ease), border-color .12s var(--ease);
}
.cg-key-people-row.is-linked { cursor: pointer; }
.cg-key-people-row.is-linked:hover { background: var(--bg-2); border-color: var(--line-2); }
.cg-key-people-row.is-linked:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: -2px;
}
.cg-key-people-body { flex: 1; min-width: 0; }
.cg-key-people-name {
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cg-key-people-title {
  font-size: 12px;
  color: var(--fg-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Compact "DVM" chip on a person card + credential suffix on the detail h1 */
.cg-vet-chip {
  font-size: 9px;
  letter-spacing: .08em;
  padding: 1px 6px;
  color: var(--brand-text, var(--brand));
  border-color: color-mix(in oklab, var(--brand) 40%, var(--line));
  background: color-mix(in oklab, var(--brand) 10%, transparent);
}
.cg-credential {
  font-weight: 500;
  color: var(--fg-3);
  letter-spacing: -0.01em;
}

/* ------------------------------------------------------------
   Entity-detail blocks (contact / socials / ratings / reviews /
   hours / license) — shared by the Person, Facility and Org
   detail views. Each card self-hides when its data is absent.
   ------------------------------------------------------------ */

/* Two-up grid for pairing e.g. License + Contact, or Contact + Hours.
   Collapses to a single column on narrow viewports. */
.cg-detail-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 14px;
  margin-top: 14px;
  align-items: start;
}
@media (max-width: 900px) {
  .cg-detail-grid { grid-template-columns: 1fr; }
}
/* A lone card inside the grid (its sibling self-hid) shouldn't stretch
   to half-width awkwardly — let it fill the row. */
.cg-detail-grid > .cg-detail-card:only-child { grid-column: 1 / -1; }
/* Same idea for an odd third (or fifth) card: the person page pairs About +
   License + Contact, and any card can self-hide, so the last card fills the
   row whenever it would otherwise sit alone in a half-width cell. */
.cg-detail-grid > .cg-detail-card:last-child:nth-child(odd) { grid-column: 1 / -1; }

.cg-detail-card { margin-top: 14px; }
.cg-detail-grid > .cg-detail-card { margin-top: 0; }

.cg-detail-rows {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.cg-detail-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 13px;
  color: var(--fg-2);
}
.cg-detail-row-icon {
  flex: 0 0 auto;
  color: var(--fg-4);
  margin-top: 2px;
  display: inline-flex;
}
.cg-detail-row-body { min-width: 0; word-break: break-word; }

.cg-detail-link {
  color: var(--brand-text, var(--brand));
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.cg-detail-link:hover { text-decoration: underline; }

/* Socials — round icon buttons: moved to design-system/components.css when
   <SocialLinks/> became a DS component (the extension renders the same
   markup, so the rule can't live in a surface stylesheet). */

/* Ratings row — Google + Yelp badges side by side */
.cg-ratings-row {
  display: inline-flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}

/* Extra header line under the entity h1/meta for ratings + socials */
.cg-org-head-extra {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 10px;
}

/* Open hours */
.cg-hours {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.cg-hours-row {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  font-size: 12.5px;
  padding: 4px 0;
  border-bottom: 1px dashed var(--line);
}
.cg-hours-row:last-child { border-bottom: 0; }
.cg-hours-day { color: var(--fg-2); }
.cg-hours-val { color: var(--fg-3); font-size: 11.5px; }

/* License rows — label above value */
.cg-lic-row {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* Export popover */
.cg-export-popover-wrap {
  position: fixed; top: 0; left: 0;
  z-index: 50;
  pointer-events: none;
}
.cg-export-popover {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-lg);
  width: 380px;
  max-width: calc(100vw - 16px); /* narrow viewports (filters-bar export) */
  overflow: hidden;
  pointer-events: auto;
}
.cg-export-popover-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 14px;
  border-bottom: 1px solid var(--line);
  font-size: 12px; font-weight: 600;
  letter-spacing: .04em; text-transform: uppercase;
  color: var(--fg-2);
}
/* Export cap notice — shown when the current selection exceeds the 10,000-record
   export limit, so the download will be a sample. Informational, not an error:
   --info, not --warn/--bad. */
.cg-export-cap {
  padding: 9px 14px;
  background: color-mix(in oklab, var(--info) 16%, var(--bg-2));
  border-bottom: 1px solid color-mix(in oklab, var(--info) 38%, var(--line));
  color: color-mix(in oklab, var(--info) 45%, var(--fg));
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .02em;
}

.cg-popover-close {
  background: none; border: 0; cursor: pointer;
  color: var(--fg-4); padding: 2px; display: flex;
  border-radius: var(--r-sm);
}
.cg-popover-close:hover { color: var(--fg); background: var(--bg-hover); }
.cg-export-list {
  display: flex; flex-direction: column;
  max-height: 360px; overflow-y: auto;
}
.cg-export-item {
  width: 100%; text-align: left;
  background: transparent; border: 0;
  padding: 12px 14px;
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 12px;
  cursor: pointer;
  transition: background .12s var(--ease);
  border-bottom: 1px solid var(--line);
}
.cg-export-item:last-child { border-bottom: 0; }
.cg-export-item:hover { background: var(--bg-hover); }
.cg-export-item-left {
  display: flex; flex-direction: column; gap: 3px;
  flex: 1; min-width: 0;
}
.cg-export-fmt {
  font-size: 13px;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--fg); font-weight: 600;
}
.cg-export-desc {
  font-size: 12.5px;
  color: var(--fg-2);
  line-height: 1.4;
}
.cg-export-item-right {
  display: flex; align-items: center; gap: 8px;
  flex: 0 0 auto;
  color: var(--fg-4);
}
.cg-export-size {
  font-size: 10.5px;
  color: var(--fg-4);
  font-variant-numeric: tabular-nums;
}

/* Each format arrives on its own beat as the popover opens — a short,
   staggered rise that reads as a list being dealt, not as five things
   appearing at once. --cg-export-i is the row's index, set inline. */
.cg-export-item {
  animation: cg-export-in .26s var(--ease) both;
  animation-delay: calc(var(--cg-export-i, 0) * 34ms);
  position: relative;
  overflow: hidden;
}
@keyframes cg-export-in {
  from { opacity: 0; transform: translateY(5px); }
  to   { opacity: 1; transform: none; }
}
.cg-export-item:disabled { cursor: default; }
/* Only the row being downloaded keeps full contrast; the others step back so
   the popover reads as busy rather than as broken. */
.cg-export-item:disabled:not(.busy) { opacity: .45; }
.cg-export-item.busy .cg-export-fmt { color: var(--brand-text); }
.cg-export-item.done .cg-export-size,
.cg-export-item.done .cg-export-item-right { color: var(--good); }
.cg-export-item.failed .cg-export-desc,
.cg-export-item.failed .cg-export-item-right { color: var(--bad); }

/* Indeterminate sweep along the row's base while the file is being built.
   The request has no measurable progress — the body arrives whole — so a
   percentage would be a fiction. */
.cg-export-progress {
  position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: linear-gradient(
    90deg,
    transparent,
    var(--brand) 45%,
    var(--brand) 55%,
    transparent
  );
  background-size: 45% 100%;
  background-repeat: no-repeat;
  animation: cg-export-sweep 1.15s var(--ease) infinite;
}
@keyframes cg-export-sweep {
  from { background-position: -45% 0; }
  to   { background-position: 145% 0; }
}

/* How many records this download covers — the count the popover used to
   fake with a fixed MB figure. */
.cg-export-scope {
  display: flex; align-items: baseline; gap: 7px;
  padding: 11px 14px;
  border-bottom: 1px solid var(--line);
}
.cg-export-scope-count {
  font-size: 18px;
  color: var(--fg);
  font-variant-numeric: tabular-nums;
}
.cg-export-scope-label {
  font-size: 12px;
  color: var(--fg-3);
}

/* Shown in place of the format list when the plan has no export. */
.cg-export-upgrade {
  padding: 16px 14px 15px;
  display: flex; flex-direction: column; align-items: flex-start; gap: 8px;
}
.cg-export-upgrade-title {
  font-family: var(--font-serif);
  font-size: 16px;
  color: var(--fg);
}
.cg-export-upgrade-body {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--fg-2);
}

@media (prefers-reduced-motion: reduce) {
  /* Static equivalents: the states still READ, they just don't move. */
  .cg-export-item { animation: none; }
  .cg-export-progress {
    animation: none;
    background: var(--brand);
    background-size: 100% 100%;
    opacity: .5;
  }
}


/* ---------- Market demographics panel (facility + person pages) ---------- */
.cg-demo-card { margin-top: 14px; }
.cg-demo-vintage { font-size: 11px; color: var(--fg-4); }
.cg-demo-note { font-size: 12px; color: var(--fg-3); margin: 2px 0 10px; }
.cg-demo-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 14px;
  margin: 10px 0 16px;
}
.cg-demo-stat-sub { font-size: 11px; color: var(--fg-4); margin-top: 2px; }
.cg-demo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 18px 22px;
}
.cg-demo-meters { display: grid; gap: 6px; margin-top: 8px; }
.cg-demo-immediate {
  margin-top: 14px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
  font-size: 11px;
  color: var(--fg-3);
}

/* ---------- Consumer spending panel (org + facility + person pages) ---------- */
.cg-spend-when { font-size: 11px; color: var(--fg-4); }
.cg-spend-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 14px;
  margin: 10px 0 12px;
}
.cg-spend-stat-delta { font-size: 15px; line-height: 1.6; }
/* The County / State rail — the DS tab bar, spaced for a card. */
.cg-spend-views { margin: 2px 0 10px; }
/* How an estimate was made: always rendered, never behind a hover. */
.cg-spend-method { font-size: 11.5px; line-height: 1.45; color: var(--fg-3); margin: -2px 0 10px; }
.cg-spend-chart { margin: 4px 0 2px; }
.cg-spend-svg { display: block; width: 100%; height: 110px; overflow: visible; }
.cg-spend-chart.is-compact .cg-spend-svg { width: 96px; height: 26px; }
.cg-spend-area { fill: var(--brand-glow); stroke: none; }
.cg-spend-line { fill: none; stroke: var(--brand); stroke-width: 1.5; }
.cg-spend-hit { fill: transparent; }
.cg-spend-hit:hover { fill: var(--grid); }
.cg-spend-axis {
  display: flex; justify-content: space-between;
  font-size: 10.5px; color: var(--fg-4); margin-top: 4px;
}
.cg-spend-disciplines {
  margin-top: 16px; padding-top: 12px;
  border-top: 1px solid var(--line);
}
.cg-spend-group { margin-top: 10px; }
.cg-spend-group-label { font-size: 12px; color: var(--fg-2); margin: 6px 0 2px; }
.cg-spend-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto 70px 96px;
  align-items: center;
  gap: 12px;
  padding: 7px 0;
  border-bottom: 1px solid var(--line);
}
.cg-spend-row:last-child { border-bottom: none; }
.cg-spend-row-name { font-size: 13px; color: var(--fg); }
.cg-spend-row-place { font-size: 10.5px; color: var(--fg-4); margin-top: 1px; }
.cg-spend-row-for { font-size: 11px; color: var(--fg-3); margin-top: 2px; }
.cg-spend-row-value { display: flex; align-items: baseline; gap: 6px; font-size: 13px; }
.cg-spend-row-year { font-size: 10.5px; color: var(--fg-4); }
.cg-spend-row-delta { font-size: 11.5px; text-align: right; }
.cg-spend-basis { margin-top: 12px; font-size: 11px; color: var(--fg-4); }
@media (max-width: 640px) {
  .cg-spend-row { grid-template-columns: minmax(0, 1fr) auto; }
  .cg-spend-row-delta { text-align: left; }
  .cg-spend-row .cg-spend-chart.is-compact { display: none; }
}

/* Health-concern demand card (2026-09-29) — facility/org "condition_demand"
   section. Each row is one clickable button so the whole row, not just a
   link fragment, opens the map filtered to that condition; flex-wrap over a
   fixed grid is what keeps it readable at 375px without a breakpoint. */
.cg-cond-lede { font-size: 12.5px; color: var(--fg-3); margin: 2px 0 8px; }
.cg-cond-list { list-style: none; padding: 0; margin: 0; }
.cg-cond-row { border-bottom: 1px dashed var(--line); }
.cg-cond-row:last-child { border-bottom: 0; }
.cg-cond-row-btn {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  width: 100%;
  gap: 6px 14px;
  margin: 0;
  padding: 8px 4px 2px;
  background: none;
  border: 0;
  border-radius: var(--r-sm);
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.cg-cond-row-btn:hover { background: var(--bg-hover); }
.cg-cond-row-btn:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.cg-cond-row-label { flex: 1 1 150px; min-width: 0; }
.cg-cond-row-name { font-size: 13px; color: var(--fg); }
.cg-cond-row-cat { display: block; font-size: 10.5px; color: var(--fg-4); margin-top: 1px; }
.cg-cond-row-burden { display: inline-flex; align-items: center; gap: 5px; }
.cg-cond-burden-swatch {
  display: inline-block;
  width: 14px; height: 10px;
  border-radius: var(--r-xs);
  box-shadow: inset 0 0 0 1px var(--line);
  flex: 0 0 auto;
}
.cg-cond-row-trend { min-width: 46px; font-size: 11px; color: var(--fg-3); text-align: right; }
.cg-cond-row-est {
  margin: 0 4px 4px;
  font-size: 10px;
  color: var(--fg-4);
  text-transform: uppercase;
  letter-spacing: .04em;
}
.cg-cond-because { margin: 0 4px 10px; font-size: 12px; color: var(--fg-3); line-height: 1.4; }
.cg-cond-more {
  background: none;
  border: 0;
  padding: 0;
  margin-top: 8px;
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--fg-3);
}
.cg-cond-more:hover { color: var(--fg); }
.cg-cond-foot { margin-top: 12px; font-size: 11px; color: var(--fg-4); }
.cg-cond-skel { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.cg-cond-skel .cg-mkt-skeleton { height: 44px; }

/* ---------- Corporate profile card (org Overview lead block) ----------
   The "company page" treatment: description with its licence attribution,
   fact grid, financial numerals on a hairline rule, leadership, products,
   and the HQ photo hanging in a side column when one exists. */
.cg-corp-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 20px;
}
.cg-corp-grid.has-photo {
  grid-template-columns: minmax(0, 1fr) 280px;
}
@media (max-width: 900px) {
  .cg-corp-grid.has-photo { grid-template-columns: minmax(0, 1fr); }
  .cg-corp-photo { max-width: 420px; }
}
.cg-corp-desc {
  margin: 10px 0 4px;
  max-width: 72ch;
  font-size: 14px;
  line-height: 1.55;
  color: var(--fg);
}
.cg-corp-attrib {
  font-size: 10.5px;
  color: var(--fg-3);
}
.cg-corp-attrib a {
  color: var(--fg-2);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.cg-corp-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 12px 24px;
  margin-top: 16px;
}
.cg-corp-fact-val {
  margin-top: 3px;
  font-size: 13.5px;
  color: var(--fg);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}
.cg-corp-ticker { flex: none; }
.cg-corp-yr { color: var(--fg-4); font-size: 11px; }
.cg-corp-fins {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 34px;
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}
.cg-corp-fin { display: flex; flex-direction: column; gap: 2px; }
.cg-corp-fin-num { font-size: 22px; line-height: 1.15; }
.cg-corp-people, .cg-corp-products { margin-top: 16px; }
.cg-corp-people-list {
  margin-top: 5px;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 18px;
  font-size: 13px;
}
.cg-corp-person a {
  color: var(--fg);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.cg-corp-role { color: var(--fg-2); }
.cg-corp-products-list {
  margin-top: 6px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.cg-corp-photo {
  margin: 0;
  align-self: start;
  border: 1px solid var(--line);
  background: var(--bg-2);
}
.cg-corp-photo img { width: 100%; display: block; }
.cg-corp-photo figcaption {
  padding: 6px 9px;
  font-size: 10px;
  color: var(--fg-3);
  border-top: 1px solid var(--line);
}
.cg-corp-photo figcaption a {
  color: var(--fg-2);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Real company logo inside the DS monogram tile: third-party marks are drawn
   for light surfaces, so the tile flips to the theme-invariant art well. */
.cg-logo.cg-logo-haswork { background: var(--art-well); }
.cg-logo .cg-logo-art {
  width: 100%;
  height: 100%;
  display: block;
  padding: 11%;
  box-sizing: border-box;
}
.cg-logo .cg-logo-art svg { width: 100%; height: 100%; display: block; }
.cg-logo .cg-logo-art img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

/* Vocabulary currency disclosure (PROD-580). An NLM licence obligation, so it
   renders inline and always — never behind a tooltip or an expander. Sizes are
   literal px to match the surrounding cards; colours are tokens only. */
.cg-vocab-asof { font-size: 11px; color: var(--fg-4); }
.cg-vocab-notice { font-size: 12px; color: var(--fg-3); margin: 2px 0 8px; }
.cg-vocab-attrib { list-style: none; margin: 0; padding: 0; }
.cg-vocab-attrib li {
  font-size: 11px;
  line-height: 1.5;
  color: var(--fg-4);
  margin-top: 4px;
}

/* ---- Watching — the org-header toggle (watch.jsx) ------------------------
   One GUI.Button whose variant flips between `primary` (not yet watching —
   the page's one filled action) and the hairline default once watching, so
   the resting states are pure DS. What is added here is the MOMENT of change:
   the icon draws itself in, the button breathes once, and a single gold ring
   (brand as accent, never as a fill) radiates and fades. Reduced-motion users
   get the state change with none of the choreography. Tokens only. */
.cg-watch-wrap { position: relative; display: inline-flex; align-items: center; }
.cg-watch-btn { position: relative; overflow: visible; }
.cg-watch-icon {
  display: inline-flex; align-items: center;
  transition: transform .25s var(--ease), color .2s var(--ease);
}
.cg-watch-btn.is-watched .cg-watch-icon { color: var(--good); }
.cg-watch-btn.is-watched .cg-watch-icon svg path {
  stroke-dasharray: 24; stroke-dashoffset: 0;
}
.cg-watch-btn.flash-on .cg-watch-icon svg path {
  animation: cg-watch-draw .45s var(--ease) both;
}
.cg-watch-btn.flash-on { animation: cg-watch-breathe .5s var(--ease); }
.cg-watch-btn.flash-on::after {
  content: ""; position: absolute; inset: -1px; border-radius: inherit;
  border: 1px solid var(--brand); pointer-events: none;
  animation: cg-watch-ring .9s var(--ease) forwards;
}
.cg-watch-btn.flash-off .cg-watch-icon { transform: rotate(-12deg) scale(.9); }
.cg-watch-btn.flash-err { animation: cg-watch-shake .4s var(--ease); }
.cg-watch-btn[aria-busy="true"] .cg-watch-label { opacity: .7; }
.cg-watch-toast {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 3;
  white-space: nowrap; font-size: 12px; color: var(--fg-2);
  background: var(--bg-2); border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 6px 10px;
  animation: cg-watch-toast .25s var(--ease) both;
}
.cg-watch-toast.is-error { color: var(--bad); border-color: color-mix(in oklab, var(--bad) 35%, var(--line)); }
/* The read receipt (PROD-504): "N new since you last looked" sits in the
   toast's slot while the count is still unread, then drains — the gold rule
   under it is the unread mark, and it recedes as the org is marked read. */
.cg-watch-receipt {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 3;
  white-space: nowrap; font-size: 11px; letter-spacing: .01em; color: var(--brand-text);
  background: var(--bg-2); border: 1px solid color-mix(in oklab, var(--brand) 40%, var(--line));
  border-radius: var(--r-sm); padding: 5px 10px;
  animation: cg-watch-toast .25s var(--ease) both;
  transition: opacity .6s var(--ease), transform .6s var(--ease), color .6s var(--ease), border-color .6s var(--ease);
}
.cg-watch-receipt::after {
  content: ""; position: absolute; left: 10px; right: 10px; bottom: -1px; height: 1px;
  background: var(--brand); transform-origin: left; transition: transform .8s var(--ease);
}
.cg-watch-receipt.is-read { color: var(--fg-3); border-color: var(--line); opacity: .55; transform: translateY(2px); }
.cg-watch-receipt.is-read::after { transform: scaleX(0); }
@keyframes cg-watch-draw {
  from { stroke-dashoffset: 24; }
  to   { stroke-dashoffset: 0; }
}
@keyframes cg-watch-breathe {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.04); }
  100% { transform: scale(1); }
}
@keyframes cg-watch-ring {
  0%   { opacity: .9; transform: scale(1); }
  100% { opacity: 0;  transform: scale(1.35); }
}
@keyframes cg-watch-shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-3px); }
  75% { transform: translateX(3px); }
}
@keyframes cg-watch-toast {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .cg-watch-btn, .cg-watch-btn::after, .cg-watch-icon, .cg-watch-icon svg path,
  .cg-watch-toast, .cg-watch-receipt, .cg-watch-receipt::after { animation: none !important; transition: none !important; }
  .cg-watch-btn.flash-on::after { display: none; }
}

/* ---- Watchlist — account settings (account-settings.jsx) -----------------
   Layout classes only; every colour/radius/ease is a token and the controls
   are DS primitives (Card, Kicker, Pill, Button). Rows reveal with a short
   stagger and leave with a collapse; reduced-motion gets neither. */
.cg-watchlist-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.cg-watchlist-count { font-size: 11px; color: var(--fg-3); }
.cg-page .cg-watchlist-sub { margin: 6px 0 14px; max-width: 62ch; }
.cg-watchlist-rows { list-style: none; margin: 0; padding: 0; display: grid; }
.cg-watchlist-row {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr) auto auto auto;
  align-items: center; gap: 14px;
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
  animation: cg-watchlist-in .3s var(--ease) both;
  transition: opacity .2s var(--ease), transform .2s var(--ease);
}
.cg-watchlist-row:last-child { border-bottom: 0; }
.cg-watchlist-row.is-leaving { opacity: 0; transform: translateX(8px); }
.cg-watchlist-name {
  font-family: var(--font-serif); font-size: 17px; font-weight: 500;
  color: var(--fg); text-decoration: none;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  transition: color .15s var(--ease);
}
.cg-watchlist-name:hover { color: var(--brand-text); text-decoration: underline; text-underline-offset: 3px; }
.cg-watchlist-meta, .cg-watchlist-since { font-size: 11px; color: var(--fg-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cg-watchlist-unwatch { padding: 4px 10px; font-size: 12px; }
.cg-watchlist-empty {
  padding: 22px 4px 8px; color: var(--fg-2); font-size: 13px; line-height: 1.55; max-width: 56ch;
  display: grid; gap: 10px; justify-items: start;
}
.cg-watchlist-empty-title { font-family: var(--font-serif); font-size: 21px; font-weight: 500; color: var(--fg); }
.cg-watchlist-cta { margin-top: 4px; }
.cg-watchlist-error { margin-top: 10px; font-size: 12px; color: var(--bad); }
@keyframes cg-watchlist-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (max-width: 900px) {
  .cg-watchlist-row { grid-template-columns: minmax(0, 1fr) auto; grid-auto-flow: row; }
  .cg-watchlist-meta, .cg-watchlist-since { grid-column: 1 / -1; }
}
@media (prefers-reduced-motion: reduce) {
  .cg-watchlist-row { animation: none; transition: none; }
}

/* ---- Notifications — account settings (account-settings.jsx, PROD-638) ---
   Sits directly under the Watchlist card and shares its head/sub classes, so
   "what I watch" and "how I hear" read as one place rather than two designs.
   Layout only: every colour, radius and ease is a token, the controls are DS
   primitives (Card, Kicker, Switch, Button, Pill), and the type rows use the
   same short stagger the watchlist rows do. */
.cg-notify-body { display: grid; gap: 4px; }
.cg-notify-row {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  padding: 14px 0;
  border-bottom: 1px solid var(--line);
}
.cg-notify-label { font-size: 14px; font-weight: 500; color: var(--fg); }
.cg-notify-hint {
  font-size: 12px; line-height: 1.5; color: var(--fg-3);
  max-width: 52ch; margin-top: 2px;
}
.cg-notify-saved { font-size: 11px; color: var(--good); animation: cg-watchlist-in .3s var(--ease) both; }
/* Segmented cadence control: ink-inverse on the selected segment, never a
   brand fill (editorial contract rule 6 — gold is not a button colour). */
.cg-notify-cadence { display: flex; gap: 8px; flex: 0 0 auto; }
.cg-notify-seg { padding: 4px 14px; font-size: 13px; }
.cg-notify-seg.is-on {
  background: var(--fg); color: var(--bg); border-color: var(--fg);
}
.cg-notify-types { padding: 16px 0 2px; }
.cg-notify-type-rows { list-style: none; margin: 10px 0 0; padding: 0; display: grid; }
.cg-notify-type {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  padding: 11px 0;
  border-bottom: 1px solid var(--line);
  animation: cg-watchlist-in .3s var(--ease) both;
}
.cg-notify-type:last-child { border-bottom: 0; }
.cg-notify-type-label { font-size: 13.5px; font-weight: 500; color: var(--fg); }
/* Not yet available: legible, clearly not a control, never a dead switch. */
.cg-notify-type.is-soon .cg-notify-type-label { color: var(--fg-2); }
.cg-notify-type.is-soon .cg-notify-hint { color: var(--fg-4); }
@media (max-width: 700px) {
  .cg-notify-row, .cg-notify-type { flex-direction: column; align-items: flex-start; gap: 10px; }
  .cg-notify-cadence { width: 100%; }
  .cg-notify-seg { flex: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .cg-notify-type, .cg-notify-saved { animation: none; }
}

/* ------------------------------------------------------------
   Ordered specialty slots (PROD-26). A slot is a hairline chip; the
   primary carries a small gold rank tag. They stagger in left to right so
   the primary is met first — reduced-motion users get them all at once.
   ------------------------------------------------------------ */
.cg-slot-group { margin-top: 12px; }
.cg-slot-group:first-child { margin-top: 0; }
.cg-slot-group-label {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--fg-4);
  margin-bottom: 6px;
}
.cg-slot-row { display: flex; flex-wrap: wrap; gap: 8px; }
.cg-slot {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--bg-1);
  font-size: 12.5px;
  color: var(--fg-2);
  animation: cg-slot-in .32s var(--ease) both;
  animation-delay: calc(var(--slot-i, 0) * 45ms);
  transition: border-color .15s var(--ease), color .15s var(--ease);
}
.cg-slot:hover { border-color: var(--line-strong); color: var(--fg); }
.cg-slot.is-primary {
  color: var(--fg);
  border-color: color-mix(in oklab, var(--brand) 45%, var(--line));
  background: color-mix(in oklab, var(--brand) 8%, var(--bg-1));
}
.cg-slot-rank {
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--brand-text, var(--brand));
}
@keyframes cg-slot-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .cg-slot { animation: none; transition: none; }
}

/* Education card (PROD-9): the years-in-practice figure leads, serif and
   large, with its label set small beside it. */
.cg-edu-years {
  display: flex; align-items: baseline; gap: 8px;
  margin-bottom: 12px;
}
.cg-edu-years-label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .04em;
  color: var(--fg-3);
}

/* ------------------------------------------------------------
   Key-account profile (Account tab, hospital blocks, payer page).
   Layout + motion only: every color/radius/font is a token. Motion is
   purposeful and never blocks reading — a staggered rise on the blocks
   (`--i` sets the order), meters that draw to their value, a connector
   line drawn in — and the reduced-motion block at the end makes every one
   of them static.
   ------------------------------------------------------------ */
.cg-acct-strip {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 12px;
  margin-bottom: 18px;
}
@media (max-width: 1000px) { .cg-acct-strip { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 640px)  { .cg-acct-strip { grid-template-columns: repeat(2, 1fr); } }

.cg-acct-in {
  animation: cg-acct-rise .55s var(--ease) both;
  animation-delay: calc(var(--i, 0) * 70ms);
}
@keyframes cg-acct-rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

/* A stat tile whose number counts up; the serif number is the editorial
   voice of the page, the mono sub-line is the measurement. */
.cg-acct-stat { padding: 16px 18px; position: relative; overflow: hidden; }
.cg-acct-stat::after {
  content: "";
  position: absolute; left: 18px; right: 18px; bottom: 0;
  height: 2px;
  background: var(--brand);
  transform: scaleX(0);
  transform-origin: left;
  animation: cg-acct-grow .9s cubic-bezier(.2,.8,.2,1) both;
  animation-delay: calc(var(--i, 0) * 70ms + 250ms);
}
@keyframes cg-acct-grow { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.cg-acct-stat-sub { font-size: 11px; color: var(--fg-3); margin-top: 4px; }

/* Meter lists — the DS MeterRow, stacked; rows rise in sequence. */
.cg-acct-meters { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
.cg-acct-meters .cg-meter-row { --meter-label-w: 150px; }
.cg-acct-meters.narrow .cg-meter-row { --meter-label-w: 110px; }
.cg-acct-meters.wide .cg-meter-row { --meter-label-w: 210px; }
.cg-acct-meters.wide .cg-meter-row { --meter-label-w: 210px; }
.cg-acct-meters .cg-meter-row-fill { transition: width .9s cubic-bezier(.2,.8,.2,1); }

/* Star row for a 1-5 rating: filled stars carry the brand gold, empty ones
   the hairline. Text glyphs so the DS needs no icon family. */
.cg-acct-stars { display: inline-flex; gap: 2px; font-size: 18px; line-height: 1; letter-spacing: 0; }
.cg-acct-stars .on  { color: var(--brand); }
.cg-acct-stars .off { color: var(--line-strong); }

/* Ranked lists (experts, research items, hospitals) */
.cg-acct-list { list-style: none; margin: 10px 0 0; padding: 0; display: flex; flex-direction: column; }
.cg-acct-list li {
  display: grid;
  grid-template-columns: 28px 1fr auto;
  gap: 10px;
  align-items: center;
  padding: 9px 4px;
  border-bottom: 1px dashed var(--line);
  transition: background .15s var(--ease);
}
.cg-acct-list li:last-child { border-bottom: 0; }
.cg-acct-list li.clickable { cursor: pointer; }
.cg-acct-list li.clickable:hover { background: var(--bg-hover); }
.cg-acct-rank {
  font-family: var(--font-serif);
  font-size: 18px;
  color: var(--fg-4);
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.cg-acct-list-title { font-size: 13px; color: var(--fg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cg-acct-list-sub { font-size: 11px; color: var(--fg-4); margin-top: 2px; }
.cg-acct-list-val { font-family: var(--font-mono); font-size: 12px; color: var(--fg-3); white-space: nowrap; }

/* Research-activity strip: four counts joined by a drawn connector. */
.cg-acct-research { position: relative; display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-top: 10px; }
@media (max-width: 640px) { .cg-acct-research { grid-template-columns: repeat(2, 1fr); } }
.cg-acct-research-cell { padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--bg-1); }
.cg-acct-research-cell .cg-stat-num { font-size: 26px; }
.cg-acct-connector { position: absolute; left: 0; right: 0; top: -8px; height: 8px; pointer-events: none; }
.cg-acct-connector line {
  stroke: var(--brand);
  stroke-width: 1.5;
  stroke-dasharray: 1200;
  stroke-dashoffset: 1200;
  animation: cg-acct-draw 1.4s var(--ease) forwards;
  animation-delay: .3s;
}
@keyframes cg-acct-draw { to { stroke-dashoffset: 0; } }

/* The account grid itself — two columns, a block may span both. */
.cg-acct-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 1000px) {
  .cg-acct-grid { grid-template-columns: 1fr; }
  .cg-acct-grid > .cg-card[style*="span 2"] { grid-column: auto !important; }
}
.cg-acct-note { font-size: 11px; color: var(--fg-4); margin-top: 10px; line-height: 1.5; }
.cg-acct-empty { font-size: 13px; color: var(--fg-3); padding: 14px 0 4px; }

/* Payer page hero: the enrollment number is the page. */
.cg-payer-hero { display: grid; grid-template-columns: 1fr auto; gap: 18px; align-items: end; margin-bottom: 18px; }
@media (max-width: 800px) { .cg-payer-hero { grid-template-columns: 1fr; } }
.cg-payer-hero .cg-stat-num { font-size: 54px; line-height: 1; }

@media (prefers-reduced-motion: reduce) {
  .cg-acct-in { animation: none; }
  .cg-acct-stat::after { animation: none; transform: none; }
  .cg-acct-meters .cg-meter-row-fill { transition: none; }
  .cg-acct-connector line { animation: none; stroke-dashoffset: 0; }
}

/* Org profile → Experts door (PROD-38). */
.cg-org-experts-body { display: grid; gap: 14px; margin-top: 8px; }
.cg-org-experts-num { font-size: 40px; }
.cg-org-experts-sub { font-size: 12px; color: var(--fg-3); margin-top: 2px; }
.cg-org-experts-areas { display: grid; gap: 6px; }
.cg-org-experts .cg-card-head .cg-btn { gap: 6px; }

/* ------------------------------------------------------------
   Payer mix donut (PROD-49). Three slices only: two measured shares and a
   hatched residual that says "not publicly reported". The ring draws in
   (stroke-dashoffset), the legend rows rise after it; reduced-motion gets
   the finished ring.
   ------------------------------------------------------------ */
.cg-pmix { display: grid; grid-template-columns: 168px 1fr; gap: 20px; align-items: center; margin-top: 10px; }
@media (max-width: 640px) { .cg-pmix { grid-template-columns: 1fr; } }
.cg-pmix-ring { width: 168px; height: 168px; display: block; }
.cg-pmix-ring .track { fill: none; stroke: var(--line); stroke-width: 18; }
.cg-pmix-ring .slice { fill: none; stroke-width: 18; transition: stroke-dashoffset 1.1s cubic-bezier(.2,.8,.2,1); }
/* Slices are positional (the API fixes their order): the first two are the
   measured public-program shares, the third is the hatched residual. */
.cg-pmix-ring .slice.slice-0 { stroke: var(--brand); }
.cg-pmix-ring .slice.slice-1 { stroke: var(--deep-slate); }
.cg-pmix-ring .slice.slice-2 { stroke: url(#cg-pmix-hatch); }
.cg-pmix-center { font-family: var(--font-serif); font-size: 26px; fill: var(--fg); }
.cg-pmix-center-sub { font-family: var(--font-mono); font-size: 9px; letter-spacing: .06em; fill: var(--fg-4); text-transform: uppercase; }
.cg-pmix-legend { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.cg-pmix-legend li {
  display: grid; grid-template-columns: 14px 1fr auto; gap: 10px; align-items: center;
  padding: 6px 0; border-bottom: 1px dashed var(--line);
}
.cg-pmix-legend li:last-child { border-bottom: 0; }
.cg-pmix-swatch { width: 14px; height: 14px; border-radius: var(--r-xs); background: var(--brand); }
.cg-pmix-swatch.slice-1 { background: var(--deep-slate); }
.cg-pmix-swatch.slice-2 {
  background: repeating-linear-gradient(135deg, var(--line-strong) 0 2px, transparent 2px 5px);
  border: 1px solid var(--line-strong);
}
.cg-pmix-pct { font-family: var(--font-serif); font-size: 20px; color: var(--fg); font-variant-numeric: tabular-nums; }
.cg-pmix-label { font-size: 13px; color: var(--fg); }
.cg-pmix-sub { font-size: 11px; color: var(--fg-4); margin-top: 1px; }
.cg-pmix-unc { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); }
@media (max-width: 640px) { .cg-pmix-unc { grid-template-columns: repeat(2, 1fr); } }
.cg-pmix-unc .cg-stat-num { font-size: 20px; }
@media (prefers-reduced-motion: reduce) {
  .cg-pmix-ring .slice { transition: none; }
}

/* ------------------------------------------------------------
   Disease areas (PROD-48). Horizontal bars ranked by discharges, each
   drawn to its share with a stagger; the caveat and coverage ratio sit in
   the card body, never in a tooltip. Reduced-motion: bars land finished.
   ------------------------------------------------------------ */
.cg-dx-head { display: flex; gap: 22px; flex-wrap: wrap; align-items: flex-end; margin-top: 6px; }
.cg-dx-head .cg-stat-num { font-size: 28px; }
.cg-dx-list { list-style: none; margin: 14px 0 0; padding: 0; display: flex; flex-direction: column; gap: 7px; }
.cg-dx-row { display: grid; grid-template-columns: minmax(0, 190px) 1fr auto; gap: 12px; align-items: center; }
.cg-dx-label { font-size: 12.5px; color: var(--fg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cg-dx-track { height: 10px; background: var(--line); border-radius: var(--r-xs); overflow: hidden; }
.cg-dx-fill {
  display: block; height: 100%; background: var(--brand); border-radius: var(--r-xs);
  transform-origin: left; transform: scaleX(var(--w, 0));
  transition: transform .9s cubic-bezier(.2,.8,.2,1);
  transition-delay: calc(var(--i, 0) * 45ms);
}
.cg-dx-val { font-family: var(--font-mono); font-size: 11.5px; color: var(--fg-3); white-space: nowrap; font-variant-numeric: tabular-nums; }
.cg-dx-caveat {
  margin-top: 12px; padding: 10px 12px;
  border-left: 2px solid var(--brand);
  background: var(--bg-1);
  font-size: 12px; color: var(--fg-2); line-height: 1.5;
}
.cg-dx-cond { margin-top: 14px; }
.cg-dx-cond .cg-acct-meters { margin-top: 8px; }
.cg-dx-cond .cg-meter-row { --meter-label-w: 190px; }
@media (max-width: 640px) { .cg-dx-row { grid-template-columns: minmax(0, 120px) 1fr auto; } }
@media (prefers-reduced-motion: reduce) {
  .cg-dx-fill { transition: none; }
}

/* ------------------------------------------------------------
   Patients, all payers. Every other patient figure on the page is drawn from
   a programme that covers only part of the population, so this is the only one
   that describes everyone the organization treats.

   ⚠ This file is served to the browser verbatim, so a COMMENT here is a
   customer surface — no data-origin names, in prose or in comments
   (CLAUDE.md -> Source attribution is internal-only). An earlier draft of this
   block named two programmes and tripped the guard.

   The year bars are a shape, not a chart: no axis, because the headline
   number is the claim and the bars only say whether it is rising. A
   PART-YEAR bar is drawn hollow — shown, because hiding it would make the
   latest year look missing, and never solid, because a partial count read
   as a finished one looks like a collapse in volume.

   Reduced-motion: bars land finished, same as the disease-area fills.
   ------------------------------------------------------------ */
.cg-pt-series {
  margin-top: 16px; display: flex; align-items: flex-end; gap: 10px;
  height: 62px;
}
.cg-pt-bar-wrap {
  flex: 1 1 0; display: flex; flex-direction: column; justify-content: flex-end;
  align-items: stretch; height: 100%; min-width: 0;
}
.cg-pt-bar {
  background: var(--brand); border-radius: var(--r-xs) var(--r-xs) 0 0;
  transform-origin: bottom; animation: cg-pt-grow .8s cubic-bezier(.2,.8,.2,1) both;
}
/* The period still in progress: outlined, never filled. */
.cg-pt-bar[data-partial="1"] {
  background: transparent;
  border: 1px dashed var(--brand);
  border-bottom: none;
}
.cg-pt-bar-label {
  margin-top: 5px; font-size: 10px; color: var(--fg-4);
  text-align: center; font-variant-numeric: tabular-nums;
}
.cg-pt-basis {
  margin-top: 14px; padding: 10px 12px;
  border-left: 2px solid var(--brand);
  background: var(--bg-1);
  font-size: 12px; color: var(--fg-2); line-height: 1.5;
}
@keyframes cg-pt-grow { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@media (prefers-reduced-motion: reduce) {
  .cg-pt-bar { animation: none; }
}

/* Primary affiliation line under the person's name (PROD-25) and the
   affiliation rows: the primary row carries the gold rank tag, former rows
   sit back in --fg-3; rows stagger in like the specialty slots. */
.cg-person-primary {
  display: inline-flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  margin-top: 8px; font-size: 13px; color: var(--fg-2);
}
.cg-person-primary-verb { color: var(--fg-3); }
.cg-person-primary-link {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; font-weight: 500; color: var(--fg);
  border-bottom: 1px solid color-mix(in oklab, var(--brand) 55%, transparent);
  transition: border-color .15s var(--ease), color .15s var(--ease);
}
.cg-person-primary-link:hover { color: var(--brand-text, var(--brand)); border-color: var(--brand); }
.cg-person-primary-where { color: var(--fg-3); font-size: 12px; }
.cg-aff-row { animation: cg-slot-in .3s var(--ease) both; animation-delay: calc(var(--row-i, 0) * 40ms); }
.cg-aff-row.is-past td { color: var(--fg-3); }
.cg-aff-rank { margin-right: 8px; }
.cg-aff-former {
  margin-left: 8px; font-family: var(--font-mono); font-size: 9.5px;
  letter-spacing: .08em; text-transform: uppercase; color: var(--fg-4);
}
@media (prefers-reduced-motion: reduce) {
  .cg-aff-row { animation: none; }
  .cg-person-primary-link { transition: none; }
}
.cg-person-primary-dept { color: var(--fg-2); font-weight: 500; }
/* ---- Watched organizations get visual priority (PROD-516) ---------------
   The shared <WatchMark> (design-system) sits beside the name in every org
   row, the drawer title and the search results; these are the layout
   touches around it — a gold rule on a watched row's edge, the drawer's
   mark spacing, and the "Watching only" bar above the org table. */
.cg-table tr.is-watched td:first-child { box-shadow: inset 2px 0 0 var(--brand); }
.cg-orgctx-title { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.cg-orgctx-watch { margin-top: 2px; }
.cg-orgtable-bar {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--line);
  font-size: 12px; color: var(--fg-2);
}
.cg-orgtable-bar-label { display: inline-flex; align-items: baseline; gap: 8px; }
.cg-orgtable-bar-n { font-size: 11px; color: var(--brand-text); }
.cg-orgtable-bar-link {
  margin-left: auto; display: inline-flex; align-items: center; gap: 4px;
  font-size: 12px; color: var(--fg-2); text-decoration: none;
  transition: color .15s var(--ease);
}
.cg-orgtable-bar-link:hover { color: var(--brand-text); }

/* ------------------------------------------------------------
   Account events timeline (PROD-47). A drawn rail with a node per event;
   entries stagger in beside it. The rail draws top-to-bottom via a scaleY
   transform, so no JS measures anything.
   ------------------------------------------------------------ */
.cg-evt { position: relative; margin-top: 12px; padding-left: 26px; }
.cg-evt::before {
  content: ""; position: absolute; left: 5px; top: 6px; bottom: 6px; width: 1px;
  background: var(--line-strong);
  transform: scaleY(0); transform-origin: top;
  animation: cg-evt-rail 1s cubic-bezier(.2,.8,.2,1) .15s forwards;
}
@keyframes cg-evt-rail { to { transform: scaleY(1); } }
.cg-evt-item { position: relative; padding: 0 0 16px; }
.cg-evt-item:last-child { padding-bottom: 0; }
.cg-evt-item::before {
  content: ""; position: absolute; left: -25px; top: 5px;
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--bg); border: 1.5px solid var(--brand);
}
.cg-evt-item.filing::before { border-color: var(--line-strong); }
.cg-evt-date { font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-4); letter-spacing: .04em; }
.cg-evt-title { font-size: 13.5px; color: var(--fg); margin-top: 2px; }
.cg-evt-title .cg-pill { margin-left: 8px; vertical-align: 1px; }
.cg-evt-sum { font-size: 12px; color: var(--fg-3); margin-top: 3px; line-height: 1.5; }
.cg-evt-where { font-size: 11px; color: var(--fg-4); margin-top: 3px; }
@media (prefers-reduced-motion: reduce) {
  .cg-evt::before { animation: none; transform: scaleY(1); }
}


/* ------------------------------------------------------------
   Patient mix (PROD-21). A derived reading of a public utilisation
   summary — so the LIMITS lead the card, in ink rather than grey, and the
   bars draw in from zero. A withheld figure says so in words; it never
   renders as a number.
   ------------------------------------------------------------ */
.cg-pmx-limits {
  list-style: none; margin: 0 0 14px; padding: 10px 12px;
  border-left: 2px solid color-mix(in oklab, var(--brand) 55%, var(--line));
  background: color-mix(in oklab, var(--brand) 5%, transparent);
  display: grid; gap: 4px;
}
.cg-pmx-limits li {
  font-size: 12px; color: var(--fg-2); line-height: 1.45;
  animation: cg-slot-in .3s var(--ease) both;
  animation-delay: calc(var(--i, 0) * 50ms);
}
.cg-pmx-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; }
@media (max-width: 760px) { .cg-pmx-grid { grid-template-columns: 1fr; } }
.cg-pmx-headline { display: flex; align-items: baseline; gap: 8px; margin-bottom: 10px; }
.cg-pmx-headline-label { font-family: var(--font-mono); font-size: 11px; color: var(--fg-3); }
.cg-pmx-sub {
  font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--fg-4); margin: 12px 0 6px;
}
.cg-pmx-row {
  display: grid; grid-template-columns: minmax(0, 1fr) 90px 34px;
  align-items: center; gap: 8px; font-size: 12.5px; color: var(--fg-2);
  padding: 2px 0;
}
.cg-pmx-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cg-pmx-track { height: 6px; background: var(--bg-3); border-radius: var(--r-pill); overflow: hidden; }
.cg-pmx-fill {
  display: block; height: 100%; width: var(--w, 0%);
  background: color-mix(in oklab, var(--brand) 70%, var(--fg-4));
  animation: cg-pmx-draw .6s var(--ease) both;
  animation-delay: calc(var(--i, 0) * 60ms);
}
@keyframes cg-pmx-draw { from { width: 0; } to { width: var(--w, 0%); } }
.cg-pmx-val { font-size: 11px; color: var(--fg-3); text-align: right; }
.cg-pmx-note { font-size: 11px; color: var(--fg-3); margin-top: 8px; }
.cg-pmx-areas, .cg-pmx-rx { margin-top: 16px; }
.cg-pmx-area-n { font-size: 10.5px; color: var(--fg-4); }
.cg-pmx-withheld { color: var(--fg-4); font-style: italic; }
@media (prefers-reduced-motion: reduce) {
  .cg-pmx-limits li { animation: none; }
  .cg-pmx-fill { animation: none; width: var(--w, 0%); }
}

/* ------------------------------------------------------------
   Formulary decision-makers (PROD-46). Committees are grouped by SCOPE and
   the scope label is always visible — a state program's committee and the
   account's own are never presented as one list. Members reveal in a short
   stagger; reduced motion drops it.
   ------------------------------------------------------------ */
.cg-fc-group { margin-top: 14px; }
.cg-fc-group:first-of-type { margin-top: 8px; }
.cg-fc-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.cg-fc-name { font-family: var(--font-serif); font-size: 16px; color: var(--fg); }
.cg-fc-meta { font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-4); }
.cg-fc-members {
  list-style: none; margin: 8px 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 4px 16px;
}
.cg-fc-members li {
  padding: 5px 0; border-bottom: 1px dashed var(--line);
  animation: cg-acct-rise .45s var(--ease) both;
  animation-delay: calc(var(--i, 0) * 25ms);
}
.cg-fc-member-name { font-size: 12.5px; color: var(--fg); }
.cg-fc-member-sub { font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-4); margin-top: 1px; }
@media (prefers-reduced-motion: reduce) { .cg-fc-members li { animation: none; } }

/* Career highlights (PROD-22): chips over a drawn chart over dated rows.
   The year column is the spine; rows stagger in under it. */
.cg-ct-chips { margin-bottom: 12px; }
.cg-ct-chips .cg-slot { cursor: pointer; font: inherit; font-size: 12.5px; }
.cg-ct-rows { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 2px; }
.cg-ct-row {
  display: grid; grid-template-columns: 52px minmax(0, 1fr);
  gap: 12px; align-items: baseline;
  padding: 7px 0; border-top: 1px solid var(--line);
  animation: cg-slot-in .3s var(--ease) both;
  animation-delay: calc(var(--i, 0) * 35ms);
}
.cg-ct-row:first-child { border-top: 0; }
.cg-ct-year { font-size: 11.5px; color: var(--fg-4); }
.cg-ct-body { min-width: 0; display: grid; gap: 2px; }
.cg-ct-verb { font-size: 13px; color: var(--fg); }
.cg-ct-detail {
  font-size: 12px; color: var(--fg-3); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
@media (prefers-reduced-motion: reduce) { .cg-ct-row { animation: none; } }

/* Generated summary (PROD-23): the first card on a profile. Serif, generous
   measure, and a quiet control row — the sentences are the point, the
   controls are not. */
.cg-sum-card { margin-bottom: 14px; }
.cg-sum-meta { display: inline-flex; align-items: center; gap: 6px; }
.cg-sum-text {
  font-family: var(--font-serif);
  font-size: 17px; line-height: 1.5; color: var(--fg);
  margin: 10px 0 0; max-width: 74ch;
  animation: cg-slot-in .4s var(--ease) both;
}
.cg-sum-actions { display: flex; align-items: center; gap: 8px; margin-top: 14px; flex-wrap: wrap; }
.cg-sum-actions .cg-btn.is-on { border-color: var(--brand); color: var(--brand-text, var(--brand)); }
.cg-sum-ack { font-size: 11px; color: var(--fg-3); }
@media (prefers-reduced-motion: reduce) { .cg-sum-text { animation: none; } }
/* ============================================================
   Hiring & demand (PROD-165)
   Layout only — every colour, radius and font is a token, and the
   card, chips, meters and trend marks are DS components. The block
   sits inside .cg-acct-grid, so it inherits the account page's
   stagger (.cg-acct-in) and its reduced-motion reset below.
   ============================================================ */
.cg-hire-stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
  margin-top: 12px;
}
@media (max-width: 760px) { .cg-hire-stats { grid-template-columns: repeat(2, 1fr); } }
.cg-hire-stats .cg-stat-num { font-size: 30px; }
.cg-hire-none { font-size: 12px; color: var(--fg-4); }

.cg-hire-pace {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 16px;
}

/* Openings by month. Bars grow from the baseline as the series arrives —
   the height is set from JS at 0 for one frame, so this transition is the
   draw-in; `--k` staggers it left to right. */
.cg-hire-spark { margin-top: 16px; }
.cg-hire-spark-bars {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 72px;
  padding-bottom: 1px;
  border-bottom: 1px solid var(--line);
}
.cg-hire-bar {
  flex: 1 1 0;
  min-width: 3px;
  height: var(--h, 0%);
  min-height: 2px;
  background: color-mix(in oklab, var(--brand) 55%, var(--bg-2));
  border-radius: var(--r-xs) var(--r-xs) 0 0;
  transition: height .9s cubic-bezier(.2,.8,.2,1), background .15s var(--ease);
  transition-delay: calc(var(--k, 0) * 18ms), 0ms;
}
.cg-hire-bar:hover { background: var(--brand); }
.cg-hire-spark-axis {
  display: flex;
  justify-content: space-between;
  font-size: 10.5px;
  color: var(--fg-4);
  margin-top: 6px;
}

.cg-hire-block { margin-top: 18px; }
.cg-hire-terms { margin-top: 18px; }
.cg-hire-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.cg-hire-chips .cg-pill { display: inline-flex; align-items: center; gap: 6px; }
.cg-hire-chip-n { font-size: 10.5px; color: var(--fg-4); }
.cg-hire-note { font-size: 11px; color: var(--fg-4); line-height: 1.5; }

@media (prefers-reduced-motion: reduce) {
  /* The bars are already at their real height on the first paint (useDrawn
     returns the target immediately under reduced motion); dropping the
     transition is what stops them animating at all. */
  .cg-hire-bar { transition: none; }
}

/* ------------------------------------------------------------
   Cross-graph Facilities / People lists in the top-level drawer
   (2026-09). Layout only — every colour is a token, every control
   is the DS's. The people row's influence cell: the number + reach
   pill, over a compact bar of the score's components (segments
   proportional to contribution, ink at stepping opacities so the
   split reads without a legend — the tooltip carries the labels).
   ------------------------------------------------------------ */
.cg-maplist-sub { font-size: 10.5px; color: var(--fg-4); margin-top: 2px; }
.cg-maplist-sub .cg-pill { vertical-align: 1px; }
.cg-maplist-link {
  background: none; border: 0; padding: 0; margin: 0;
  font: inherit; color: var(--fg-3); cursor: pointer;
  text-decoration: underline dotted;
  text-underline-offset: 2px;
}
.cg-maplist-link:hover { color: var(--fg); }
.cg-influence { display: inline-flex; align-items: center; gap: 8px; }
.cg-influence-num { font-size: 13px; color: var(--fg); }
.cg-influence-bar {
  display: flex; gap: 1px;
  width: 104px; height: 4px; margin-top: 6px;
  border-radius: var(--r-xs); overflow: hidden;
  background: var(--line);
}
.cg-influence-seg {
  display: block; height: 100%;
  background: color-mix(in oklab, var(--fg) calc(92% - var(--i, 0) * 10%), transparent);
}
/* Rows dim while the next page of a refined filter is in flight — the last
   good rows stay legible, and the loading state is visible without a
   spinner over them. */
.cg-dash-list .cg-table[data-loading="true"] tbody { opacity: .6; transition: opacity .18s var(--ease); }
.cg-dash-list .cg-table tr.is-picked td { background: var(--bg-2); }
.cg-maplist-selbar {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 10px 18px;
  border-bottom: 1px solid var(--line);
}
.cg-maplist-pickall {
  display: inline-flex; align-items: center; gap: 8px;
  cursor: pointer; font-size: 10.5px; color: var(--fg-3);
}
.cg-maplist-selcount { font-size: 11px; color: var(--fg-2); }
.cg-maplist-selactions { margin-left: auto; display: inline-flex; gap: 8px; }
.cg-maplist-selactions .cg-btn { gap: 6px; }
/* The People tab's tab-row actions sit beside the export slot. */
.cg-dash-tabbar-end .cg-x-addlist, .cg-dash-tabbar-end .cg-x-export { display: inline-flex; }

/* The filters panel's People group (2026-09): a sub-label row for the
   area control's "Browse all", the three floors side by side, and the
   topic-browser modal mounted at the bar root (the root is pointer-
   events: none so map gestures pass through; the modal takes them back). */
.cg-filtersbar-influence { gap: 8px; }
.cg-filtersbar-influence-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  margin-top: 2px;
}
/* The folded-in # of people range: its own block at the foot of the People
   section, set off by a hairline because it narrows organizations and
   facilities while everything above it narrows people. */
.cg-filtersbar-roster {
  display: flex; flex-direction: column; gap: 8px;
  margin-top: 6px; padding-top: 12px;
  border-top: 1px solid var(--line-2);
}
.cg-filtersbar-sublabel {
  font-size: 10px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--fg-4);
}
.cg-filtersbar-floors { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.cg-filtersbar-floors .cg-x-floor { grid-template-columns: auto minmax(0, 1fr); }
@media (max-width: 640px) {
  .cg-filtersbar-floors { grid-template-columns: 1fr; }
}
.cg-filtersbar-modal { pointer-events: auto; }

/* ============================================================
   The account's discipline scope, said out loud (2026-09-11)
   ------------------------------------------------------------
   One line on BOTH Explore tabs — under the drawer's three counts on the
   Map, under the page head on Trends. Structure carried by a hairline, not
   by a fill: this is a statement of fact about the screen, not a warning
   and not a call to action, and a coloured banner would read as either.
   ============================================================ */
.cg-scope-note {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  padding: 9px 0 11px;
  border-bottom: 1px solid var(--line-2);
  font-size: 12px; line-height: 1.55; color: var(--fg-3);
}
.cg-scope-note-body { flex: 1 1 320px; min-width: 0; }
.cg-scope-note strong { color: var(--fg-1); font-weight: 600; }
.cg-scope-note-aside { color: var(--fg-4); }
.cg-scope-note .cg-btn { flex: 0 0 auto; }

/* A `services=` slug the account cannot reach — a hand-edited URL or a
   bookmark from before its scope changed. Named under the control, because
   the server's honest answer (an empty map, an empty drawer) is otherwise
   indistinguishable from a quiet market. */
.cg-filtersbar-outofscope {
  margin-top: 6px; font-size: 11px; line-height: 1.5; color: var(--fg-4);
}
