/* Beta Briefing dashboard — slice B token surface + layout shell.
 *
 * Tokens lifted from `plans/mockups/design_handoff_beta_briefing/README.md`.
 * Two themes (cream / graphite), four accents (clay / indigo / forest / plum),
 * two densities (regular / compact), four card sizes (hero / major / standard
 * / compact). All theme/accent/density swaps are pure CSS-variable changes
 * driven by Alpine $watch on <html data-*>.
 */

/* ------------------------------------------------------------------ *
 * Tokens — Light ("Cream") default                                    *
 * ------------------------------------------------------------------ */
:root {
  --bg-paper:    #faf8f4;
  --paper-soft:  #f2efe8;
  --ink:         #1a1814;
  --ink-80:      rgba(26, 24, 20, 0.82);
  --ink-65:      rgba(26, 24, 20, 0.62);
  --ink-50:      rgba(26, 24, 20, 0.48);
  --ink-40:      rgba(26, 24, 20, 0.36);
  --ink-30:      rgba(26, 24, 20, 0.24);
  --ink-20:      rgba(26, 24, 20, 0.16);
  --rule:        rgba(26, 24, 20, 0.10);
  --rule-strong: rgba(26, 24, 20, 0.18);

  --accent:      oklch(0.52 0.13 265);
  --accent-ok:   oklch(0.62 0.10 150);

  --font-serif:  "Spectral", Georgia, serif;
  --font-body:   "Geist", ui-sans-serif, system-ui, sans-serif;
  --font-mono:   "Geist Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  /* Spacing scale (4-based). */
  --pad-card: 14px;
  --gap-grid: 12px;
  --pad-container: 24px;

  /* Card size baseline (regular density). */
  --card-min-hero:     200px;
  --card-min-major:    160px;
  --card-min-standard: 130px;
  --card-min-compact:   90px;
  --head-hero:     26px;
  --head-major:    17px;
  --head-standard: 14.5px;
  --head-compact:  14.5px;
}

/* Tone overrides — Graphite (dark) */
[data-tone="graphite"] {
  --bg-paper:    #18161a;
  --paper-soft:  #221f25;
  --ink:         #f3efe7;
  --ink-80:      rgba(243, 239, 231, 0.82);
  --ink-65:      rgba(243, 239, 231, 0.62);
  --ink-50:      rgba(243, 239, 231, 0.50);
  --ink-40:      rgba(243, 239, 231, 0.38);
  --ink-30:      rgba(243, 239, 231, 0.26);
  --ink-20:      rgba(243, 239, 231, 0.18);
  --rule:        rgba(243, 239, 231, 0.12);
  --rule-strong: rgba(243, 239, 231, 0.22);
  --accent:      oklch(0.72 0.13 265);
}

/* Accent overrides — Clay / Forest / Plum (Indigo is :root default) */
[data-accent="clay"]   { --accent: oklch(0.55 0.13 35); }
[data-accent="forest"] { --accent: oklch(0.50 0.10 150); }
[data-accent="plum"]   { --accent: oklch(0.48 0.13 320); }

[data-tone="graphite"][data-accent="clay"]   { --accent: oklch(0.72 0.13 35); }
[data-tone="graphite"][data-accent="forest"] { --accent: oklch(0.72 0.10 150); }
[data-tone="graphite"][data-accent="plum"]   { --accent: oklch(0.72 0.13 320); }

/* Compact density: tighter padding, lower line-height, smaller card heads. */
[data-density="compact"] {
  --pad-card: 10px;
  --gap-grid: 8px;
  --pad-container: 18px;
  --card-min-hero:     130px;
  --card-min-major:    100px;
  --card-min-standard:  84px;
  --card-min-compact:   64px;
  --head-hero:     22px;
  --head-major:    15px;
  --head-standard: 13px;
  --head-compact:  13px;
}

/* ------------------------------------------------------------------ *
 * Reset                                                               *
 * ------------------------------------------------------------------ */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--bg-paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  min-height: 100vh;
}

/* Pin body to the viewport on dashboard pages — inner panes (left-rail,
   center-pane) own their own scroll on desktop. Defense-in-depth against
   any rogue 1px absolutely-positioned descendant (e.g. SR-only labels)
   extending documentElement.scrollHeight past the viewport. Scoped via
   :has() so non-dashboard pages (portal, error pages, etc.) still scroll
   normally. Desktop-only: the (max-width: 768px) block below flips
   both .dashboard and .center-pane to overflow:visible (separate rules,
   not a combinator selector) because mobile abandons
   the pane-scroll model and lets the document body scroll the whole
   page — applying overflow:hidden at every viewport would orphan mobile
   content past the fold (Slice C followup regression). Use the exact
   logical complement of `(max-width: 768px)` so fractional widths
   (768 < w < 769, possible under browser zoom) don't fall through a
   gap between (min-width: 769px) and (max-width: 768px). */
@media not all and (max-width: 768px) {
  body:has(.dashboard) {
    min-height: 0;
    overflow: hidden;
  }
}

a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; cursor: pointer; }

/* ------------------------------------------------------------------ *
 * Impersonation banner (admin viewing-as) — top_bar chrome           *
 * ------------------------------------------------------------------ *
 * Lives in the shared top_bar.html.j2 (rendered on every full page),
 * so its CSS belongs in dashboard.css — the one stylesheet every page
 * loads — NOT in dashboard_forms.css (settings/smart-edit/public only).
 * It renders ABOVE the sticky 52px .top-bar; the desktop overflow rule
 * is alongside the .dashboard height in the handoff layer below. */
.impersonation-banner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 7px 16px;
  background: color-mix(in oklch, var(--accent) 14%, var(--bg-paper));
  border-bottom: 0.5px solid color-mix(in oklch, var(--accent) 35%, transparent);
  font-size: 12.5px;
  color: var(--ink-80);
}
.impersonation-banner__text { font-family: var(--font-body); }
.impersonation-banner__who { font-weight: 600; color: var(--ink); }
.impersonation-banner__form { display: inline; margin: 0; }
.impersonation-banner__action {
  font-family: var(--font-mono);
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--accent);
  background: transparent;
  border: 0.5px solid color-mix(in oklch, var(--accent) 45%, transparent);
  border-radius: 6px;
  padding: 3px 10px;
  cursor: pointer;
}
.impersonation-banner__action:hover { background: color-mix(in oklch, var(--accent) 16%, transparent); }
.impersonation-banner__action:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ------------------------------------------------------------------ *
 * Top bar                                                             *
 * ------------------------------------------------------------------ */
.top-bar {
  display: flex;
  align-items: center;
  height: 52px;
  padding: 0 var(--pad-container);
  border-bottom: 0.5px solid var(--rule);
  gap: 16px;
  background: var(--bg-paper);
  backdrop-filter: blur(8px);
  position: sticky;
  top: 0;
  z-index: 50;
}
/* Anchor-scroll reservation for the two scroll contexts the dashboard uses:
    - Mobile (<=768px): body scrolls under the sticky global .top-bar (52px).
      ``html { scroll-padding-top }`` applies because html/body is the scroll
      container in that mode.
    - Desktop (>768px): body is overflow:hidden; .center-pane owns its own
      scroll AND contains its own sticky .page-header (~60px tall). Anchor
      navigation inside .center-pane (e.g. rail link /topics#topic-X) must
      reserve the in-pane header's height, NOT the global top-bar's — the
      top-bar lives above the scroll container, not inside it. Hence the
      separate scroll-padding-top on .center-pane below.
   If either header height changes, bump the matching reservation. */
html {
  scroll-padding-top: 64px;
}
.top-bar__left, .top-bar__right {
  display: flex;
  align-items: center;
  gap: 10px;
}
.brand {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 500;
  font-size: 17px;
  letter-spacing: -0.01em;
}
.status-dot {
  width: 6px; height: 6px;
  border-radius: 999px;
  background: var(--accent-ok);
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--accent-ok) 18%, transparent);
}
.status-line {
  font-family: var(--font-mono);
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-50);
}
.search-stub {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 30px;
  padding: 0 8px;
  background: var(--paper-soft);
  border: 0;
  border-radius: 7px;
  color: var(--ink-50);
  font-size: 12.5px;
  min-width: 320px;
  max-width: 480px;
}
.search-stub__placeholder { flex: 1; text-align: left; }
.search-stub__chip {
  font-family: var(--font-mono);
  font-size: 10px;
  background: var(--bg-paper);
  border: 0.5px solid var(--rule);
  border-radius: 4px;
  padding: 1px 5px;
  color: var(--ink-65);
}
.seg {
  display: inline-flex;
  background: var(--paper-soft);
  border: 0.5px solid var(--rule);
  border-radius: 7px;
  padding: 2px;
  gap: 2px;
}
.seg__btn {
  background: transparent;
  border: 0;
  height: 22px;
  min-width: 26px;
  border-radius: 5px;
  color: var(--ink-65);
  font-size: 12px;
}
.seg__btn[aria-pressed="true"], .seg__btn--active {
  background: var(--bg-paper);
  color: var(--ink);
  box-shadow: 0 0.5px 2px rgba(0, 0, 0, 0.12);
}
.avatar {
  width: 28px; height: 28px;
  border-radius: 999px;
  background: var(--ink);
  color: var(--bg-paper);
  font-family: var(--font-mono);
  font-size: 10.5px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
}
.avatar--lg { width: 40px; height: 40px; font-size: 13px; }

/* ------------------------------------------------------------------ *
 * Layout                                                              *
 * ------------------------------------------------------------------ */
.dashboard {
  display: grid;
  grid-template-columns: 220px 1fr;
  min-height: calc(100vh - 52px);
}
.left-rail {
  border-right: 0.5px solid var(--rule);
  padding: 18px 12px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.rail-section__title {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-40);
  margin: 0 8px 6px;
}
.rail-list { list-style: none; padding: 0; margin: 0; }
.rail-link, .rail-topic {
  display: flex;
  align-items: center;
  height: 28px;
  padding: 0 8px;
  font-size: 13px;
  color: var(--ink-80);
  border-radius: 5px;
}
.rail-link--active { background: var(--paper-soft); color: var(--ink); }
.rail-topic { display: grid; grid-template-columns: 1fr auto; gap: 6px; }
.rail-topic__label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rail-topic__spark {
  width: 44px; height: 14px;
  background: linear-gradient(to right, var(--accent) 0%, var(--accent) 100%);
  opacity: 0.18;
  border-radius: 2px;
}
.center-pane {
  padding: 24px var(--pad-container) 64px;
  max-width: 1280px;
  width: 100%;
}
.page-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 24px;
}
.page-title {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 500;
  font-size: 22px;
  margin: 0;
}
.greeting {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 300;
  font-size: 28px;
  line-height: 1.15;
  letter-spacing: -0.015em;
  color: var(--ink);
  margin: 0;
}
.view-switcher {
  display: inline-flex;
  background: var(--paper-soft);
  border: 0.5px solid var(--rule);
  border-radius: 8px;
  padding: 2px;
  gap: 2px;
}
.view-switcher__btn {
  padding: 6px 12px;
  border-radius: 6px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-65);
}
.view-switcher__btn--active {
  background: var(--bg-paper);
  color: var(--ink);
  box-shadow: 0 0.5px 2px rgba(0, 0, 0, 0.12);
}

/* Right-side controls cluster in the page-header (date_selector +
 * view-switcher). Keeps the two pills as a matched horizontal pair. */
.view-controls {
  display: inline-flex;
  align-items: center;
  gap: 0;
  flex-wrap: nowrap;
}

/* Detail control — docked in the Daily Briefing page-header next to the date
 * selector. Shares the .view-switcher chrome vocabulary (paper-soft track,
 * mono uppercase labels, neutral paper-pop active) so it reads as native
 * dashboard chrome rather than the foreign floating pill it replaced. The depth
 * behavior itself stays driven by html[data-briefing-density] in
 * briefing_body.css. Only the Daily Briefing view mounts it. */
.briefing-density-control--docked {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-right: 10px;
}
.briefing-density-control--docked[hidden] { display: none; }
.briefing-density-control--docked .briefing-density-heading {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-40);
}
.briefing-density-control--docked .briefing-density-options {
  display: inline-flex;
  background: var(--paper-soft);
  border: 0.5px solid var(--rule);
  border-radius: 8px;
  padding: 2px;
  gap: 2px;
}
.briefing-density-control--docked .briefing-density-option {
  background: transparent;
  border: 0;
  padding: 6px 12px;
  border-radius: 6px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-65);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
.briefing-density-control--docked .briefing-density-option:hover {
  color: var(--ink);
}
.briefing-density-control--docked .briefing-density-option:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.briefing-density-control--docked .briefing-density-option[aria-pressed="true"] {
  background: var(--bg-paper);
  color: var(--ink);
  box-shadow: 0 0.5px 2px rgba(0, 0, 0, 0.12);
}
/* Bar-stack glyph — Headlines = 1 solid bar (others ghosted), Compact = 2,
   Full = 3. Matches the public toolbar's icon; opacity (not display) holds a
   fixed icon height across modes. */
.briefing-density-control--docked .briefing-density-icon {
  display: inline-flex;
  flex-direction: column;
  /* Integer gap (3px, not 2.5px) — see the public toolbar glyph note in
     static/style.css: a fractional gap snaps the middle bar to a different
     device-pixel fraction and it antialiases heavier/lighter than its
     neighbours (the "Full" glyph's bottom bar reading thicker). 3px keeps all
     three bars on one fraction → uniform weight. */
  gap: 3px;
  width: 13px;
}
.briefing-density-control--docked .briefing-density-icon span {
  display: block;
  height: 2px;
  border-radius: 1px;
  background: currentColor;
}
.briefing-density-control--docked .briefing-density-icon--headline span:nth-child(2),
.briefing-density-control--docked .briefing-density-icon--headline span:nth-child(3),
.briefing-density-control--docked .briefing-density-icon--compact span:nth-child(3) {
  opacity: 0.2;
}

/* ------------------------------------------------------------------ *
 * Date selector — 7-day temporal navigator (Sotto Voce variant)       *
 * Extends the existing .seg / .view-switcher chrome vocabulary so it  *
 * disappears into the top-bar rather than introducing a new control   *
 * type. Day-of-week letters (M/T/W/T/F/S/S) anchored to today's PT    *
 * weekday; today's letter is accent-colored; a sparse 2px dot         *
 * marks only days with no published briefing.                         *
 * ------------------------------------------------------------------ */
.date-selector {
  display: inline-flex;
  align-items: stretch;
  background: var(--paper-soft);
  border: 0.5px solid var(--rule);
  border-radius: 8px;
  padding: 2px;
  gap: 0;
  user-select: none;
  touch-action: none;
  /* sit next to view-switcher in the page-header */
  margin-right: 8px;
}
.date-selector__cell {
  position: relative;
  display: inline-grid;
  place-items: center;
  min-width: 28px;
  height: 22px;
  padding: 0 6px;
  border-radius: 5px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-50);
  text-decoration: none;
  cursor: pointer;
  transition: background-color 100ms ease, color 100ms ease;
}
.date-selector__cell:hover { color: var(--ink); }
.date-selector__cell--in-range,
.date-selector__cell[data-in-range="true"] {
  background: var(--bg-paper);
  color: var(--ink);
}
.date-selector__cell--current,
.date-selector__cell[aria-current="true"],
.date-selector__cell--range-start,
.date-selector__cell--range-end {
  background: var(--bg-paper);
  color: var(--ink);
  box-shadow: 0 0.5px 2px rgba(0, 0, 0, 0.12);
}
/* Today's letter glows accent regardless of selection state.
 * Placed AFTER in-range/current rules so source-order wins for the
 * equal-specificity attribute-vs-class clash. */
.date-selector__cell[data-today="true"] {
  color: var(--accent);
}
/* Sparse "no briefing that day" indicator — 2px dot, no dot otherwise.
 * Only days WITHOUT a published run get the marker; the dashboard's
 * baseline assumption is that a briefing ran. */
.date-selector__cell[data-active="false"]::after {
  content: "";
  position: absolute;
  bottom: 1px;
  left: 50%;
  transform: translateX(-50%);
  width: 2px;
  height: 2px;
  border-radius: 999px;
  background: color-mix(in oklch, var(--ink) 24%, transparent);
}
/* Window readout caption — optional sibling, currently rendered as a
 * <span> via page-header helpers when not today-only. */
.date-selector__readout {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 12px;
  color: var(--ink-65);
  margin-right: 10px;
  white-space: nowrap;
  align-self: center;
}

/* Mobile: keep the letters visible (they're the primary content under
 * Sotto Voce) but tighten cell padding. */
@media (max-width: 720px) {
  .date-selector__cell {
    min-width: 22px;
    padding: 0 4px;
    font-size: 10px;
  }
  /* Hit-target expansion — visual stays at 22 px (Sotto Voce intent) but
   * the tappable area grows to ~28 × 26 px so fingertips don't mistap an
   * adjacent cell. Meets WCAG 2.5.8 (24 × 24 px) without altering layout. */
  .date-selector__cell::before {
    content: "";
    position: absolute;
    inset: -3px -2px;
  }
}

/* ------------------------------------------------------------------ *
 * Cards                                                               *
 * ------------------------------------------------------------------ */
.card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: var(--pad-card);
  background: var(--paper-soft);
  border: 0.5px solid var(--rule);
  border-radius: 10px;
  color: inherit;
  text-decoration: none;
  transition: border-color 120ms ease, transform 120ms ease;
}
.card:hover { border-color: var(--rule-strong); transform: translateY(-1px); }
.card--hero     { min-height: var(--card-min-hero); }
.card--major    { min-height: var(--card-min-major); }
.card--standard { min-height: var(--card-min-standard); }
.card--compact  { min-height: var(--card-min-compact); padding: calc(var(--pad-card) - 2px); }

.card--priority-critical {
  border-color: color-mix(in oklch, var(--accent) 45%, var(--rule));
  background: color-mix(in oklch, var(--accent) 6%, var(--paper-soft));
}

.card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.card__kicker {
  font-family: var(--font-mono);
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--accent);
}
.card__meta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-50);
}
.card__priority { color: var(--accent); }
.card__headline {
  font-family: var(--font-body);
  font-weight: 500;
  margin: 0;
  font-size: var(--head-standard);
  line-height: 1.4;
}
.card--hero .card__headline {
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: var(--head-hero);
  line-height: 1.18;
}
.card--major .card__headline {
  font-size: var(--head-major);
  line-height: 1.3;
}
.card--compact .card__headline { font-size: var(--head-compact); }

.card__standfirst {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 15px;
  line-height: 1.55;
  margin: 0;
  color: var(--ink-80);
}
.card__why {
  border-top: 0.5px solid var(--rule);
  padding-top: 8px;
  margin-top: 4px;
}
.card__why-label {
  display: block;
  font-family: var(--font-mono);
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-40);
  margin-bottom: 4px;
}
.card__why-text {
  font-size: 12.5px;
  color: var(--ink-65);
  margin: 0;
}
.card__foot {
  margin-top: auto;
  display: flex;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ink-50);
}

/* Compact density hides the read-time-eating extras. */
[data-density="compact"] .card__standfirst,
[data-density="compact"] .card__why { display: none; }

/* Grids */
.card-grid { display: grid; gap: var(--gap-grid); }
.card-grid--majors    { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.card-grid--standards { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.card-grid--compacts  { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }

.today-hero { margin-bottom: 24px; }
.today-majors { margin-bottom: 24px; }

.feed-band { margin-bottom: 32px; }
.band-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
}
.band-header__label {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-65);
  margin: 0;
}
.band-header__count {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ink-40);
}
.band-header__dot {
  width: 6px; height: 6px;
  border-radius: 999px;
  background: var(--ink-30);
}
.band-header__dot--critical   { background: var(--accent); }
.band-header__dot--notable    { background: var(--ink-40); }
.band-header__dot--background { background: var(--ink-20); }

.spillover {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px;
  background: var(--paper-soft);
  border: 0.5px solid var(--rule);
  border-radius: 10px;
}
.spillover__label {
  font-family: var(--font-serif);
  font-style: italic;
  color: var(--ink-65);
}
.spillover__cta {
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

/* ------------------------------------------------------------------ *
 * Topics view                                                         *
 * ------------------------------------------------------------------ */
.topics-stack {
  display: flex;
  flex-direction: column;
  gap: 32px;
}
.topic-lane__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 12px;
}
.topic-lane__title {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 18px;
  margin: 0;
}
.topic-lane__meta {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-50);
}
/* Topic lanes stack their cards into a responsive grid so the whole lane is
   visible at once — no left/right scrolling. 3-up on desktop (like the Feed
   page's standard band, where a card is also 3-across), stepping to 2-up on
   tablet and 1-up on mobile. The 2-up tablet step is a deliberate divergence
   from the Feed, which collapses 3→1 with no intermediate step. */
.topic-lane__rail {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--gap-grid);
}
/* Cards render at size='standard'; the global Feed-grid rule
   `.card--standard { grid-column: span 2 }` (on a 6-column grid) would make
   them span two of three tracks here, so pin each card to a single track.
   `min-width: 0` overrides the grid-item default (`min-width: auto`) so a card
   can shrink below its content's min-content width — without it a long
   unbreakable headline token could blow a track out past the lane. */
.topic-lane__rail > .card {
  grid-column: auto;
  min-width: 0;
}
@media (max-width: 1024px) {
  .topic-lane__rail { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 768px) {
  .topic-lane__rail { grid-template-columns: 1fr; }
}

/* ------------------------------------------------------------------ *
 * Reader (slide-over desktop / bottom-sheet mobile)                   *
 * ------------------------------------------------------------------ */
.reader {
  position: fixed;
  inset: 0;
  z-index: 100;
}
.reader__scrim {
  position: absolute;
  inset: 0;
  background: color-mix(in oklch, var(--ink) 24%, transparent);
}
.reader__panel {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(720px, 92vw);
  background: var(--bg-paper);
  border-left: 0.5px solid var(--rule-strong);
  box-shadow: -20px 0 60px -20px rgba(0, 0, 0, 0.25);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transform: translateX(0);
  transition: transform 280ms ease-out;
}
.reader__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px var(--pad-container);
  border-bottom: 0.5px solid var(--rule);
}
.reader__kicker {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--accent);
}
.reader__close {
  background: transparent;
  border: 0;
  font-size: 22px;
  line-height: 1;
  color: var(--ink-65);
  width: 32px;
  height: 32px;
  border-radius: 999px;
}
.reader__close:hover { background: var(--paper-soft); color: var(--ink); }
.reader__content {
  overflow-y: auto;
  padding: 24px var(--pad-container) 64px;
  display: flex;
  flex-direction: column;
  gap: 32px;
}
.reader-chips {
  position: sticky;
  top: 0;
  display: flex;
  gap: 6px;
  padding: 8px 0;
  background: color-mix(in oklch, var(--bg-paper) 85%, transparent);
  backdrop-filter: blur(6px);
  border-bottom: 0.5px solid var(--rule);
  overflow-x: auto;
  z-index: 1;
}
.reader-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  border: 0.5px solid var(--rule);
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-65);
  white-space: nowrap;
}
.reader-chip__num { color: var(--ink-40); }
.reader-chip__dot {
  width: 5px; height: 5px;
  background: var(--accent);
  border-radius: 999px;
}
.reader-chip:hover { background: var(--paper-soft); color: var(--ink); }
.reader-hero__kicker {
  display: block;
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--accent);
  margin-bottom: 8px;
}
.reader-hero__headline {
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: 28px;
  line-height: 1.22;
  margin: 0 0 12px;
}
.reader-hero__meta {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-50);
  margin: 0;
}
.reader-tier__label {
  font-family: var(--font-mono);
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-40);
  margin: 0 0 8px;
}
.reader-tier__body { font-size: 15px; line-height: 1.6; margin: 0; }
.reader-tier__body--muted { color: var(--ink-50); }
.reader-tier--why {
  border-left: 2px solid var(--accent);
  padding-left: 12px;
}
.reader-tier--full .reader-tier__body {
  font-family: var(--font-serif);
  font-size: 16px;
  line-height: 1.65;
}
.citation {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--accent);
  margin: 0 1px;
}
.reader-sources {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 8px;
  list-style: none;
  padding: 0;
  margin: 0;
}
.reader-source {
  display: flex;
  gap: 8px;
  padding: 10px 12px;
  background: var(--paper-soft);
  border-radius: 8px;
}
.reader-source__num {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ink-40);
}
.reader-source__link { color: var(--ink); flex: 1; font-size: 13px; }
.reader-ask-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 12px 0;
}
.ask-chip {
  background: var(--paper-soft);
  border: 0.5px solid var(--rule);
  border-radius: 999px;
  padding: 6px 12px;
  font-size: 12.5px;
  color: var(--ink-65);
}
.reader-ask-composer {
  display: flex;
  background: var(--paper-soft);
  border-radius: 14px;
  padding: 6px;
  align-items: center;
  gap: 6px;
}
.reader-ask-input {
  flex: 1;
  background: transparent;
  border: 0;
  outline: none;
  padding: 8px 12px;
  font-size: 14px;
  color: var(--ink-65);
}
.reader-ask-send {
  background: var(--ink);
  color: var(--bg-paper);
  border: 0;
  border-radius: 999px;
  width: 32px;
  height: 32px;
}

.sheet-handle {
  display: none;
  width: 36px;
  height: 5px;
  background: var(--ink-30);
  border-radius: 999px;
  margin: 10px auto 0;
}

.empty-state {
  padding: 48px 24px;
  text-align: center;
  color: var(--ink-50);
}
.empty-state__title {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 22px;
  color: var(--ink-65);
  margin: 0 0 8px;
}
.empty-state__body { margin: 0; font-size: 14px; }

/* Inline view-level notice (e.g. Daily Briefing's "picked day had no edition,
   showing most recent" fallback) — quiet, above the content it explains. */
.view-notice {
  margin: 0 auto 16px;
  /* min() keeps a 16px gutter when the pane is narrower than the column —
     unlike .briefing-page this is a bordered box, so flush-to-rail shows. */
  max-width: min(720px, calc(100% - 32px));
  padding: 8px 14px;
  font-size: 13px;
  color: var(--ink-65);
  background: var(--paper-soft);
  border: 0.5px solid var(--rule);
  border-radius: 8px;
}

/* ------------------------------------------------------------------ *
 * Mobile — single-column, bottom-sheet Reader                         *
 * ------------------------------------------------------------------ */
@media (max-width: 768px) {
  /* Drawer geometry anchor — mobile top-bar uses padding 56px 18px 8px
     and contains the 44px hamburger button in the flex row, so the
     effective rendered height is 108px (measured via getBoundingClientRect
     at 375x667). Pre-hamburger this was ~96px (32px avatar). Both
     .left-rail and .rail-scrim anchor below the top-bar via
     var(--mobile-topbar-height); under-counting the var leaves the drawer
     top edge above the top-bar bottom (12px visual overlap). Update here
     if the top-bar resizes again. */
  :root { --mobile-topbar-height: 108px; }
  .dashboard { grid-template-columns: 1fr; }
  /* Left rail becomes a slide-in drawer on mobile. railOpen on
     dashboardPrefs() drives .is-open which triggers the transform. */
  .left-rail {
    display: flex;
    flex-direction: column;
    position: fixed;
    top: var(--mobile-topbar-height, 108px);
    bottom: 0;
    left: 0;
    width: min(280px, 86vw);
    z-index: 105;
    transform: translateX(-100%);
    /* Hide closed drawer from focus + AT. visibility=hidden removes
       rail links from tab order and screen-reader output but still
       lets the slide-out transform animation play (visibility flips
       after the transform's 280ms via delayed transition). Without
       this, keyboard / SR users land on offscreen rail-links when
       railOpen=false. pointer-events: none flips IMMEDIATELY so a
       fast tap during the 280ms slide-out can't land on a rail-link
       while the control state already says closed. */
    visibility: hidden;
    pointer-events: none;
    transition: transform 280ms cubic-bezier(.2, .7, .2, 1),
                visibility 0s linear 280ms;
    overflow-y: auto;
    background: var(--bg-paper);
    border-right: 0.5px solid var(--rule);
  }
  .left-rail.is-open {
    transform: translateX(0);
    visibility: visible;
    pointer-events: auto;
    /* On open, visibility flips immediately so focus-on-first-link
       in openRail() actually lands on a visible target. */
    transition: transform 280ms cubic-bezier(.2, .7, .2, 1),
                visibility 0s linear 0s;
  }
  /* NOTE: .rail-scrim and .hamburger visibility overrides live in the
     SECOND mobile media query (~line 1880 in the handoff layer), AFTER
     the base `display: none` rules at lines 1003/1022. Equal-specificity
     base rules later in source order would otherwise win on mobile,
     leaving hamburger and scrim invisible. See post-execution review. */
  .center-pane { padding: 16px 18px 64px; }
  .reader__panel {
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    height: 78%;
    width: 100%;
    border-left: 0;
    border-top-left-radius: 24px;
    border-top-right-radius: 24px;
    box-shadow: 0 -20px 50px -10px rgba(0, 0, 0, 0.30);
    transform: translateY(0);
    transition: transform 360ms cubic-bezier(.2, .7, .2, 1);
  }
  .sheet-handle { display: block; }
  .card-grid--majors,
  .card-grid--standards,
  .card-grid--compacts { grid-template-columns: 1fr; }
}

/* ------------------------------------------------------------------ *
 * Handoff fidelity layer                                              *
 * ------------------------------------------------------------------ */
body {
  text-rendering: optimizeLegibility;
}

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--ink-20);
  border: 2px solid transparent;
  border-radius: 999px;
  background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover {
  background: var(--ink-30);
  background-clip: content-box;
}

.top-bar {
  padding: 0 20px;
  gap: 20px;
}
.top-bar__left { gap: 8px; }
/* __right docks to the far edge. The old flex:1 `.top-bar__center` spacer that
   used to push it there was removed along with the search box, so margin-left:
   auto now carries the dock (parent .top-bar is display:flex). */
.top-bar__right { gap: 8px; margin-left: auto; }
/* Hamburger button — mobile-only. display: none on desktop, switched
   to inline-flex inside @media (max-width: 768px). Tap target 44x44
   per WCAG 2.5.5 / iOS HIG. Flex alignment is a no-op while display
   is none, so the alignment rules live in the mobile block. */
.hamburger {
  display: none;
  width: 44px;
  height: 44px;
  margin-left: -8px;
  padding: 0;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--ink-80);
  cursor: pointer;
}
.hamburger:hover { color: var(--ink); }
.hamburger:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
/* Rail scrim — mobile-only. display: none on desktop, switched on
   in the mobile block when .is-open is applied. */
.rail-scrim {
  display: none;
}
.seg__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}

.dashboard {
  height: calc(100vh - 52px);
  min-height: 0;
  overflow: hidden;
}
/* When the admin impersonation banner is present it stacks ABOVE the sticky
   52px top-bar, so this fixed-height overflow:hidden scroll frame must also
   subtract the banner height or its bottom is clipped past the fold. Measured
   ~39px on desktop (single line); 40 gives a hair of font-metric headroom.
   Admin + impersonation only. The mobile block resets this to height:auto. */
body:has(.impersonation-banner) .dashboard { height: calc(100vh - 52px - 40px); }
.left-rail {
  overflow-y: auto;
}
.center-pane {
  max-width: none;
  overflow-y: auto;
  padding: 0;
  /* Reserve in-pane sticky .page-header height (~60px: 28px vertical
     padding + ~32px title/controls) + 20px breathing when anchor
     navigation scrolls inside this container. The global .top-bar is
     OUTSIDE this scroll context (sits above .dashboard) so its 52px
     doesn't factor in here. See the html { scroll-padding-top } note
     near the .top-bar declaration. */
  scroll-padding-top: 80px;
}
.page-header {
  position: sticky;
  top: 0;
  z-index: 10;
  align-items: center;
  margin: 0;
  padding: 14px var(--pad-container);
  border-bottom: 0.5px solid var(--rule);
  background: color-mix(in oklch, var(--bg-paper) 92%, transparent);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.page-header__title-group {
  display: flex;
  align-items: baseline;
  gap: 14px;
}
.page-title {
  line-height: 1.1;
  letter-spacing: -0.01em;
}
.page-subtitle,
.greeting__subline {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-50);
}
.center-pane > :not(.page-header) {
  margin-left: var(--pad-container);
  margin-right: var(--pad-container);
}
.center-pane > .audio-strip { margin-top: 20px; }
/* The briefing edition + its fallback notice center like the public site's
   .container (max-width: 720px + auto margins) — the generic child-inset
   rule above (0,2,0) would otherwise beat their (0,1,0) auto margins and
   pin both to the left pad. When the pane is narrower than the column the
   auto margins resolve to 0 and the side inset comes from .briefing-page's
   own ported `.container` padding (briefing_body.css), NOT pane padding —
   `.center-pane { padding: 0 }` on desktop. The ≤768px block below zeroes
   the generic 18px child margins for the briefing page for the same
   reason (16px ported padding = the public mobile inset). */
.center-pane > .briefing-page,
.center-pane > .view-notice {
  margin-left: auto;
  margin-right: auto;
}
.center-pane > .empty-state,
.center-pane > .topics-stack,
.center-pane > .feed-band,
.center-pane > .today-hero,
.center-pane > .today-majors,
.center-pane > .spillover {
  margin-top: 24px;
}
.center-pane > :last-child { margin-bottom: 60px; }

.rail-section__title {
  font-size: 9.5px;
  letter-spacing: 0.14em;
  margin-bottom: 8px;
}
.rail-link,
.rail-topic {
  border-radius: 6px;
}
.rail-topic {
  grid-template-columns: 1fr auto auto;
  gap: 8px;
  font-size: 12.5px;
}
.rail-topic__spark {
  display: inline-flex;
  align-items: flex-end;
  width: 44px;
  height: 14px;
  background: transparent;
  opacity: 1;
}
.rail-topic__new {
  min-width: 18px;
  text-align: right;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ink-50);
}
.sparkline {
  display: block;
  width: 44px;
  height: 14px;
}
.sparkline__bar {
  fill: var(--accent);
  opacity: 0.7;
  rx: 1px;
}
.sparkline__bar--empty { opacity: 0.18; }

.card-grid {
  grid-template-columns: repeat(6, minmax(0, 1fr));
}
.card-grid--majors,
.card-grid--standards,
.card-grid--compacts {
  grid-template-columns: repeat(6, minmax(0, 1fr));
}
.card--hero { grid-column: span 6; }
.card--major { grid-column: span 3; }
.card--standard,
.card--compact { grid-column: span 2; }
[data-density="compact"] .card--compact { grid-column: span 1; }

.card {
  gap: 10px;
  cursor: default;
  transition: border-color 140ms ease, background 140ms ease, transform 140ms ease;
}
.card:hover {
  background: color-mix(in oklch, var(--accent) 3%, var(--paper-soft));
}
.card__kicker {
  color: var(--ink-50);
  letter-spacing: 0.12em;
}
.card__meta {
  gap: 8px;
  letter-spacing: 0.08em;
}
.card__source-count {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 7px;
  border-radius: 999px;
  background: color-mix(in oklch, var(--accent) 15%, transparent);
  color: var(--accent);
}
.card__source-count::before {
  content: "";
  width: 5px;
  height: 5px;
  border-radius: 999px;
  background: currentColor;
}
.card__priority::before {
  content: "○ ";
}
.card--priority-critical .card__priority::before {
  content: "● ";
}
.card__headline {
  letter-spacing: 0;
  text-wrap: pretty;
}
.card--hero .card__headline {
  font-weight: 400;
  letter-spacing: 0;
}
.card__standfirst {
  color: var(--ink-65);
  text-wrap: pretty;
}
.card__why {
  margin-top: auto;
  padding-top: 10px;
}
.card__why-label { letter-spacing: 0.14em; }
.card__why-text {
  line-height: 1.5;
  text-wrap: pretty;
}
/* Clamp the body on major + standard cards to 3 rendered lines so the
   last visible line fills most of the column width and ends with an
   ellipsis. Hero stays unclamped (it has card__standfirst for the
   long-form). Compact density hides .card__why entirely via the
   line-535 rule, so this only applies in Regular. */
.card--major .card__why-text,
.card--standard .card__why-text {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.card__foot {
  align-items: center;
  justify-content: space-between;
  letter-spacing: 0.06em;
}
.card__foot-meta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.action-bar {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
}
.action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-width: 22px;
  height: 22px;
  padding: 0;
  border: 0.5px solid var(--rule);
  border-radius: 5px;
  background: var(--bg-paper);
  color: var(--ink-50);
  font-family: var(--font-mono);
  font-size: 11px;
}
.action:hover {
  border-color: var(--rule-strong);
  color: var(--ink);
}
.action:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
/* Visual feedback while hx-disabled-elt="this" holds the button during an
   in-flight POST. Without this, rapid taps look identical pre- and
   mid-flight, even though HTMX has neutralized the click. */
.action:disabled {
  opacity: 0.5;
  cursor: default;
}
/* Toggle-active state for Save / Like / (any future) action that maps to a
   persisted snapshot row. Background tint + accent border so the button
   reads as "on" without depending on glyph swap alone — important for the
   ＋ Save case where the glyph stays identical. */
.action.is-active {
  border-color: color-mix(in oklch, var(--accent) 55%, var(--rule));
  background: color-mix(in oklch, var(--accent) 14%, var(--bg-paper));
  color: var(--ink);
}
.action.is-active:hover {
  border-color: var(--accent);
  background: color-mix(in oklch, var(--accent) 20%, var(--bg-paper));
}
/* Chained .action selector bumps specificity to (0,3,0) so this wins on
   both card and reader surfaces — without it, `.reader__header .action`
   (0,2,0, defined later in source) ties on specificity and overrides
   background/color, leaving only border-color from the copied state. */
.action.action--export.is-copied {
  border-color: color-mix(in oklch, var(--accent) 60%, var(--rule));
  background: color-mix(in oklch, var(--accent) 18%, var(--bg-paper));
  color: var(--accent);
}
/* Tier-05 "Continue with AI" CTA: the shared Copy-for-AI button upsized for a
   standalone in-reader call to action. Mirrors the reader-header action
   sizing tokens (taller hit area, body font) rather than the compact 22px
   action-bar default — no new design language, just reused tokens. */
.action--export-tier {
  height: 36px;
  min-width: 0;
  padding: 0 16px;
  margin-top: 12px;
  border-radius: 8px;
  background: var(--paper-soft);
  color: var(--ink-80);
  font-family: var(--font-body);
  font-size: 13px;
}
.action--like.is-active {
  color: var(--accent);
}
.action--like.is-active .action__glyph {
  /* Filled heart already encoded via the ♥ vs ♡ glyph swap; nudge weight. */
  font-weight: 600;
}
.action--restore .action__glyph {
  font-size: 12px;
}
.card .action__label {
  /* Modern SR-only: must include top/left to anchor the absolute box at the
     containing block's origin. Without them, the 1×1 label settles at its
     natural in-flow position — which on a card footer is near viewport
     bottom — and contributes that bottom edge to documentElement.scrollHeight
     even though it's clipped to 0. With 140 cards on /feed and /topics, that
     adds up to multi-thousand-pixel page overflow (Slice C bug). */
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}
.reader__header .action {
  height: 32px;
  min-width: 0;
  padding: 0 10px;
  border-radius: 6px;
  background: var(--paper-soft);
  color: var(--ink-80);
  font-family: var(--font-body);
  font-size: 11.5px;
}
.reader__header .action--like { display: none; }
.reader__header .action__label { display: inline; }

.band-header {
  gap: 10px;
}
.band-header__label {
  letter-spacing: 0.14em;
  color: var(--ink-50);
}
.band-header__rule {
  flex: 1;
  height: 0.5px;
  background: var(--rule);
}
.today-hero,
.today-majors,
.feed-band {
  margin-bottom: 0;
}
.spillover {
  padding: 14px 18px;
}
.spillover__label {
  font-size: 16px;
  color: var(--ink);
}
.spillover__cta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  border: 0.5px solid color-mix(in oklch, var(--accent) 40%, var(--rule));
  border-radius: 8px;
  background: color-mix(in oklch, var(--accent) 8%, transparent);
}

.topic-lane {
  padding-bottom: 18px;
  border-bottom: 0.5px solid var(--rule);
}
.topic-lane__title {
  letter-spacing: 0;
}
.topic-lane__meta {
  letter-spacing: 0.1em;
}

.reader__panel {
  animation: reader-slide-in 280ms ease-out both;
}
@keyframes reader-slide-in {
  from { transform: translateX(100%); }
  to { transform: translateX(0); }
}
.reader__header {
  gap: 16px;
  padding: 14px 22px;
  background: var(--bg-paper);
  /* Kill the scrollbar that appears when .action-bar (flex-shrink: 0)
     can't compress at narrower panel widths. If verification reveals
     buttons getting clipped at min(720px, 92vw) panel widths, fall
     back to: .reader__header .action-bar { flex-shrink: 1;
     overflow-x: auto; scrollbar-width: thin; } */
  overflow: hidden;
}
.reader__kicker {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--ink-50);
  letter-spacing: 0.12em;
}
.reader__priority-dot {
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: var(--accent);
}
.reader__close {
  width: 28px;
  height: 28px;
  border-radius: 6px;
  font-size: 16px;
}
.reader__content {
  padding: 0 22px;
  gap: 0;
}
.reader-chips {
  margin: 0 -22px;
  padding: 10px 22px;
  gap: 4px;
  background: color-mix(in oklch, var(--bg-paper) 92%, transparent);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.reader-chip {
  gap: 6px;
  padding: 5px 11px;
  font-size: 10.5px;
  background: transparent;
}
.reader-chip--active {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--bg-paper);
}
.reader-chip--active .reader-chip__num {
  color: color-mix(in oklch, var(--bg-paper) 55%, transparent);
}
.reader-hero {
  padding: 24px 0 16px;
  border-bottom: 0.5px solid var(--rule);
}
.reader-hero__kicker {
  color: var(--ink-50);
  letter-spacing: 0.1em;
}
.reader-hero__headline {
  font-weight: 400;
  letter-spacing: 0;
  text-wrap: pretty;
}
.reader-hero__standfirst {
  margin: 0 0 12px;
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 300;
  font-size: 17px;
  line-height: 1.55;
  color: var(--ink-65);
  text-wrap: pretty;
}
.reader-tier {
  padding: 22px 0;
  border-bottom: 0.5px solid var(--rule);
}
.reader-tier__label {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
  font-size: 10px;
  letter-spacing: 0.16em;
  color: var(--ink-50);
}
.reader-tier__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 5px;
  background: var(--ink);
  color: var(--bg-paper);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0;
}
.reader-tier--why {
  border-left: 0;
  padding-left: 0;
}
.reader-tier--why .reader-tier__body {
  border-left: 2px solid var(--accent);
  padding-left: 16px;
  color: var(--ink-80);
}
.reader-tier--full .reader-tier__body {
  color: var(--ink-80);
  text-wrap: pretty;
}
.citation {
  vertical-align: super;
  padding: 0 1px;
}
.reader-tier--perspectives .reader-tier__body {
  border-left: 2px solid var(--accent);
  padding-left: 14px;
  color: var(--ink-80);
}
.reader-tier__held-by {
  margin: 10px 0 0;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-50);
}
.reader-sources {
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  margin-top: 14px;
}
.reader-source {
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border: 0.5px solid var(--rule);
}
.reader-source__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border: 0.5px solid var(--rule);
  border-radius: 4px;
  background: var(--bg-paper);
  color: var(--ink-65);
}
.reader-source__link {
  color: var(--ink-80);
  font-size: 12.5px;
}
.reader-source__read {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ink-40);
}
.reader-tier--ask {
  border-bottom: 0;
  padding-bottom: 14px;
}

.audio-strip {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 12px;
  border: 0.5px solid var(--rule);
  border-radius: 10px;
  background: var(--paper-soft);
}
.audio-strip__player {
  min-width: 220px;
  max-width: 480px;
  height: 32px;
  flex: 1;
}
.audio-strip__edition-link {
  flex-shrink: 0;
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.user-menu-mobile {
  position: fixed;
  inset: 0;
  z-index: 110;
  pointer-events: none;
}
.user-menu-mobile::before {
  content: "";
  position: absolute;
  inset: 0;
  background: color-mix(in oklch, var(--ink) 16%, transparent);
  pointer-events: auto;
}
.user-menu-mobile__sheet {
  position: absolute;
  top: 60px;
  right: 24px;
  width: 264px;
  max-height: calc(100vh - 80px);
  overflow-y: auto;
  padding: 6px;
  border: 0.5px solid var(--rule-strong);
  border-radius: 12px;
  box-shadow: 0 12px 40px -8px rgba(0, 0, 0, 0.25), 0 0 0 0.5px var(--rule);
  background: var(--bg-paper);
  pointer-events: auto;
}
.user-menu-mobile .sheet-handle { display: none; }
.user-menu-mobile__identity {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 10px 12px;
  border-bottom: 0.5px solid var(--rule);
  margin-bottom: 4px;
}
.user-menu-mobile__name {
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
}
.user-menu-mobile__email {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-50);
}
.user-menu-mobile__group-label {
  padding: 8px 10px 6px;
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-40);
}
.user-menu-mobile__group .seg {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  margin: 0 6px 4px;
}
.user-menu-mobile__group .seg__btn {
  padding: 0 8px;
  font-size: 11.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.swatches {
  display: flex;
  gap: 8px;
  padding: 4px 12px 8px;
}
.swatch {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0.5px solid var(--rule);
  border-radius: 999px;
  background: transparent;
}
.swatch::before {
  content: "";
  width: 18px;
  height: 18px;
  border-radius: 999px;
}
.swatch--clay::before { background: #9c5538; }
.swatch--indigo::before { background: #3b5db5; }
.swatch--forest::before { background: #4a7b5a; }
.swatch--plum::before { background: #864c83; }
.swatch--active {
  box-shadow: 0 0 0 2px var(--bg-paper), 0 0 0 3.5px var(--ink);
}
.user-menu-mobile__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 8px 10px;
  border: 0;
  border-top: 0.5px solid var(--rule);
  border-radius: 0;
  background: transparent;
  color: var(--ink-80);
  font-size: 13px;
  text-align: left;
  text-transform: none;
  letter-spacing: 0;
}
.user-menu-mobile__signout {
  width: 100%;
  border: 0;
  background: transparent;
  color: var(--ink-65);
  text-align: left;
  padding: 0;
}
.library-list {
  list-style: none;
  padding: 0;
}
.library-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 14px;
  border: 0.5px solid var(--rule);
  border-radius: 10px;
  background: var(--paper-soft);
}
.library-row + .library-row { margin-top: 10px; }
.library-row__link {
  min-width: 0;
  flex: 1;
}
.library-row__kicker {
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-50);
}
.library-row__title {
  margin: 4px 0;
  font-size: 15px;
  line-height: 1.35;
}
.library-row__gist {
  margin: 0;
  color: var(--ink-65);
  font-size: 12.5px;
}
.library-paginate {
  margin-top: 16px;
  text-align: center;
}
.library-paginate__link {
  display: inline-block;
  padding: 8px 14px;
  border: 0.5px solid var(--rule);
  border-radius: 6px;
  background: var(--bg-paper);
  color: var(--ink-80);
  font-family: var(--font-mono);
  font-size: 11.5px;
  text-decoration: none;
}
.library-paginate__link:hover {
  border-color: var(--rule-strong);
  color: var(--ink);
}
.library-paginate__link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

@media (max-width: 768px) {
  body {
    font-size: 15px;
  }
  .top-bar {
    position: sticky;
    top: 0;
    height: auto;
    padding: 56px 18px 8px;
    gap: 10px;
    border-bottom: 0;
  }
  .brand {
    font-size: 19px;
  }
  .status-dot,
  .status-line,
  .top-bar__right > .seg {
    display: none;
  }
  .avatar {
    width: 32px;
    height: 32px;
    font-size: 11px;
  }
  /* Slice E visibility overrides — must live in this LATER media query
     so they win the equal-specificity cascade against base rules at
     lines ~1003 (.hamburger) and ~1022 (.rail-scrim) which would
     otherwise force `display: none` on mobile too. */
  .hamburger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  .rail-scrim {
    display: block;
    position: fixed;
    inset: var(--mobile-topbar-height, 108px) 0 0 0;
    background: rgba(0, 0, 0, 0.32);
    z-index: 104;
    opacity: 0;
    pointer-events: none;
    transition: opacity 240ms ease-out;
  }
  .rail-scrim.is-open {
    opacity: 1;
    pointer-events: auto;
  }
  .dashboard {
    display: block;
    height: auto;
    min-height: calc(100vh - 108px);
    overflow: visible;
  }
  /* The desktop body:has(.impersonation-banner) override sets a fixed calc
     height and would win on specificity here; reset it so mobile (block flow,
     body scrolls) keeps height:auto and the banner just adds to scroll height. */
  body:has(.impersonation-banner) .dashboard { height: auto; }
  .center-pane {
    overflow: visible;
    padding: 0 0 64px;
  }
  .center-pane > :not(.page-header) {
    margin-left: 18px;
    margin-right: 18px;
  }
  /* The briefing page carries the public .container's own 16px side padding
     (briefing_body.css) — stacking the generic 18px margins on top would
     inset its content 34px where the public mobile page shows 16px. */
  .center-pane > .briefing-page {
    margin-left: 0;
    margin-right: 0;
  }
  .page-header {
    position: static;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
    padding: 4px 18px 12px;
    border-bottom: 0;
    background: var(--bg-paper);
    backdrop-filter: none;
  }
  .page-header__title-group {
    flex-direction: column;
    gap: 2px;
  }
  .greeting {
    font-size: 28px;
  }
  /* Stack the date selector above a full-width view switcher on mobile.
   * Desktop is a single horizontal `view-controls` row; on mobile the
   * switcher's `width: 100%` only resolves when the parent is a column-
   * flex with a defined width — without this override the switcher sized
   * to its content (~186 px) and the chunky button design didn't land. */
  .view-controls {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    width: 100%;
  }
  /* Detail control goes full-width in the stacked mobile view-controls column,
   * matching the view switcher's full-width treatment above. */
  .briefing-density-control--docked {
    margin-right: 0;
    width: 100%;
  }
  .briefing-density-control--docked .briefing-density-options {
    flex: 1;
    min-width: 0;
    display: grid;
    /* minmax(0, 1fr) (not 1fr) so the three segments can shrink below their
       "Headlines" + glyph min-content instead of forcing the pill past its
       rounded border — mirrors the public toolbar's shrink-safe base track. */
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  /* Trim the desktop button padding/gap on phones so the longest label
     ("HEADLINES") + its glyph breathe inside the shrunk grid cells. Desktop
     keeps the roomier 6px 12px / 7px values above. */
  .briefing-density-control--docked .briefing-density-option {
    padding: 6px 6px;
    gap: 5px;
    justify-content: center;
    letter-spacing: 0.04em;
  }
  .date-selector {
    align-self: flex-start;
    margin-right: 0;
  }
  .view-switcher {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    width: 100%;
    gap: 6px;
    padding: 0;
    border: 0;
    background: transparent;
  }
  .view-switcher__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 32px;
    padding: 0;
    border: 0.5px solid var(--rule);
    border-radius: 8px;
    background: var(--paper-soft);
    font-size: 11px;
  }
  .view-switcher__btn--active {
    background: var(--ink);
    color: var(--bg-paper);
    border-color: var(--ink);
    box-shadow: none;
  }
  .card-grid,
  .card-grid--majors,
  .card-grid--standards,
  .card-grid--compacts {
    grid-template-columns: 1fr;
  }
  .card,
  .card--hero,
  .card--major,
  .card--standard,
  .card--compact {
    grid-column: span 1;
    border-radius: 12px;
  }
  .card--hero .card__headline {
    font-size: 22px;
    line-height: 1.2;
  }
  .card__meta {
    flex-wrap: wrap;
    justify-content: flex-end;
  }
  .card .action {
    width: 24px;
    height: 24px;
    border-radius: 6px;
  }
  .audio-strip {
    flex-direction: column;
    align-items: stretch;
  }
  .audio-strip__player {
    width: 100%;
    min-width: 0;
  }
  .reader__scrim {
    background: color-mix(in oklch, var(--ink) 32%, transparent);
  }
  .reader__panel {
    animation: mobile-sheet-in 360ms cubic-bezier(.2, .7, .2, 1) both;
  }
  @keyframes mobile-sheet-in {
    from { transform: translateY(100%); }
    to { transform: translateY(0); }
  }
  .reader__header {
    padding: 0 18px 12px;
  }
  .reader__header .action-bar {
    display: none;
  }
  .reader__close {
    border: 0.5px solid var(--rule);
    border-radius: 999px;
    background: var(--paper-soft);
  }
  .reader__content {
    padding: 0 18px;
  }
  .reader-chips {
    margin: 0 -18px;
    padding: 10px 18px;
  }
  .reader-hero__headline {
    font-size: 24px;
    line-height: 1.2;
  }
  .user-menu-mobile::before {
    background: color-mix(in oklch, var(--ink) 32%, transparent);
  }
  .user-menu-mobile__sheet {
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    width: auto;
    max-height: 78%;
    padding: 10px 0 24px;
    border: 0;
    border-top-left-radius: 24px;
    border-top-right-radius: 24px;
    box-shadow: 0 -20px 50px -10px rgba(0, 0, 0, 0.30);
    animation: mobile-sheet-in 360ms cubic-bezier(.2, .7, .2, 1) both;
  }
  .user-menu-mobile .sheet-handle {
    display: block;
  }
  .user-menu-mobile__identity {
    padding: 14px 20px 16px;
  }
  .user-menu-mobile__name {
    font-size: 15px;
  }
  .user-menu-mobile__group-label {
    padding: 14px 20px 4px;
    letter-spacing: 0.16em;
  }
  .user-menu-mobile__group .seg,
  .swatches {
    margin-left: 20px;
    margin-right: 20px;
    padding-left: 0;
    padding-right: 0;
  }
  .user-menu-mobile__row {
    padding: 12px 20px;
    font-size: 14px;
  }
}
