/* Foundation prototype fonts, all served locally for this branch. */
@font-face {
  font-family: "Elza";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/fonts/Elza-Regular.woff2") format("woff2");
}

@font-face {
  font-family: "Elza";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/assets/fonts/Elza-Medium.woff2") format("woff2");
}

@font-face {
  font-family: "Elza";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/assets/fonts/Elza-Semibold.woff2") format("woff2");
}

/* Self-hosted Inter variable font — kept as a dense-data fallback. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/assets/fonts/InterVariable.woff2") format("woff2-variations"),
       url("/assets/fonts/InterVariable.woff2") format("woff2");
}

@font-face {
  font-family: "Inter";
  font-style: italic;
  font-weight: 100 900;
  font-display: swap;
  src: url("/assets/fonts/InterVariable-Italic.woff2") format("woff2-variations"),
       url("/assets/fonts/InterVariable-Italic.woff2") format("woff2");
}

:root {
  color-scheme: light;

  /* Light theme is retained for the toggle, but the prototype boots dark. */
  --bg: #f6f4ef;
  --bg-grad-1: rgba(188, 145, 128, 0.08);
  --bg-grad-2: rgba(12, 12, 12, 0.028);
  --bg-grad-3: rgba(120, 92, 76, 0.035);

  --frame: rgba(255, 255, 255, 0.58);
  --frame-border: rgba(255, 255, 255, 0.88);
  --frame-stroke: rgba(66, 50, 42, 0.13);
  --frame-shadow: 0 24px 70px rgba(45, 35, 29, 0.15), 0 6px 18px rgba(45, 35, 29, 0.08);

  --card: rgba(255, 255, 255, 0.18);
  --card-border: rgba(255, 255, 255, 0.9);
  --card-stroke: rgba(72, 60, 50, 0.16);
  --card-hover: rgba(255, 255, 255, 0.32);

  --pill: rgba(255, 253, 248, 0.78);
  --pill-border: rgba(255, 255, 255, 0.86);
  --pill-stroke: rgba(71, 55, 46, 0.16);
  --pill-active: #201814;
  --pill-active-ink: #ffffff;
  --surface-strong: rgba(255, 253, 248, 0.96);
  --surface-inset: rgba(43, 34, 29, 0.06);
  --menu-bg: rgba(255, 253, 248, 0.96);
  --logo-bg: linear-gradient(135deg, rgba(255, 255, 255, 0.94) 0%, rgba(235, 223, 214, 0.82) 100%);
  --logo-border: rgba(71, 55, 46, 0.18);

  --ink: #17120f;
  --ink-soft: #3e332c;
  --muted: #75675f;
  --line: rgba(71, 55, 46, 0.16);
  --line-soft: rgba(71, 55, 46, 0.08);

  --accent: #bc9180;
  --accent-soft: #d6afa0;
  --accent-glow: rgba(188, 145, 128, 0.34);
  --pink: #ff9ad6;
  --blue: #8ab4cc;

  --orange: #f7931a;
  --red: #d4365b;
  --green: #2fb09e;

  --radius-lg: 18px;
  --radius-md: 12px;
  --radius-sm: 8px;
  --radius-pill: 999px;

  --shadow-card: 0 18px 52px rgba(36, 30, 24, 0.085), 0 1px 0 rgba(255, 255, 255, 0.94) inset, 0 -1px 0 rgba(54, 46, 38, 0.1) inset;
  --shadow-hero: 0 26px 82px rgba(36, 30, 24, 0.12), 0 1px 0 rgba(255, 255, 255, 0.92) inset, 0 -1px 0 rgba(54, 46, 38, 0.1) inset;
}

/* Dark theme — toggled with <html data-theme="dark"> */
[data-theme="dark"] {
  color-scheme: dark;
  --bg: #000000;
  --bg-grad-1: rgba(255, 255, 255, 0.14);
  --bg-grad-2: rgba(188, 145, 128, 0.12);
  --bg-grad-3: rgba(255, 255, 255, 0.06);

  --frame: rgba(0, 0, 0, 0.58);
  --frame-border: rgba(255, 255, 255, 0.08);
  --frame-stroke: rgba(255, 255, 255, 0.1);
  --frame-shadow: 0 30px 90px rgba(0, 0, 0, 0.62);

  --card: rgba(9, 9, 9, 0.76);
  --card-border: rgba(255, 255, 255, 0.07);
  --card-stroke: rgba(255, 255, 255, 0.1);
  --card-hover: rgba(20, 18, 17, 0.92);

  --pill: rgba(10, 10, 10, 0.72);
  --pill-border: rgba(255, 255, 255, 0.1);
  --pill-stroke: rgba(255, 255, 255, 0.12);
  --pill-active: #ffffff;
  --pill-active-ink: #080706;
  --surface-strong: rgba(18, 18, 18, 0.94);
  --surface-inset: rgba(255, 255, 255, 0.055);
  --menu-bg: rgba(8, 8, 8, 0.96);
  --logo-bg: linear-gradient(135deg, rgba(255, 255, 255, 0.92) 0%, rgba(224, 205, 195, 0.78) 100%);
  --logo-border: rgba(255, 255, 255, 0.18);

  --ink: #ffffff;
  --ink-soft: rgba(255, 255, 255, 0.8);
  --muted: rgba(255, 255, 255, 0.56);
  --line: rgba(255, 255, 255, 0.12);
  --line-soft: rgba(255, 255, 255, 0.065);
  --accent: #bc9180;
  --accent-soft: #e0b7a8;
  --accent-glow: rgba(188, 145, 128, 0.32);
  --shadow-card: 0 22px 70px rgba(0, 0, 0, 0.42), 0 1px 0 rgba(255, 255, 255, 0.06) inset;
  --shadow-hero: 0 40px 120px rgba(0, 0, 0, 0.52), 0 1px 0 rgba(255, 255, 255, 0.07) inset;
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  position: relative;
  isolation: isolate;
  margin: 0;
  min-height: 100vh;
  min-width: 320px;
  background: var(--bg);
  background-image:
    radial-gradient(ellipse 52% 42% at 50% 16%, var(--bg-grad-1) 0%, transparent 68%),
    radial-gradient(ellipse 38% 32% at 78% 18%, var(--bg-grad-2) 0%, transparent 70%),
    radial-gradient(ellipse 70% 48% at 50% 100%, var(--bg-grad-3) 0%, transparent 72%);
  background-size: auto, auto, auto;
  background-position: center top, right top, center bottom;
  background-repeat: no-repeat, no-repeat, no-repeat;
  background-attachment: fixed;
  color: var(--ink);
  font-family: Elza, Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-feature-settings: "ss01", "cv11";
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

body::before {
  content: "";
  position: fixed;
  top: 0;
  left: 50%;
  z-index: 0;
  width: 100vw;
  height: min(1040px, 100vh);
  min-height: 620px;
  pointer-events: none;
  transform: translateX(-50%);
  background-image: url("/assets/brand/foundation-deco-linework.svg");
  background-size: 314px 76px;
  background-position: center top;
  background-repeat: repeat;
  opacity: 0.072;
  -webkit-mask-image: radial-gradient(ellipse 46% 72% at 50% 18%, #000 0%, #000 48%, rgba(0, 0, 0, 0.74) 64%, rgba(0, 0, 0, 0.2) 84%, transparent 100%);
  mask-image: radial-gradient(ellipse 46% 72% at 50% 18%, #000 0%, #000 48%, rgba(0, 0, 0, 0.74) 64%, rgba(0, 0, 0, 0.2) 84%, transparent 100%);
}

[data-theme="dark"] body::before {
  opacity: 0.105;
  filter: invert(1);
}

a {
  color: inherit;
}

.page {
  position: relative;
  z-index: 1;
  width: min(1440px, 100%);
  margin: 0 auto;
  padding: clamp(14px, 3vw, 32px) clamp(14px, 3vw, 32px) clamp(40px, 6vw, 80px);
}

html, body { overflow-x: hidden; }

/* Keyboard-only skip link — invisible until focused, then sits at the
   top-left so a tab user can jump straight past the topbar to content. */
.skip-link {
  position: fixed;
  top: 12px;
  left: 12px;
  z-index: 1000;
  padding: 10px 16px;
  border-radius: var(--radius-sm);
  background: var(--ink);
  color: #fff;
  font-weight: 700;
  font-size: 0.9rem;
  text-decoration: none;
  transform: translateY(-200%);
  transition: transform 0.15s ease;
}

.skip-link:focus,
.skip-link:focus-visible {
  transform: translateY(0);
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Inline meta separator. Replaces the per-context horizontal-rule
   treatments scattered through this file (.hero-meta .sep,
   .rail-card-meta .sep, .feed-card-meta .sep, etc.). All those rules
   are now overridden here so the separator renders as a middle dot
   character instead of an em-dash-like line — reads cleaner between
   short meta items (badge · date · count). aria-hidden on the span
   keeps screen readers silent. */
.sep {
  display: inline-block !important;
  width: auto !important;
  height: auto !important;
  background: transparent !important;
  opacity: 1 !important;
  color: var(--muted);
  line-height: 1;
}

.sep::before {
  content: "·";
  font-weight: 700;
  opacity: 0.7;
}

/* ------- Glass frame ------- */
.glass-frame {
  position: relative;
  border-radius: var(--radius-lg);
  border: 1px solid var(--frame-stroke);
  background: var(--frame);
  backdrop-filter: blur(22px) saturate(1.05);
  -webkit-backdrop-filter: blur(22px) saturate(1.05);
  box-shadow: var(--frame-shadow), inset 0 1px 0 var(--frame-border);
  padding: clamp(18px, 3vw, 32px);
  overflow: hidden;
}

.hero-panel,
.rail-card,
.feed-card,
.source-card,
.post-card,
.related-card {
  position: relative;
  overflow: hidden;
  backdrop-filter: blur(6px) saturate(1.24) contrast(1.06);
  -webkit-backdrop-filter: blur(6px) saturate(1.24) contrast(1.06);
}

:root:not([data-theme="dark"]) .hero-panel,
:root:not([data-theme="dark"]) .rail-card,
:root:not([data-theme="dark"]) .feed-card,
:root:not([data-theme="dark"]) .source-card,
:root:not([data-theme="dark"]) .post-card,
:root:not([data-theme="dark"]) .related-card {
  backdrop-filter: blur(4px) saturate(1.28) contrast(1.08);
  -webkit-backdrop-filter: blur(4px) saturate(1.28) contrast(1.08);
  background:
    linear-gradient(145deg, rgba(255, 255, 255, 0.34) 0%, rgba(255, 255, 255, 0.06) 46%, rgba(255, 255, 255, 0.015) 100%),
    rgba(255, 255, 255, 0.1);
  border-color: rgba(72, 60, 50, 0.16);
}

:root:not([data-theme="dark"]) .rail-card::before,
:root:not([data-theme="dark"]) .feed-card::before,
:root:not([data-theme="dark"]) .source-card::before,
:root:not([data-theme="dark"]) .post-card::before,
:root:not([data-theme="dark"]) .related-card::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  border-radius: inherit;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.34) 0%, rgba(255, 255, 255, 0.06) 26%, transparent 64%),
    linear-gradient(90deg, rgba(255, 255, 255, 0.36) 0%, rgba(255, 255, 255, 0.08) 14%, transparent 34%),
    linear-gradient(0deg, rgba(54, 46, 38, 0.08) 0%, transparent 38%),
    radial-gradient(circle at 12% 0%, rgba(255, 255, 255, 0.26) 0%, transparent 34%);
}

:root:not([data-theme="dark"]) .rail-card > *,
:root:not([data-theme="dark"]) .feed-card > *,
:root:not([data-theme="dark"]) .source-card > *,
:root:not([data-theme="dark"]) .post-card > *,
:root:not([data-theme="dark"]) .related-card > * {
  position: relative;
  z-index: 1;
}

.glass-frame::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.4) 0%, rgba(255, 255, 255, 0) 35%),
    linear-gradient(315deg, rgba(180, 150, 255, 0.18) 0%, rgba(255, 255, 255, 0) 50%);
  pointer-events: none;
}

[data-theme="dark"] .glass-frame::before {
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0) 35%),
    linear-gradient(315deg, rgba(188, 145, 128, 0.14) 0%, rgba(255, 255, 255, 0) 50%);
}

/* ------- Top bar: brand + pill nav + search ------- */
.topbar {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: clamp(12px, 2vw, 24px);
  align-items: center;
  z-index: 2;
}

.brand {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  min-height: 0;
  padding: 0;
  border-radius: 0;
  background: transparent;
  border: 0;
  color: var(--ink);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.95rem;
  white-space: nowrap;
}

.brand img {
  display: block;
  width: clamp(156px, 14vw, 206px);
  height: auto;
}

:root:not([data-theme="dark"]) .brand {
  background: transparent;
}

:root:not([data-theme="dark"]) .brand img {
  filter: invert(1);
}

.pill-nav {
  display: flex;
  align-items: center;
  gap: 4px;
  /* Wrapping disabled on desktop — overflow scrolls horizontally if the row
     ever outgrows its column. With the trimmed pill padding below + the
     trimmed My List pill, all 9 pills fit on one line at 1280px+. The
     mobile media query overrides this with its own scroll setup. */
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.pill-nav::-webkit-scrollbar {
  display: none;
}

.pill-nav button,
.pill-nav a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 38px;
  padding: 0 12px;
  flex-shrink: 0;
  border-radius: var(--radius-sm);
  background: var(--pill);
  border: 1px solid var(--pill-stroke);
  color: var(--ink-soft);
  font: inherit;
  font-size: 0.88rem;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.pill-nav button:hover,
.pill-nav a:hover,
.pill-nav button:focus-visible,
.pill-nav a:focus-visible {
  background: var(--card-hover);
  border-color: rgba(188, 145, 128, 0.42);
  color: var(--ink);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.18);
  outline: none;
}

.brand {
  transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

.brand:hover,
.brand:focus-visible {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
  outline: none;
}

.brand:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 6px;
}

.search {
  transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

.search:hover,
.search:focus-within {
  border-color: rgba(188, 145, 128, 0.42);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.18);
}

.pill-nav button[aria-pressed="true"],
.pill-nav a[aria-pressed="true"] {
  background: var(--pill-active);
  border-color: var(--pill-active);
  color: var(--pill-active-ink);
}

.topbar-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.search {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 42px;
  padding: 0 14px;
  border-radius: var(--radius-sm);
  background: var(--pill);
  border: 1px solid var(--pill-stroke);
  min-width: 220px;
  max-width: 320px;
}

.theme-toggle {
  display: inline-grid;
  place-items: center;
  width: 42px;
  height: 42px;
  flex: 0 0 42px;
  border-radius: var(--radius-sm);
  background: var(--pill);
  border: 1px solid var(--pill-stroke);
  color: var(--ink);
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}

/* Mobile-only search trigger — hidden on desktop, shown by the phone
   media query below. Same shape/size as the theme toggle on phones so
   the topbar row has visual symmetry. */
.search-trigger {
  display: none;
  place-items: center;
  border-radius: var(--radius-sm);
  background: var(--pill);
  border: 1px solid var(--pill-stroke);
  color: var(--ink);
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}

.search-trigger:hover,
.search-trigger:focus-visible {
  background: var(--card-hover);
  border-color: rgba(188, 145, 128, 0.32);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.14);
  transform: translateY(-1px);
  outline: none;
}

.search-trigger svg {
  width: 17px;
  height: 17px;
}

.theme-toggle:hover,
.theme-toggle:focus-visible {
  background: var(--card-hover);
  border-color: rgba(188, 145, 128, 0.32);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.14);
  transform: translateY(-1px);
  outline: none;
}

.theme-toggle-icon {
  position: relative;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 0 4px rgba(188, 145, 128, 0.12);
}

.theme-toggle-icon::after {
  content: "";
  position: absolute;
  top: -3px;
  left: 5px;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background: var(--pill);
  transition: transform 0.15s ease, opacity 0.15s ease;
}

[data-theme="dark"] .theme-toggle-icon::after {
  transform: translate(9px, -2px);
  opacity: 0;
}

.search input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 0.9rem;
  outline: none;
}

.search input::placeholder {
  color: var(--muted);
}

.search-icon {
  width: 16px;
  height: 16px;
  color: var(--muted);
  flex-shrink: 0;
}

/* ------- Hero block ------- */
.hero-shell {
  margin-top: clamp(20px, 3vw, 32px);
}

.hero {
  position: relative;
  /* Was a 2-column grid (hero / rail). Rail was retired — hero now
     spans the full width of the home shell. Auto min-height: the
     content's natural size sets it, which on desktop is significantly
     shorter than the old 420px floor (the rail used to pad the row).
     Net effect: the latest brief sits closer to the top of the fold. */
  display: block;
  width: 100%;
  min-width: 0;
}

.hero > * {
  min-width: 0;
}

.hero-copy {
  display: flex;
  width: 100%;
  min-width: 0;
  align-self: stretch;
}

/* Hero panel — solid white card matching the rail-card aesthetic, floats
   on the page background with real lift. Content stacks from top; the
   logo strip uses auto margins to center itself in any free vertical
   space, and the CTA anchors to the bottom. */
.hero-panel {
  position: relative;
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: 18px;
  padding: clamp(24px, 3vw, 40px);
  border-radius: var(--radius-md);
  border: 1px solid var(--card-stroke);
  background: var(--card);
  box-shadow: var(--shadow-hero);
  overflow: hidden;
}

.hero-panel::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0) 36%),
    radial-gradient(circle at 86% 12%, rgba(188, 145, 128, 0.18) 0%, transparent 34%);
}

.hero-panel > * {
  position: relative;
  z-index: 1;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  border-radius: var(--radius-pill);
  background: rgba(188, 145, 128, 0.12);
  border: 1px solid rgba(188, 145, 128, 0.22);
  color: var(--accent);
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  width: fit-content;
}

/* Topline pairs the LATEST eyebrow pill with the date/reading-time meta
   on one horizontal row. Saves a row of vertical space vs. the old
   layout where meta sat above the H1 inside the headline block.
   nowrap because Chromium's wrap algorithm was being conservative on
   narrow viewports and stacking them even when ~60px of slack
   remained. With nowrap + min-width: 0 on the meta, the meta text
   shrinks/ellipsises gracefully on truly tiny viewports if needed. */
.hero-topline {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: 16px;
  min-width: 0;
}

/* When the meta is rendered inside .hero-topline (as opposed to the post
   detail page where it sits inside .hero-headline), keep it on one line
   alongside the eyebrow. Without this, the mobile rule
   `.hero-meta { flex-wrap: wrap }` makes the meta claim a full row even
   when it'd fit beside the eyebrow. */
.hero-topline .hero-meta {
  flex-wrap: nowrap;
  flex-shrink: 1;
  min-width: 0;
}

.hero-topline .hero-meta > span {
  white-space: nowrap;
}

.hero-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--muted);
  font-size: 0.85rem;
  font-weight: 500;
}

.hero-meta .sep {
  width: 14px;
  height: 1px;
  background: var(--muted);
  opacity: 0.5;
}

/* Prev / next brief navigation footer on brief detail pages. Two cards
   side-by-side: previous brief on the left, next on the right. Mobile
   collapses to a stacked single column. Recaps walk recap-to-recap and
   dailies walk daily-to-daily so the navigation never mixes formats. */
.brief-prev-next {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-top: 32px;
}

.brief-prev-next-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border-radius: var(--radius-md);
  border: 1px solid var(--card-stroke);
  background: var(--card);
  color: var(--ink);
  text-decoration: none;
  transition: border-color 0.15s, background 0.15s;
}

.brief-prev-next-card:hover {
  border-color: rgba(188, 145, 128, 0.4);
  background: rgba(188, 145, 128, 0.04);
}

.brief-prev-next-card--next {
  flex-direction: row-reverse;
  text-align: right;
}

.brief-prev-next-card--empty {
  background: transparent;
  border-color: transparent;
}

.brief-prev-next-arrow {
  flex: 0 0 auto;
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--muted);
}

.brief-prev-next-meta {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.brief-prev-next-title {
  margin-top: 4px;
  font-weight: 600;
  color: var(--ink);
  line-height: 1.3;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

@media (max-width: 640px) {
  .brief-prev-next { grid-template-columns: 1fr; }
  .brief-prev-next-card--empty { display: none; }
}

/* Brief eyebrow date — shown above the LLM headline on brief detail pages,
   so the canonical date stays scannable while the headline does the H1 work. */
.brief-date-eyebrow {
  color: var(--muted);
  font-size: 0.9rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  margin: 6px 0 6px;
}

/* Brief table of contents — a horizontal pill row between the lead and
   the body sections. Each pill jumps to a slugified h2 in the brief. On
   mobile this scrolls horizontally so long briefs don't push the body
   far down the page. */
.brief-toc {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 14px 0 20px;
  padding: 12px 0;
  border-top: 1px solid var(--border, rgba(188, 145, 128, 0.12));
  border-bottom: 1px solid var(--border, rgba(188, 145, 128, 0.12));
}

.brief-toc-pill {
  display: inline-flex;
  align-items: center;
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid rgba(188, 145, 128, 0.22);
  background: rgba(188, 145, 128, 0.06);
  color: var(--ink);
  font-size: 0.82rem;
  font-weight: 600;
  text-decoration: none;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}

.brief-toc-pill:hover,
.brief-toc-pill:focus-visible {
  background: rgba(188, 145, 128, 0.18);
  border-color: rgba(188, 145, 128, 0.45);
}

[data-theme="dark"] .brief-toc-pill {
  border-color: rgba(255, 255, 255, 0.22);
  background: rgba(255, 255, 255, 0.05);
}

[data-theme="dark"] .brief-toc-pill:hover,
[data-theme="dark"] .brief-toc-pill:focus-visible {
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.5);
}

/* Smooth scroll when clicking a TOC pill — soft jump rather than hard cut.
   Scope to the brief body so we don't change site-wide anchor behavior. */
html { scroll-behavior: smooth; }

/* Slight scroll offset so the in-page anchor doesn't land flush against
   the viewport top — leaves room for the section heading to breathe. */
.post-body h2[id] { scroll-margin-top: 28px; }

@media (max-width: 640px) {
  .brief-toc {
    flex-wrap: nowrap;
    overflow-x: auto;
    margin: 12px -16px 20px;
    padding: 10px 16px;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .brief-toc::-webkit-scrollbar { display: none; }
  .brief-toc-pill { flex: 0 0 auto; }
}

.hero h1 {
  margin: 0;
  font-size: clamp(2.2rem, 4vw, 4.2rem);
  line-height: 1.05;
  letter-spacing: 0;
  font-weight: 600;
  color: var(--ink);
  max-width: min(100%, 24ch);
}

.hero-panel .hero-headline {
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(18px, 2.2vw, 28px);
  align-items: center;
}

.hero-panel .hero-headline .logo.logo-lg {
  width: clamp(72px, 6vw, 88px);
  height: clamp(72px, 6vw, 88px);
}

.hero-panel .hero-headline > div {
  max-width: 100%;
}

.hero .post-summary {
  width: 100%;
  min-width: 0;
  /* Was 62ch back when the hero shared its column with the rail. Rail
     retired → panel is full-width → body wraps wider → fewer lines and
     less wasted whitespace on the right. Matches the editorial variant's
     max-width below. */
  max-width: min(100%, 90ch);
  overflow-wrap: anywhere;
  word-break: break-word;
  /* Cap the hero summary at 4 lines so a long release notes block can't
     push the CTA below the fold. Full summary still renders on the
     detail page (.post-card .post-summary). */
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin-bottom: 6px;
}

.hero .post-summary span {
  display: block;
  min-width: 0;
  margin-top: 6px;
  overflow-wrap: anywhere;
  word-break: break-word;
}

.hero .post-summary span:first-child {
  margin-top: 0;
}

.hero .post-summary strong {
  color: var(--ink);
  font-weight: 700;
}

/* Editorial variant — used when the LLM lead replaces the auto-summary.
   Italic + quote-style left border to signal "editor's voice" rather
   than "system-generated stat line". Clamped to 4 lines on the hero so
   the full panel (including the CTA + brief logos) stays above the fold
   on a typical 900px-tall desktop viewport. Full text always renders on
   the brief's detail page. Wider max-width than the regular variant
   because the panel is now full-width with no rail to share it with. */
.hero .post-summary--editorial {
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-style: italic;
  padding-left: 14px;
  border-left: 2px solid var(--accent, rgba(160, 130, 255, 0.6));
  color: var(--ink);
  line-height: 1.55;
  max-width: 90ch;
}

.hero .post-summary--editorial span {
  margin-top: 0;
}

.hero-signals {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  min-width: 0;
  margin-top: 18px;
}

.hero-signal {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  min-height: 34px;
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  border: 1px solid rgba(188, 145, 128, 0.18);
  background: rgba(188, 145, 128, 0.06);
  color: var(--muted);
  font-size: 0.76rem;
  font-weight: 700;
}

.hero-signal strong {
  color: var(--ink);
  font-size: 0.92rem;
  font-weight: 850;
}

[data-theme="dark"] .hero-signal {
  border-color: rgba(255, 255, 255, 0.18);
  background: rgba(255, 255, 255, 0.06);
}

/* Horizontal marquee of project logos shown on brief previews — slow
   auto-scroll right-to-left, "what's in this brief" at a glance. Auto
   margins center it in the empty space between summary and CTA. Vertical
   padding gives room for the logo drop shadows to render without getting
   clipped by overflow: hidden. */
.hero-logo-strip {
  position: relative;
  min-width: 0;
  width: 100%;
  margin: auto 0;
  /* Tight vertical padding so the strip doesn't blow the hero panel past
     a 13"-laptop screen height. Browser title= tooltip still gives the
     project name on hover; we don't need a custom label row underneath. */
  padding: 6px 0;
  overflow: hidden;
}

/* The track is what scrolls — the fade mask is applied here so it doesn't
   clip the label below. */
.hero-logo-strip-track {
  position: relative;
  display: flex;
  flex-wrap: nowrap;
  gap: 12px;
  width: max-content;
  animation: hero-logo-marquee 45s linear infinite;
  will-change: transform;
  mask-image: linear-gradient(to right, transparent 0, #000 32px, #000 calc(100% - 32px), transparent 100%);
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 32px, #000 calc(100% - 32px), transparent 100%);
}

.hero-logo-strip:hover .hero-logo-strip-track,
.hero-logo-strip:focus-within .hero-logo-strip-track {
  animation-play-state: paused;
}

.hero-logo-strip .logo {
  flex-shrink: 0;
  width: 52px;
  height: 52px;
  border-radius: 12px;
  box-shadow:
    0 8px 18px rgba(0, 0, 0, 0.26),
    0 2px 6px rgba(0, 0, 0, 0.18),
    0 1px 0 rgba(255, 255, 255, 0.5) inset;
}

/* Desktop bumps the marquee logos +25% for more presence on wider canvases. */
@media (min-width: 980px) {
  .hero-logo-strip .logo {
    width: 65px;
    height: 65px;
    border-radius: 15px;
  }

  .hero-logo-strip-track {
    gap: 14px;
  }
}

[data-theme="dark"] .hero-logo-strip .logo {
  box-shadow:
    0 8px 18px rgba(0, 0, 0, 0.5),
    0 2px 6px rgba(0, 0, 0, 0.32),
    0 1px 0 rgba(255, 255, 255, 0.06) inset;
}

.hero-logo-strip .logo img {
  pointer-events: none;
}

/* Loop one full copy of the list — since the track contains the logos
   twice end-to-end, translating by -50% means the second copy lines up
   exactly where the first started. No visible jump. */
@keyframes hero-logo-marquee {
  0%   { transform: translateX(0); }
  100% { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
  .hero-logo-strip-track { animation: none; }
}

.hero-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  min-width: 0;
  margin-top: 8px;
}

.hero-source-note {
  color: var(--muted);
  font-size: 0.8rem;
  font-weight: 650;
  overflow-wrap: anywhere;
}

.hero-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.tag {
  display: inline-flex;
  align-items: center;
  height: 28px;
  padding: 0 12px;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 600;
}

.tag.solid {
  background: var(--pill);
  border: 1px solid var(--pill-stroke);
}

.cta {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  height: 48px;
  padding: 0 22px 0 24px;
  border-radius: var(--radius-md);
  background: linear-gradient(159.5deg, #bc9180 0%, #713a29 100%);
  border: 1px solid rgba(113, 58, 41, 0.44);
  color: #ffffff;
  font: inherit;
  font-weight: 700;
  font-size: 0.95rem;
  text-decoration: none;
  cursor: pointer;
  width: fit-content;
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.28);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

[data-theme="dark"] .cta {
  border-color: rgba(188, 145, 128, 0.38);
}

.cta:hover {
  transform: translateY(-1px);
  box-shadow: 0 18px 46px rgba(0, 0, 0, 0.36);
}

.cta-arrow {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  /* Was var(--ink) which is near-white in dark mode — invisible against
     the equally light .cta background. Accent purple pops in both themes
     and reinforces brand colour at the primary action. */
  background: rgba(0, 0, 0, 0.24);
  color: #fff;
  font-size: 0.78rem;
  font-weight: 700;
  line-height: 1;
}

/* Orb removed — hero now uses the same glass-card aesthetic as the rail. */

/* ------- Right rail: Recommended ------- */
/* Hide the rail container when it has no content — covers stale SW cache
   serving old app.js that doesn't know how to populate the new structure,
   and also handles genuinely empty fallback weeks (very rare given the
   "Latest releases" bucket).  CSS :empty is true when there are zero
   children, not just no visible content. */
.rail:empty {
  display: none;
}

.rail {
  position: relative;
  z-index: 2;
  align-self: stretch;
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-width: 0;
  isolation: isolate;
  /* Give the rail the same card-surface treatment as .hero-panel so both
     visible "boxes" read as equal-height containers regardless of how
     much content each one has inside. Grid align-items:stretch already
     equalises the heights; this just makes that equality visible. */
  padding: clamp(18px, 2.2vw, 24px);
  border-radius: var(--radius-md);
  border: 1px solid var(--card-stroke);
  background: var(--card);
  box-shadow: var(--shadow-card);
}

.rail-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 0 2px;
  margin-bottom: 12px;
}

.rail-head h2 {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--ink);
}

/* Multi-section rail. Each section is { heading, mini-card-list }. The
   rail aside now contains 1–3 sections (Most shipped this week, Security
   patches, Hot in last 24h) instead of one flat list. */
.rail-section {
  display: flex;
  flex-direction: column;
}

.rail-section + .rail-section {
  margin-top: 22px;
  padding-top: 22px;
  border-top: 1px solid var(--border, rgba(188, 145, 128, 0.12));
}

.rail-extra {
  color: var(--accent, #bc9180);
  font-weight: 700;
}

.rail-head a {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--muted);
  font-size: 0.82rem;
  font-weight: 600;
  text-decoration: none;
}

.rail-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.rail-card {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr);
  gap: 12px;
  align-items: center;
  padding: 12px 14px;
  border-radius: var(--radius-md);
  border: 1px solid var(--card-stroke);
  background: var(--card);
  box-shadow: var(--shadow-card);
  text-decoration: none;
  color: var(--ink);
  cursor: pointer;
  transition: transform 0.15s ease, background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

.rail-card-body { min-width: 0; }

.rail-card:hover,
.rail-card:focus-visible {
  background: var(--card-hover);
  border-color: rgba(188, 145, 128, 0.32);
  transform: translateY(-1px);
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.16);
  outline: none;
}

.rail-card-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 4px;
  color: var(--muted);
  font-size: 0.74rem;
  font-weight: 600;
  /* The meta row was wrapping per-span ("AI release" splitting into "AI"
     and "release" on separate lines), making card heights inconsistent.
     Keep on one line; truncate gracefully if a long badge ever overflows. */
  min-width: 0;
  flex-wrap: nowrap;
  overflow: hidden;
}

.rail-card-meta > span:not(.sep) {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.rail-card-meta .sep {
  width: 10px;
  height: 1px;
  background: var(--muted);
  opacity: 0.4;
  flex-shrink: 0;
}

.rail-card h4 {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.25;
  font-weight: 700;
  color: var(--ink);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
  /* Always reserve 2 lines so every rail-card has the same height. */
  min-height: calc(2 * 1.25em);
}

.rail-thumb {
  width: 64px;
  height: 64px;
  border-radius: var(--radius-sm);
  background: linear-gradient(135deg, var(--accent-soft) 0%, var(--pink) 100%);
  position: relative;
  overflow: hidden;
  flex-shrink: 0;
}

.rail-thumb[data-tone="security"] { background: linear-gradient(135deg, #ff8a9d 0%, #713a29 100%); }
.rail-thumb[data-tone="release"] { background: linear-gradient(135deg, #8ec5ff 0%, #d6afa0 100%); }
.rail-thumb[data-tone="privacy"] { background: linear-gradient(135deg, #713a29 0%, #8ec5ff 100%); }
.rail-thumb[data-tone="lightning"] { background: linear-gradient(135deg, #ffd28a 0%, #ff9ad6 100%); }
.rail-thumb[data-tone="nostr"] { background: linear-gradient(135deg, #d6afa0 0%, #ff9ad6 100%); }
.rail-thumb[data-tone="ai"] { background: linear-gradient(135deg, #2fe0c4 0%, #8ec5ff 100%); }
.rail-thumb[data-tone="research"] { background: linear-gradient(135deg, #8ec5ff 0%, #bc9180 100%); }
.rail-thumb[data-tone="guide"] { background: linear-gradient(135deg, #d6afa0 0%, #8ec5ff 100%); }

.rail-thumb::after {
  content: "";
  position: absolute;
  inset: -10%;
  background:
    radial-gradient(circle at 30% 30%, rgba(255, 255, 255, 0.7) 0%, transparent 35%),
    radial-gradient(circle at 70% 70%, rgba(255, 255, 255, 0.25) 0%, transparent 45%);
}

/* ------- Chronological feed ------- */
.feed {
  margin-top: clamp(28px, 4vw, 48px);
}

.feed-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 18px;
  padding: 0 6px;
}

.feed-head h2 {
  margin: 0;
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--ink);
}

.feed-head .feed-count {
  color: var(--muted);
  font-size: 0.85rem;
  font-weight: 500;
}

.feed-see-all {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 6px 12px;
  border-radius: var(--radius-sm);
  background: rgba(188, 145, 128, 0.08);
  border: 1px solid rgba(188, 145, 128, 0.18);
  color: var(--accent);
  font-size: 0.82rem;
  font-weight: 700;
  text-decoration: none;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.feed-see-all:hover {
  background: rgba(188, 145, 128, 0.18);
  border-color: rgba(188, 145, 128, 0.32);
}

.feed-see-all[hidden] {
  display: none;
}

.post-nav-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
}

.post-nav-row .post-back {
  margin-bottom: 0;
}

.post-nav-actions {
  display: flex;
  align-items: center;
  /* nowrap: the action buttons must never split across lines. A long
     product name in the project-history link used to push Share + the
     theme toggle onto a second row. */
  flex-wrap: nowrap;
  gap: 10px;
  margin-left: auto;
  min-width: 0;
}

/* The project-history link is the only flexible action — it shrinks and
   ellipsises its label so an absurd product name (e.g. "Arkade TS SDK
   @arkade-os/boltz-swap") can never force the row to wrap. Share and the
   theme toggle stay fixed-width. */
.post-nav-actions .post-back {
  min-width: 0;
  max-width: clamp(150px, 34vw, 360px);
  white-space: nowrap;
}

.post-nav-actions .post-back .post-back-long {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.post-nav-actions .post-back > [aria-hidden],
.post-nav-actions .share-control,
.post-nav-actions .theme-toggle {
  flex-shrink: 0;
}

.archive-header {
  position: relative;
  z-index: 1;
  padding: clamp(20px, 3vw, 32px);
  border-radius: var(--radius-md);
  border: 1px solid var(--card-stroke);
  background: var(--card);
  box-shadow: var(--shadow-card);
}

/* "Browse by topic" tag cloud — chip row on the briefs archive page
   that surfaces /tag/<slug>/ pages which would otherwise be orphaned. */
.tag-cloud-section {
  margin: 20px 0 8px;
}

.tag-cloud-heading {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 12px;
}

.tag-cloud {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.tag-cloud-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid var(--card-stroke);
  background: var(--card);
  color: var(--ink);
  font-size: 0.85rem;
  font-weight: 600;
  text-decoration: none;
  transition: background 0.15s, border-color 0.15s;
}

.tag-cloud-chip:hover,
.tag-cloud-chip:focus-visible {
  background: rgba(188, 145, 128, 0.08);
  border-color: rgba(188, 145, 128, 0.35);
}

.tag-cloud-count {
  color: var(--muted);
  font-weight: 600;
  font-size: 0.75rem;
}

/* Project page (/project/<slug>/) — richer header than the generic
   archive layout, with stats tiles and a siblings sidebar. */
.project-header {
  display: flex;
  align-items: flex-start;
  gap: clamp(16px, 2.5vw, 28px);
  padding: clamp(20px, 3vw, 32px);
  border-radius: var(--radius-md);
  border: 1px solid var(--card-stroke);
  background: var(--card);
  box-shadow: var(--shadow-card);
}

.project-header-logo {
  width: 80px;
  height: 80px;
  border-radius: 18px;
  flex: 0 0 80px;
  object-fit: cover;
  background: rgba(188, 145, 128, 0.08);
}

.project-header-logo--fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 32px;
  font-weight: 800;
  color: var(--accent, #bc9180);
}

.project-header-body {
  flex: 1;
  min-width: 0;
}

.project-header-meta {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 6px;
}

.project-header-body h1 {
  margin: 0 0 8px;
  font-size: clamp(1.6rem, 3vw, 2.2rem);
  line-height: 1.15;
}

.project-header-desc {
  margin: 6px 0 14px;
  color: var(--muted);
  line-height: 1.55;
  max-width: 60ch;
}

.project-beat-badge {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 999px;
  background: rgba(188, 145, 128, 0.15);
  color: var(--accent, #bc9180);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-decoration: none;
}

.project-beat-badge:hover { background: rgba(188, 145, 128, 0.25); }

.project-link-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.project-link-chip {
  display: inline-flex;
  align-items: center;
  padding: 6px 12px;
  border-radius: 999px;
  border: 1px solid var(--card-stroke);
  background: var(--card);
  color: var(--ink);
  font-size: 0.85rem;
  font-weight: 600;
  text-decoration: none;
  transition: background 0.15s, border-color 0.15s;
}

.project-link-chip:hover,
.project-link-chip:focus-visible {
  background: rgba(188, 145, 128, 0.08);
  border-color: rgba(188, 145, 128, 0.35);
}

.project-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 12px;
  margin: 20px 0;
}

.project-stat {
  padding: 14px 16px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--card-stroke);
  background: var(--card);
}

.project-stat-value {
  font-size: 1.35rem;
  font-weight: 800;
  color: var(--ink);
  line-height: 1.1;
}

.project-stat-label {
  margin-top: 4px;
  color: var(--muted);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.project-layout {
  display: grid;
  grid-template-columns: 1fr 240px;
  gap: clamp(20px, 3vw, 32px);
  margin-top: 20px;
}

@media (max-width: 920px) {
  .project-layout { grid-template-columns: 1fr; }
}

.project-releases-heading {
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 14px;
}

.project-empty-state {
  display: grid;
  gap: 10px;
  padding: 20px;
  border: 1px solid var(--card-stroke);
  border-radius: var(--radius-sm);
  background: var(--card);
}

.project-empty-state h3 {
  margin: 0 0 6px;
  font-size: 1rem;
}

.project-empty-state p {
  margin: 0;
  color: var(--muted);
  line-height: 1.55;
}

.project-empty-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 4px;
}

.project-siblings {
  padding: 16px 18px;
  border-radius: var(--radius-md);
  border: 1px solid var(--card-stroke);
  background: var(--card);
  align-self: start;
}

.project-siblings h2 {
  margin: 0 0 12px;
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.project-siblings ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.project-siblings li {
  margin: 0 0 6px;
}

.project-siblings a {
  color: var(--ink);
  text-decoration: none;
  font-weight: 500;
}

.project-siblings a:hover { color: var(--accent, #bc9180); }

@media (max-width: 640px) {
  .project-header { flex-direction: column; }
}

.archive-title-row {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 14px;
}

.archive-title-row h1 {
  margin: 0;
  font-size: clamp(1.85rem, 3.4vw, 2.8rem);
  line-height: 1.1;
  letter-spacing: 0;
  font-weight: 800;
  overflow-wrap: anywhere;
}

.archive-count {
  display: inline-flex;
  align-items: center;
  height: 32px;
  padding: 0 12px;
  border-radius: var(--radius-pill);
  background: rgba(188, 145, 128, 0.1);
  border: 1px solid rgba(188, 145, 128, 0.18);
  color: var(--accent);
  font-size: 0.78rem;
  font-weight: 800;
}

.archive-header .post-summary {
  max-width: 760px;
  margin: 12px 0 0;
}

.date-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0 6px 14px;
}

.date-filters button {
  display: inline-flex;
  align-items: center;
  height: 30px;
  padding: 0 12px;
  border-radius: var(--radius-sm);
  background: var(--pill);
  border: 1px solid var(--pill-stroke);
  color: var(--ink-soft);
  font: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;
}

.date-filters button:hover,
.date-filters button:focus-visible {
  background: var(--card-hover);
  border-color: rgba(188, 145, 128, 0.32);
  color: var(--ink);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.14);
  outline: none;
}

.date-filters button[aria-pressed="true"] {
  background: var(--pill-active);
  border-color: var(--pill-active);
  color: var(--pill-active-ink);
}

.feed-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
}

.feed-more {
  display: flex;
  justify-content: center;
  margin-top: 24px;
}

.feed-more[hidden] { display: none; }

.feed-more button {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 42px;
  padding: 0 24px;
  border-radius: var(--radius-sm);
  background: var(--pill);
  border: 1px solid var(--pill-stroke);
  color: var(--ink);
  font: inherit;
  font-size: 0.9rem;
  font-weight: 700;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}

.feed-more button:hover,
.feed-more button:focus-visible {
  background: var(--card-hover);
  border-color: rgba(188, 145, 128, 0.32);
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.16);
  transform: translateY(-1px);
  outline: none;
}

/* Favorites — shared between feed cards (home) and source cards
   (/sources/). The star button is a sibling of the card link inside its
   wrapper so it can be clicked independently of the card navigation. */
.feed-card-wrap,
.source-li {
  position: relative;
  display: flex;
  min-width: 0;
}

.feed-card-wrap > .feed-card,
.source-li > .source-card {
  flex: 1;
  min-width: 0;
}

.fav-toggle {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border-radius: 50%;
  background: var(--pill);
  border: 1px solid var(--pill-stroke);
  color: var(--muted);
  cursor: pointer;
  /* Subtle by default; fills in when active. Slight pop on press so the
     interaction feels real on touch devices. */
  transition: background 0.15s ease, border-color 0.15s ease,
              color 0.15s ease, transform 0.12s ease;
}

.fav-toggle:hover,
.fav-toggle:focus-visible {
  background: var(--card-hover);
  border-color: rgba(188, 145, 128, 0.32);
  color: var(--ink);
  outline: none;
}

.fav-toggle:active {
  transform: scale(0.92);
}

.fav-toggle[aria-pressed="true"] {
  background: rgba(188, 145, 128, 0.18);
  border-color: rgba(188, 145, 128, 0.55);
  color: var(--accent);
}

[data-theme="dark"] .fav-toggle[aria-pressed="true"] {
  background: rgba(188, 145, 128, 0.22);
}

.fav-toggle svg {
  width: 16px;
  height: 16px;
  display: block;
}

/* Post-page favorite chip — lives inside the .post-card just below the
   hero headline. Labelled (not icon-only) so it reads as a clear action:
   "Add llama.cpp to My List". Toggles to "On My List · llama.cpp" once
   active, with the star filled. Lives inside the card so it doesn't fight
   the topbar nav row for space on mobile. */
.post-fav-row {
  /* Sits between the H1 and the body copy. Equal-ish spacing top + bottom
     so the chip reads as a standalone affordance rather than glued to
     either side. */
  margin: 12px 0 18px;
  display: flex;
  justify-content: flex-start;
}

.fav-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 38px;
  padding: 0 14px 0 12px;
  /* Match the design-system radius used by the topbar nav buttons (Back,
     All versions, Share, theme toggle) instead of a full-pill radius —
     the post-card itself uses --radius-md so this stays consistent. */
  border-radius: var(--radius-sm);
  background: var(--pill);
  border: 1px solid var(--pill-stroke);
  color: var(--ink-soft);
  font: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease,
              color 0.15s ease, transform 0.12s ease;
  max-width: 100%;
}

.fav-chip:hover,
.fav-chip:focus-visible {
  background: var(--card-hover);
  border-color: rgba(188, 145, 128, 0.32);
  color: var(--ink);
  outline: none;
}

.fav-chip:active {
  transform: scale(0.97);
}

.fav-chip[aria-pressed="true"] {
  background: rgba(188, 145, 128, 0.16);
  border-color: rgba(188, 145, 128, 0.55);
  color: var(--accent);
}

[data-theme="dark"] .fav-chip[aria-pressed="true"] {
  background: rgba(188, 145, 128, 0.22);
}

.fav-chip-icon {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

.fav-chip-label {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

/* Reserve room in the card's head row so the badge/date metadata doesn't
   slide under the star button at the top-right. :has() lets us only pay
   the cost on cards that actually have a star (briefs don't). */
.feed-card-wrap:has(.fav-toggle) .feed-card-head {
  padding-right: 36px;
}

.source-li .source-card-head {
  padding-right: 36px;
}

/* My List pill — distinct from the beat pills so it reads as "this is
   your personal view" rather than another category. Kept narrow so the
   whole pill row fits on one line at 1280px+ without wrapping. */
.pill-nav a.pill-fav {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 0 12px;
  background: rgba(188, 145, 128, 0.10);
  border-color: rgba(188, 145, 128, 0.32);
  color: var(--ink);
}

.pill-nav a.pill-fav .pill-fav-icon {
  width: 12px;
  height: 12px;
  color: var(--accent);
}

/* Count is rendered as plain inline text in the accent color rather than
   a separate badge bubble — saves ~25px of pill width which is what was
   pushing the "Briefs" pill onto a second line on the desktop layout. */
.pill-nav a.pill-fav .pill-fav-count {
  color: var(--accent);
  font-size: 0.85rem;
  font-weight: 700;
  margin-left: 2px;
}

.pill-nav a.pill-fav[aria-pressed="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.pill-nav a.pill-fav[aria-pressed="true"] .pill-fav-icon {
  color: #fff;
}

.pill-nav a.pill-fav[aria-pressed="true"] .pill-fav-count {
  color: rgba(255, 255, 255, 0.88);
}

/* Mobile filter drawer — make the My List option visually match. */
.filter-drawer-option-fav .filter-drawer-fav-count {
  display: inline-grid;
  place-items: center;
  min-width: 20px;
  height: 18px;
  margin-left: 6px;
  padding: 0 6px;
  border-radius: 9px;
  background: var(--accent);
  color: #fff;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1;
}

/* Empty state when My List filter is active but nothing matches the
   current date range. */
.empty-state-favorites {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 28px;
  border-radius: var(--radius-md);
  border: 1px dashed var(--card-stroke);
  background: var(--card);
  text-align: center;
}

.empty-state-favorites p {
  margin: 0;
  color: var(--ink-soft);
}

.empty-state-favorites a {
  color: var(--accent);
  text-decoration: none;
  font-weight: 600;
}

.empty-state-favorites a:hover {
  text-decoration: underline;
}

/* Toast — used for the stale-favorite prune notice and similar one-shot
   confirmations. Anchored top-right on desktop, top-center on mobile.
   No backdrop; auto-dismisses after 4s. */
.ftd-toast {
  position: fixed;
  top: 24px;
  right: 24px;
  z-index: 200;
  max-width: 320px;
  padding: 12px 16px;
  border-radius: var(--radius-sm);
  background: var(--card);
  border: 1px solid var(--card-stroke);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.32);
  color: var(--ink);
  font-size: 0.9rem;
  line-height: 1.4;
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity 0.2s ease, transform 0.2s ease;
  cursor: pointer;
}

.ftd-toast--visible {
  opacity: 1;
  transform: translateY(0);
}

@media (max-width: 640px) {
  .ftd-toast {
    top: 12px;
    left: 12px;
    right: 12px;
    max-width: none;
  }
}

.feed-card {
  display: flex;
  flex-direction: column;
  gap: 9px;
  min-width: 0;
  padding: 18px 18px 20px;
  border-radius: var(--radius-md);
  border: 1px solid var(--card-stroke);
  background: var(--card);
  box-shadow: var(--shadow-card);
  color: var(--ink);
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.15s ease, background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
  text-align: left;
  font: inherit;
}

.feed-card:hover,
.feed-card:focus-visible {
  transform: translateY(-1px);
  background: var(--card-hover);
  border-color: rgba(188, 145, 128, 0.32);
  box-shadow: 0 14px 36px rgba(0, 0, 0, 0.24);
  outline: none;
}

.feed-card-head {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

.feed-card-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  min-width: 0;
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 600;
}

.feed-card-meta span {
  min-width: 0;
  overflow-wrap: anywhere;
}

.feed-card-meta .sep {
  width: 12px;
  height: 1px;
  background: var(--muted);
  opacity: 0.4;
}

.feed-card h3 {
  margin: 4px 0 0;
  font-size: 1.1rem;
  line-height: 1.22;
  font-weight: 700;
  overflow-wrap: anywhere;
  color: var(--ink);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.feed-card p {
  margin: 0;
  color: var(--muted);
  font-size: 0.88rem;
  line-height: 1.45;
  overflow-wrap: anywhere;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.feed-card-tags {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: auto;
  padding-top: 4px;
}

.feed-card-tags .tag {
  font-size: 0.72rem;
  height: 24px;
  padding: 0 10px;
}

.feed-card-tags .tag-link {
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.feed-card-tags .tag-link:hover {
  background: rgba(188, 145, 128, 0.16);
  color: var(--accent);
}

.archive-card h3 {
  font-size: clamp(1rem, 1.6vw, 1.08rem);
  line-height: 1.24;
  hyphens: auto;
}

.archive-card p {
  -webkit-line-clamp: 3;
}

.empty-state {
  grid-column: 1 / -1;
  display: grid;
  gap: 10px;
  padding: clamp(24px, 4vw, 40px);
  border-radius: var(--radius-md);
  border: 1px solid var(--card-stroke);
  background: linear-gradient(180deg, var(--surface-strong) 0%, var(--card) 100%);
  color: var(--muted);
  font-weight: 500;
  box-shadow: var(--shadow-card);
}

.empty-state-rich {
  text-align: left;
}

.empty-state-compact {
  padding: 24px;
}

.empty-state h3,
.source-empty h2 {
  margin: 0;
  color: var(--ink);
  font-size: clamp(1rem, 1.8vw, 1.18rem);
  line-height: 1.22;
}

.empty-state p,
.source-empty p {
  max-width: 58ch;
  margin: 0;
  color: var(--muted);
  line-height: 1.58;
}

.empty-state-actions,
.source-empty-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 6px;
}

.empty-state-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 38px;
  padding: 8px 14px;
  border: 1px solid var(--card-stroke);
  border-radius: var(--radius-sm);
  background: var(--surface-inset);
  color: var(--ink);
  font: inherit;
  font-size: 0.88rem;
  font-weight: 750;
  line-height: 1.15;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease, transform 0.15s ease;
}

button.empty-state-action {
  appearance: none;
}

.empty-state-action:hover,
.empty-state-action:focus-visible {
  background: var(--card-hover);
  border-color: rgba(188, 145, 128, 0.35);
  color: var(--accent);
}

.empty-state-action--primary {
  border-color: transparent;
  background: var(--pill-active);
  color: var(--pill-active-ink);
}

.empty-state-action--primary:hover,
.empty-state-action--primary:focus-visible {
  background: var(--accent);
  color: #ffffff;
  transform: translateY(-1px);
}

/* ------- Logos ------- */
.logo {
  display: inline-grid;
  place-items: center;
  flex-shrink: 0;
  overflow: hidden;
  border: 1px solid var(--logo-border);
  background: var(--logo-bg);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
  color: var(--ink);
  font-weight: 800;
  letter-spacing: 0;
  line-height: 1;
}

.logo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.logo-sm {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  font-size: 1rem;
}

.logo-md {
  width: 52px;
  height: 52px;
  border-radius: 12px;
  font-size: 1.3rem;
}

.logo-lg {
  width: 72px;
  height: 72px;
  border-radius: 16px;
  font-size: 1.8rem;
}

/* Hero logos get a soft drop shadow so they read as a distinct surface
   above the hero glass panel. */
.hero-headline .logo {
  box-shadow:
    0 8px 20px rgba(0, 0, 0, 0.16),
    0 1px 0 rgba(255, 255, 255, 0.7) inset;
}

/* Fallback tone backgrounds — gradients tinted by beat */
.logo-fallback[data-tone="security"]  { background: linear-gradient(135deg, #ff8a9d 0%, #713a29 100%); color: #fff; border-color: rgba(255,255,255,0.7); }
.logo-fallback[data-tone="release"]   { background: linear-gradient(135deg, #8ec5ff 0%, #d6afa0 100%); color: #1a1530; }
.logo-fallback[data-tone="privacy"]   { background: linear-gradient(135deg, #713a29 0%, #8ec5ff 100%); color: #fff; }
.logo-fallback[data-tone="lightning"] { background: linear-gradient(135deg, #ffd28a 0%, #ff9ad6 100%); color: #4a1f2c; }
.logo-fallback[data-tone="nostr"]     { background: linear-gradient(135deg, #d6afa0 0%, #ff9ad6 100%); color: #2a1430; }
.logo-fallback[data-tone="ai"]        { background: linear-gradient(135deg, #2fe0c4 0%, #8ec5ff 100%); color: #0c2933; }
.logo-fallback[data-tone="research"]  { background: linear-gradient(135deg, #d6afa0 0%, #8ec5ff 100%); color: #1a1530; }
.logo-fallback[data-tone="guide"]     { background: linear-gradient(135deg, #d6afa0 0%, #8ec5ff 100%); color: #1a1530; }

/* The brief hero logo is now the Freedom.Tech mark — let it fill the
   rounded rectangle edge-to-edge, no extra padding. */
.logo img[src$="_brief.png"],
.logo img[src$="freedom-tech-logo-light.svg"] {
  background: transparent;
}

/* ------- Hero headline (logo + meta + title row) ------- */
.hero-headline {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 16px;
  align-items: center;
  margin-top: 20px;
}

.hero-headline > div {
  min-width: 0;
}

.hero-headline .hero-meta {
  margin: 4px 0 8px;
}

/* ------- Footer ------- */
.footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: clamp(28px, 4vw, 48px);
  padding: 0 6px;
  color: var(--muted);
  font-size: 0.85rem;
}

.footer a {
  color: var(--muted);
  text-decoration: none;
  font-weight: 600;
}

.footer a:hover {
  color: var(--ink);
}

.footer-brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.footer-brand-logo {
  width: 38px;
  height: 38px;
  flex: 0 0 auto;
  border-radius: 50%;
  object-fit: contain;
}

.footer-brand-text {
  white-space: nowrap;
}

.footer-brand-text a {
  color: var(--accent);
}

.footer-brand-text a:hover {
  color: var(--accent-soft);
}

.footer-stats {
  margin-left: auto;
  margin-right: 16px;
  font-variant-numeric: tabular-nums;
  font-size: 0.78rem;
  color: var(--muted);
  opacity: 0.85;
}

.footer-links {
  display: flex;
  gap: 16px;
  align-items: center;
  flex-wrap: wrap;
}

.footer-links a {
  font-size: 0.85rem;
}

/* Editor's-pick badge — shown on feed cards in `editorPicks` from
   config/editorial-overrides.json. Subtle accent ring + chip. */
.editor-pick-badge {
  display: inline-flex;
  align-items: center;
  height: 18px;
  padding: 0 8px;
  border-radius: var(--radius-pill);
  background: rgba(188, 145, 128, 0.14);
  color: var(--accent);
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.feed-card-pick {
  border-color: rgba(188, 145, 128, 0.32);
  box-shadow: var(--shadow-card), 0 0 0 2px rgba(188, 145, 128, 0.12);
}

/* /sources/ — public, browsable list of every feed the pipeline pulls
   from. Grouped by beat, sorted by tier within each beat. */
.source-actions {
  margin-top: 18px;
}

/* Search input + result count above the sources grid. Reuses the
   .search component styling from the home page topbar. Tip: pressing '/'
   anywhere on the page focuses the input (wired inline in the page). */
.source-search {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 18px;
  flex-wrap: wrap;
}

.source-search .search {
  flex: 1;
  min-width: 0;
  max-width: none;
}

.source-search-count {
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Shown when the search filter matches zero sources. */
.source-empty {
  margin-top: 24px;
  display: grid;
  gap: 10px;
  padding: clamp(22px, 4vw, 34px);
  border-radius: var(--radius-md);
  border: 1px solid var(--card-stroke);
  background: linear-gradient(180deg, var(--surface-strong) 0%, var(--card) 100%);
  box-shadow: var(--shadow-card);
}

.source-section {
  margin-top: 32px;
}

.source-section-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 12px;
}

.source-section-head h2 {
  margin: 0;
  font-size: 1.35rem;
  font-weight: 800;
  color: var(--ink);
  letter-spacing: 0;
}

.source-count {
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.source-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 12px;
  align-items: stretch;
}

.source-list > li {
  display: flex;
  height: 100%;
}

/* Search filter hides matched-out cards. The default [hidden] CSS rule
   sets display:none, but our display:flex above overrides it — so we
   need to be explicit. */
.source-list > li[hidden] {
  display: none;
}

/* Freshness chip — last-release-tracked indicator on the source card. */
.source-freshness {
  color: var(--accent, #bc9180);
  font-weight: 700;
}

/* Linked source name (clickable to project page when there's a history). */
.source-name--linked {
  text-decoration: none;
  color: inherit;
  position: relative;
  z-index: 1;
}

.source-name--linked:hover {
  text-decoration: underline;
  text-decoration-color: var(--accent, #bc9180);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}

.source-card {
  display: flex;
  flex-direction: column;
  width: 100%;
  padding: 18px 18px 16px;
  border-radius: var(--radius-md);
  border: 1px solid var(--card-stroke);
  background: var(--card);
  box-shadow: var(--shadow-card);
  color: inherit;
  text-decoration: none;
  transition: transform 120ms ease, border-color 120ms ease, box-shadow 120ms ease;
}

a.source-card:hover,
a.source-card:focus-visible {
  transform: translateY(-1px);
  border-color: var(--accent-soft, rgba(188, 145, 128, 0.4));
  box-shadow: var(--shadow-card-hover, 0 8px 24px rgba(20, 14, 50, 0.12));
  outline: none;
}

a.source-card:hover .source-name,
a.source-card:focus-visible .source-name {
  color: var(--accent);
}

.source-card-head {
  display: flex;
  align-items: center;
  gap: 14px;
}

.source-card-title {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  flex: 1;
}

.source-name {
  font-size: 1rem;
  font-weight: 700;
  color: var(--ink);
  line-height: 1.25;
  transition: color 120ms ease;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* .health-pill — small ok/fail badge in the /admin/ source-health table.
   Replaced the old .source-tier-* badges (which were repurposed for ok/
   fail rendering) when tiers were retired. */
.health-pill {
  display: inline-flex;
  align-items: center;
  height: 18px;
  padding: 0 8px;
  border-radius: var(--radius-pill);
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.health-pill-ok {
  background: rgba(47, 224, 196, 0.18);
  color: #1e7d6c;
  border: 1px solid rgba(47, 224, 196, 0.4);
}

[data-theme="dark"] .health-pill-ok {
  color: #6be5cf;
}

.health-pill-fail {
  background: rgba(255, 90, 120, 0.15);
  color: #c4324c;
  border: 1px solid rgba(255, 90, 120, 0.4);
}

[data-theme="dark"] .health-pill-fail {
  color: #ff8a9d;
}

.source-card-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.74rem;
  font-weight: 600;
  color: var(--muted);
}

.source-card-meta .sep {
  width: 10px;
  height: 1px;
  background: var(--muted);
  opacity: 0.4;
}

.source-description {
  margin: 10px 0 0;
  font-size: 0.86rem;
  line-height: 1.45;
  color: var(--ink-soft);
  /* Clamp to 2 lines so source cards converge on a uniform height
     regardless of row. Long descriptions ellipsize; the source name's
     link is the path to the full project page anyway. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Push description to the bottom of the card via flex auto-margin so the
   head sits flush at the top and descriptions align across the row. */
.source-card .source-description {
  margin-top: auto;
  padding-top: 14px;
}

/* /admin/#editorial (formerly /edit/) — local-only editorial overrides editor. Generates a JSON
   snippet for `config/editorial-overrides.json`. */
.edit-toolbar {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 18px;
  align-items: center;
}

.edit-summary {
  margin: 18px 0;
  border: 1px solid var(--card-stroke);
  border-radius: var(--radius-sm);
  padding: 10px 14px;
}

.edit-summary summary {
  cursor: pointer;
  font-size: 0.86rem;
  font-weight: 700;
  color: var(--ink);
}

.edit-summary pre {
  margin: 10px 0 0;
  padding: 12px;
  border-radius: var(--radius-sm);
  background: var(--surface-inset);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.78rem;
  line-height: 1.4;
  overflow-x: auto;
  white-space: pre;
}

.edit-table {
  width: 100%;
  margin-top: 12px;
  border-collapse: collapse;
  font-size: 0.88rem;
}

.edit-table th,
.edit-table td {
  padding: 10px 12px;
  border-bottom: 1px solid var(--line-soft);
  vertical-align: middle;
}

.edit-table th {
  text-align: left;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.edit-col-action {
  text-align: center;
  width: 96px;
}

.edit-col-title {
  width: 32%;
}

.edit-col-title input {
  width: 100%;
  height: 32px;
  padding: 0 10px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--pill-stroke);
  background: var(--pill);
  color: var(--ink);
  font: inherit;
  font-size: 0.86rem;
}

.edit-row-hidden td {
  opacity: 0.45;
}

.edit-row-meta {
  font-size: 0.72rem;
  color: var(--muted);
  margin-top: 2px;
}

.edit-table input[type="checkbox"] {
  width: 20px;
  height: 20px;
  accent-color: var(--accent);
  cursor: pointer;
}

/* /admin/#analytics (formerly /stats/) — auth-gated visitor counter table. */
.stats-controls {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 18px;
}

.stats-table {
  width: 100%;
  margin-top: 18px;
  border-collapse: collapse;
  font-size: 0.9rem;
}

.stats-table th,
.stats-table td {
  padding: 10px 12px;
  border-bottom: 1px solid var(--line-soft);
  text-align: left;
}

.stats-table th {
  font-size: 0.74rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.stats-table td a {
  color: var(--ink);
  text-decoration: none;
  font-weight: 600;
}

.stats-table td a:hover { color: var(--accent); }

.stats-table .num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
}

.stats-table tfoot td {
  border-top: 2px solid var(--card-stroke);
  border-bottom: 0;
  font-size: 0.92rem;
}

/* ---------- My List → Nostr sync modal ---------- */
/* Sync explainer card — shown ONLY on the My List view (state.filter ===
   FAVORITES_FILTER). Inserted by app.js into a dedicated slot ABOVE the
   feed-head, so it sits in the user's eyeline when they switch to My
   List. Teaches what Nostr sync is and lets the user opt in. Switches to
   a compact connected status once signed in. */
#my-list-sync-slot {
  margin-bottom: 18px;
}

.my-list-sync-card {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr) auto;
  gap: 16px;
  align-items: center;
  padding: 18px 20px;
  border-radius: var(--radius-md);
  border: 1px solid rgba(188, 145, 128, 0.32);
  background: linear-gradient(135deg, rgba(188, 145, 128, 0.08), rgba(188, 145, 128, 0.02));
  box-shadow: var(--shadow-card);
}

.my-list-sync-card--connected {
  border-color: rgba(188, 145, 128, 0.55);
  background: linear-gradient(135deg, rgba(188, 145, 128, 0.14), rgba(188, 145, 128, 0.04));
}

.my-list-sync-icon {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: rgba(188, 145, 128, 0.16);
  color: var(--accent);
}

.my-list-sync-icon svg {
  width: 20px;
  height: 20px;
}

.my-list-sync-body { min-width: 0; }

.my-list-sync-body h3 {
  margin: 0 0 4px;
  font-size: 1rem;
  font-weight: 700;
  color: var(--ink);
}

.my-list-sync-body p {
  margin: 0;
  font-size: 0.88rem;
  line-height: 1.45;
  color: var(--ink-soft);
}

.my-list-sync-body code {
  font-size: 0.85em;
  background: var(--pill);
  border: 1px solid var(--pill-stroke);
  padding: 1px 6px;
  border-radius: 4px;
  word-break: break-all;
}

.my-list-sync-cta {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 40px;
  padding: 0 18px;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: #fff;
  font: inherit;
  font-size: 0.9rem;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.15s ease, transform 0.12s ease;
}

.my-list-sync-cta:hover { background: #6a4def; }
.my-list-sync-cta:active { transform: scale(0.97); }

.my-list-sync-cta--secondary {
  background: transparent;
  border: 1px solid var(--accent);
  color: var(--accent);
}

.my-list-sync-cta--secondary:hover {
  background: rgba(188, 145, 128, 0.12);
}

@media (max-width: 640px) {
  .my-list-sync-card {
    grid-template-columns: 36px minmax(0, 1fr);
    grid-template-areas:
      "icon body"
      "cta  cta";
    padding: 16px;
    gap: 12px;
  }
  .my-list-sync-icon { grid-area: icon; width: 36px; height: 36px; }
  .my-list-sync-icon svg { width: 16px; height: 16px; }
  .my-list-sync-body { grid-area: body; }
  .my-list-sync-cta { grid-area: cta; width: 100%; }
}

/* Sync modal — same overlay framing as the search drawer. State sections
   are toggled via [data-state] + [data-show-when] attributes from JS. */
.sync-drawer {
  position: fixed;
  inset: 0;
  z-index: 120;
}

.sync-drawer[hidden] {
  display: none;
}

.sync-drawer-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(10, 8, 24, 0.72);
  opacity: 0;
  transition: opacity 0.22s ease;
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

.sync-drawer.open .sync-drawer-backdrop {
  opacity: 1;
}

.sync-drawer-sheet {
  position: absolute;
  left: 50%;
  top: 50%;
  width: min(92vw, 520px);
  max-height: min(82vh, 720px);
  overflow-y: auto;
  padding: 22px;
  /* Solid background — var(--card) is rgba(...,0.72) in dark mode which let
     the page H1 + rail cards bleed through the modal. Using fully opaque
     fallbacks per theme so the modal reads as a clear surface. */
  background: #ffffff;
  border: 1px solid var(--card-stroke);
  border-radius: var(--radius-lg);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
  transform: translate(-50%, -50%) scale(0.96);
  opacity: 0;
  transition: transform 0.22s cubic-bezier(0.2, 0.9, 0.3, 1), opacity 0.18s ease;
}

[data-theme="dark"] .sync-drawer-sheet {
  background: #1e1a36;
}

.sync-drawer.open .sync-drawer-sheet {
  transform: translate(-50%, -50%) scale(1);
  opacity: 1;
}

.sync-drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;
}

.sync-drawer-head h2 {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 800;
  color: var(--ink);
}

.sync-drawer-blurb {
  margin: 0 0 18px;
  font-size: 0.88rem;
  line-height: 1.45;
  color: var(--ink-soft);
}

.sync-drawer-blurb code {
  font-size: 0.85em;
  background: var(--pill);
  border: 1px solid var(--pill-stroke);
  padding: 1px 6px;
  border-radius: 4px;
}

/* State sections — toggled by JS setting data-state on the .sync-drawer */
[data-show-when] { display: block; }
.sync-drawer[data-state="disconnected"] [data-show-when="connecting"],
.sync-drawer[data-state="disconnected"] [data-show-when="connected"],
.sync-drawer[data-state="connecting"]   [data-show-when="disconnected"],
.sync-drawer[data-state="connecting"]   [data-show-when="connected"],
.sync-drawer[data-state="connected"]    [data-show-when="disconnected"],
.sync-drawer[data-state="connected"]    [data-show-when="connecting"] {
  display: none;
}

.sync-tabs {
  display: flex;
  gap: 6px;
  margin-bottom: 14px;
  padding: 4px;
  border-radius: var(--radius-sm);
  background: var(--pill);
  border: 1px solid var(--pill-stroke);
}

.sync-tab {
  flex: 1;
  height: 36px;
  padding: 0 12px;
  border: 0;
  background: transparent;
  border-radius: calc(var(--radius-sm) - 2px);
  color: var(--muted);
  font: inherit;
  font-size: 0.88rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;
}

.sync-tab:hover { color: var(--ink); }

/* Active state — accent purple background with white text so the
   selected tab is unmistakable. The previous styling used var(--card)
   which is nearly identical to var(--pill) (the tabstrip background)
   in dark mode, leaving the two tabs visually almost-equal. */
.sync-tab[aria-selected="true"] {
  background: var(--accent);
  color: #fff;
  box-shadow: 0 2px 8px rgba(188, 145, 128, 0.32);
}

.sync-tab[aria-selected="true"]:hover {
  color: #fff;
}

.sync-tab-panel {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.sync-tab-panel[hidden] {
  display: none;
}

.sync-input-label {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--ink-soft);
}

#sync-bunker-uri {
  width: 100%;
  padding: 10px 12px;
  background: var(--pill);
  border: 1px solid var(--pill-stroke);
  border-radius: var(--radius-sm);
  color: var(--ink);
  font: inherit;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.85rem;
  resize: vertical;
  min-height: 64px;
}

#sync-bunker-uri:focus {
  outline: none;
  border-color: rgba(188, 145, 128, 0.55);
}

.sync-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 42px;
  padding: 0 18px;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: #fff;
  font: inherit;
  font-size: 0.92rem;
  font-weight: 700;
  cursor: pointer;
  transition: background 0.15s ease, transform 0.12s ease;
}

.sync-primary:hover { background: #6a4def; }
.sync-primary:active { transform: scale(0.98); }
.sync-primary:disabled { opacity: 0.55; cursor: not-allowed; }

.sync-primary-spinner,
.sync-spinner-large {
  display: inline-block;
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-top-color: #fff;
  border-radius: 50%;
  animation: sync-spin 0.8s linear infinite;
}

.sync-primary-spinner[hidden],
.sync-spinner-large[hidden] {
  display: none;
}

.sync-primary-spinner { width: 14px; height: 14px; }
.sync-spinner-large { width: 32px; height: 32px; margin: 0 auto 14px; border-color: rgba(188, 145, 128, 0.3); border-top-color: var(--accent); }

@keyframes sync-spin { to { transform: rotate(360deg); } }

.sync-hint {
  margin: 0;
  font-size: 0.82rem;
  line-height: 1.4;
  color: var(--muted);
}

.sync-connecting {
  text-align: center;
  padding: 14px 0;
}

.sync-status-message {
  margin: 0 0 6px;
  font-weight: 700;
  color: var(--ink);
}

.sync-status-list {
  display: grid;
  gap: 10px;
  margin: 0 0 18px;
}

.sync-status-list > div {
  display: grid;
  grid-template-columns: 90px 1fr;
  align-items: baseline;
  gap: 10px;
}

.sync-status-list dt {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.sync-status-list dd {
  margin: 0;
  font-size: 0.9rem;
  color: var(--ink);
}

.sync-status-list code {
  font-size: 0.82rem;
  word-break: break-all;
}

.sync-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.sync-secondary {
  display: inline-flex;
  align-items: center;
  height: 38px;
  padding: 0 14px;
  border-radius: var(--radius-sm);
  background: var(--pill);
  border: 1px solid var(--pill-stroke);
  color: var(--ink);
  font: inherit;
  font-size: 0.88rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.sync-secondary:hover { background: var(--card-hover); border-color: rgba(188, 145, 128, 0.32); }

.sync-secondary--danger {
  color: #c64f6e;
  border-color: rgba(198, 79, 110, 0.32);
}

.sync-secondary--danger:hover {
  background: rgba(198, 79, 110, 0.10);
  border-color: rgba(198, 79, 110, 0.55);
}

.sync-error {
  margin: 14px 0 0;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  background: rgba(198, 79, 110, 0.12);
  border: 1px solid rgba(198, 79, 110, 0.32);
  color: #d77a92;
  font-size: 0.85rem;
  line-height: 1.4;
}

/* Mobile search drawer — top sheet that slides down when the search-
   trigger icon in the topbar is tapped. Contains the real input which
   mirrors to #search via app.js so the existing filter pipeline drives
   everything. Hidden by default; opened by JS. */
.search-drawer {
  position: fixed;
  inset: 0;
  z-index: 110;
}

.search-drawer[hidden] {
  display: none;
}

.search-drawer-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(10, 8, 24, 0.72);
  opacity: 0;
  transition: opacity 0.22s ease;
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

.search-drawer.open .search-drawer-backdrop {
  opacity: 1;
}

/* Centered modal — true overlay positioned dead-center of the viewport
   so it reads as a focused dialog rather than a leaky top-sheet. The
   backdrop above carries the dim + blur for the rest of the screen. */
.search-drawer-sheet {
  position: absolute;
  left: 50%;
  top: 50%;
  width: min(92vw, 460px);
  padding: 18px;
  background: var(--card);
  border: 1px solid var(--card-stroke);
  border-radius: var(--radius-lg);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
  transform: translate(-50%, -50%) scale(0.96);
  opacity: 0;
  transition: transform 0.22s cubic-bezier(0.2, 0.9, 0.3, 1), opacity 0.18s ease;
}

.search-drawer.open .search-drawer-sheet {
  transform: translate(-50%, -50%) scale(1);
  opacity: 1;
}

.search-drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}

.search-drawer-head h2 {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 800;
  color: var(--ink);
}

.search-drawer-close {
  display: inline-grid;
  place-items: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border-radius: 50%;
  border: 1px solid var(--pill-stroke);
  background: var(--pill);
  color: var(--ink);
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.search-drawer-close:hover,
.search-drawer-close:focus-visible {
  background: var(--card-hover);
  border-color: rgba(188, 145, 128, 0.32);
  outline: none;
}

.search-drawer-close svg {
  width: 14px;
  height: 14px;
  display: block;
}

.search-drawer-field {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 48px;
  padding: 0 14px;
  border-radius: var(--radius-sm);
  background: var(--pill);
  border: 1px solid var(--pill-stroke);
}

.search-drawer-field:focus-within {
  border-color: rgba(188, 145, 128, 0.32);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.14);
}

.search-drawer-field .search-icon {
  width: 18px;
  height: 18px;
  color: var(--muted);
  flex-shrink: 0;
}

.search-drawer-field input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 1rem;
  outline: none;
}

.search-drawer-field input::placeholder {
  color: var(--muted);
}

/* Mobile filter drawer — bottom sheet that opens when the "Filter" button
   in the mobile nav is tapped. Hidden on desktop. */
.filter-drawer {
  position: fixed;
  inset: 0;
  z-index: 100;
}

.filter-drawer[hidden] {
  display: none;
}

.filter-drawer-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(20, 17, 40, 0.55);
  opacity: 0;
  transition: opacity 0.22s ease;
}

.filter-drawer.open .filter-drawer-backdrop {
  opacity: 1;
}

.filter-drawer-sheet {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  max-height: 80vh;
  overflow-y: auto;
  padding: 18px 18px calc(28px + env(safe-area-inset-bottom, 0px));
  border-top-left-radius: var(--radius-lg);
  border-top-right-radius: var(--radius-lg);
  background: var(--card);
  border-top: 1px solid var(--card-stroke);
  box-shadow: 0 -16px 40px rgba(0, 0, 0, 0.18);
  transform: translateY(100%);
  transition: transform 0.22s cubic-bezier(0.2, 0.9, 0.3, 1);
}

.filter-drawer.open .filter-drawer-sheet {
  transform: translateY(0);
}

.filter-drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}

.filter-drawer-head h2 {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 800;
  color: var(--ink);
}

.filter-drawer-close {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid var(--pill-stroke);
  background: var(--pill);
  color: var(--ink);
  font-size: 1.2rem;
  line-height: 1;
  cursor: pointer;
}

.filter-drawer-section {
  margin-top: 12px;
}

.filter-drawer-section h3 {
  margin: 0 0 8px;
  font-size: 0.74rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.filter-drawer-options {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.filter-drawer-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  height: 48px;
  padding: 0 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--pill-stroke);
  background: var(--pill);
  color: var(--ink);
  font: inherit;
  font-size: 0.95rem;
  font-weight: 600;
  cursor: pointer;
  text-align: left;
}

.filter-drawer-option[aria-checked="true"] {
  background: var(--pill-active);
  border-color: var(--pill-active);
  color: var(--pill-active-ink);
}

.filter-drawer-check {
  font-weight: 800;
}

/* Mobile-only sticky quick-action bar — hidden on desktop. iOS safe-area
   inset so it sits cleanly above the home-bar. */
/* .scroll-top — floating "back to top" FAB. Replaces the old 4-tab mobile
   bottom bar (it consumed too much viewport real estate for the value).
   Hidden by default via the `hidden` attribute; JS removes that after the
   user scrolls past 400px. Mobile-only via media query — desktop never
   shows it. */
.scroll-top {
  display: none;
}

@media (max-width: 640px) {
  .scroll-top {
    position: fixed;
    bottom: calc(16px + env(safe-area-inset-bottom, 0px));
    right: 16px;
    z-index: 50;
    width: 44px;
    height: 44px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--card-stroke);
    background: rgba(255, 255, 255, 0.92);
    backdrop-filter: blur(14px) saturate(1.2);
    -webkit-backdrop-filter: blur(14px) saturate(1.2);
    color: var(--accent);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.22);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 160ms ease, transform 160ms ease;
    align-items: center;
    justify-content: center;
  }

  .scroll-top:not([hidden]) {
    display: flex;
  }

  .scroll-top.is-visible {
    opacity: 1;
    transform: translateY(0);
  }

  [data-theme="dark"] .scroll-top {
    background: rgba(22, 18, 42, 0.92);
    border-color: rgba(255, 255, 255, 0.22);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.42);
  }

  .scroll-top:active {
    transform: scale(0.95);
  }
}

/* ------- Per-post page ------- */
.post-page {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(20px, 3vw, 32px);
  padding: 0;
}

.post-article {
  max-width: 760px;
  margin: 0 auto;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: clamp(20px, 3vw, 28px);
}

@media (min-width: 980px) {
  .post-article {
    max-width: none;
  }
}

/* Main article content sits on its own card surface, matching the tip-jar
   and primary-sources styling — keeps the visual hierarchy consistent. */
.post-card {
  padding: clamp(24px, 3vw, 40px);
  border-radius: var(--radius-md);
  border: 1px solid var(--card-stroke);
  background: var(--card);
  box-shadow: var(--shadow-card);
}

.post-card .hero-headline {
  margin-top: 0;
}

.post-card .post-summary {
  margin-bottom: 28px;
}

.post-card .post-body :last-child {
  margin-bottom: 0;
}

/* Release context block. Two variants:
   - .release-context--fallback: shown in place of an empty/noise release
     body. Has prominent project description + explicit "no notes" copy.
   - .release-context--footer: shown beneath real release notes as a
     compact "Release context" footer with cadence and external links. */
.release-context {
  border: 1px solid rgba(188, 145, 128, 0.18);
  background: rgba(188, 145, 128, 0.04);
  border-radius: var(--radius-sm);
  padding: 18px 20px;
}

.release-context--fallback {
  margin-top: 4px;
}

.release-context--footer {
  margin-top: 32px;
  padding: 16px 20px;
  background: rgba(188, 145, 128, 0.03);
}

:root:not([data-theme="dark"]) .release-context {
  border-color: var(--card-stroke);
  background:
    linear-gradient(145deg, rgba(255, 255, 255, 0.42) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.06) 100%),
    var(--card);
  box-shadow: var(--shadow-card);
  backdrop-filter: blur(6px) saturate(1.22) contrast(1.04);
  -webkit-backdrop-filter: blur(6px) saturate(1.22) contrast(1.04);
}

:root:not([data-theme="dark"]) .release-context--footer {
  background:
    linear-gradient(145deg, rgba(255, 255, 255, 0.34) 0%, rgba(255, 255, 255, 0.12) 52%, rgba(255, 255, 255, 0.05) 100%),
    var(--card);
}

.release-context > * {
  margin: 0 0 12px;
}

.release-context > :last-child {
  margin-bottom: 0;
}

/* Specificity-bumped so `.post-body h2` (font-size:1.45rem, margin:36px 0 14px)
   doesn't win. Without `.post-body` qualifier, the chunky default h2 styles
   bleed through and the eyebrow becomes a 1.45rem heading with a 36px gap
   above — visible as a giant "RELEASE CONTEXT" header floating in whitespace
   inside the context footer block. */
.post-body .release-context-heading,
.release-context-heading {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 12px;
}

.release-context-desc {
  font-size: 1rem;
  line-height: 1.55;
  color: var(--ink);
}

.release-context-note {
  color: var(--muted);
  font-size: 0.92rem;
  line-height: 1.5;
}

.release-context-links a {
  font-weight: 600;
}

.release-context-cadence {
  color: var(--muted);
  font-size: 0.88rem;
}

.release-context-cadence .muted {
  opacity: 0.8;
}

[data-theme="dark"] .release-context {
  border-color: rgba(255, 255, 255, 0.2);
  background: rgba(255, 255, 255, 0.03);
}

[data-theme="dark"] .release-context--footer {
  background: rgba(255, 255, 255, 0.02);
}

/* "Filed under" — discoverability row at the foot of a release post.
   Compact beat + tag chips that link into the matching archive pages. */
.filed-under {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 28px;
  padding-top: 22px;
  border-top: 1px solid var(--line-soft);
}

.filed-under-label {
  font-size: 0.74rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.filed-under-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.filed-under-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 28px;
  padding: 0 12px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--pill-stroke);
  background: var(--pill);
  color: var(--ink-soft);
  text-decoration: none;
  font-size: 0.78rem;
  font-weight: 600;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.filed-under-chip:hover,
.filed-under-chip:focus-visible {
  background: var(--card-hover);
  border-color: rgba(188, 145, 128, 0.32);
  color: var(--ink);
  outline: none;
}

.filed-under-chip-beat {
  color: var(--accent);
  background: rgba(188, 145, 128, 0.10);
  border-color: rgba(188, 145, 128, 0.22);
  font-weight: 700;
}

.filed-under-chip-beat:hover,
.filed-under-chip-beat:focus-visible {
  background: rgba(188, 145, 128, 0.18);
  border-color: rgba(188, 145, 128, 0.36);
  color: var(--accent);
}

.filed-under-chip-project {
  font-weight: 700;
}

/* "Read next" — related posts widget at the foot of a release/advisory
   detail page. 1-3 sibling cards drawn from same product or beat. */
.related {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.related-title {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 800;
  color: var(--ink);
  letter-spacing: 0;
}

.related-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
  gap: 12px;
}

@media (min-width: 720px) {
  .related-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.related-card {
  display: grid;
  grid-template-columns: 48px minmax(0, 1fr);
  gap: 12px;
  align-items: center;
  padding: 14px 16px;
  border-radius: var(--radius-md);
  border: 1px solid var(--card-stroke);
  background: var(--card);
  box-shadow: var(--shadow-card);
  text-decoration: none;
  color: var(--ink);
  transition: transform 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

.related-card:hover,
.related-card:focus-visible {
  transform: translateY(-1px);
  border-color: rgba(188, 145, 128, 0.32);
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.16);
  outline: none;
}

.related-card .logo { width: 48px; height: 48px; }

.related-card-body { min-width: 0; }

.related-card-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 600;
  margin-bottom: 4px;
}

.related-card-meta .sep {
  width: 10px;
  height: 1px;
  background: var(--muted);
  opacity: 0.4;
}

.related-card h3 {
  margin: 0;
  font-size: 0.92rem;
  line-height: 1.25;
  font-weight: 700;
  color: var(--ink);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
}

.post-back {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 42px;
  margin-bottom: 24px;
  padding: 0 14px 0 10px;
  border-radius: var(--radius-sm);
  background: var(--pill);
  border: 1px solid var(--pill-stroke);
  color: var(--ink-soft);
  text-decoration: none;
  font-size: 0.85rem;
  font-weight: 600;
}

.post-back:hover {
  background: var(--card-hover);
  color: var(--ink);
}

.post-article h1 {
  margin: 14px 0 18px;
  font-size: clamp(1.85rem, 3.4vw, 2.8rem);
  line-height: 1.1;
  letter-spacing: 0;
  font-weight: 800;
  overflow-wrap: anywhere;
}

.hero h1 {
  overflow-wrap: anywhere;
}

.post-summary {
  margin: 0 0 28px;
  color: var(--ink-soft);
  font-size: clamp(1rem, 1.4vw, 1.15rem);
  line-height: 1.55;
}

.post-body {
  color: var(--ink-soft);
  font-size: 1rem;
  line-height: 1.65;
}

.post-body h2 {
  margin: 36px 0 14px;
  font-size: 1.45rem;
  font-weight: 700;
  color: var(--ink);
  letter-spacing: 0;
}

.post-body h3 {
  margin: 28px 0 10px;
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--ink);
}

.post-body p {
  margin: 0 0 16px;
}

.post-body ul {
  margin: 0 0 20px;
  padding: 0 0 0 20px;
}

.post-body li {
  margin: 6px 0;
}

.post-body ol {
  margin: 0 0 20px;
  padding: 0 0 0 22px;
}

.post-body code {
  padding: 0.12em 0.38em;
  border-radius: 6px;
  border: 1px solid var(--line-soft);
  background: var(--pill);
  color: var(--ink);
  font-family: "SFMono-Regular", "SF Mono", Consolas, "Liberation Mono", monospace;
  font-size: 0.9em;
}

.post-body pre {
  margin: 18px 0 22px;
  padding: 16px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--card-stroke);
  background: var(--pill);
  color: var(--ink);
  overflow-x: auto;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
}

.post-body pre code {
  display: block;
  padding: 0;
  border: 0;
  background: transparent;
  font-size: 0.88rem;
  line-height: 1.6;
  white-space: pre;
}

.post-body blockquote {
  margin: 18px 0 22px;
  padding: 12px 16px;
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  background: var(--pill);
  color: var(--ink-soft);
}

.post-body blockquote p {
  margin: 0;
}

.post-body a {
  color: var(--accent);
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px solid rgba(188, 145, 128, 0.3);
  overflow-wrap: anywhere;
}

.post-body a:hover {
  border-bottom-color: var(--accent);
}

.post-sources {
  padding: 24px 26px;
  border-radius: var(--radius-md);
  border: 1px solid var(--card-stroke);
  background: var(--card);
  box-shadow: var(--shadow-card);
}

.post-sources h2 {
  margin: 0 0 14px;
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent);
}

.post-sources ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 10px;
}

.post-sources li {
  padding-top: 10px;
  border-top: 1px solid var(--line-soft);
}

.post-sources li:first-child {
  border-top: 0;
  padding-top: 0;
}

.post-sources a {
  color: var(--ink);
  font-size: 0.92rem;
  font-weight: 600;
  text-decoration: none;
  overflow-wrap: anywhere;
}

.post-sources a:hover {
  color: var(--accent);
}

/* ------- Share + tip on per-post pages ------- */
.share-control {
  position: relative;
  display: inline-block;
}

.share-primary {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 42px;
  padding: 0 16px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--pill-stroke);
  background: var(--pill);
  color: var(--ink);
  font: inherit;
  font-size: 0.88rem;
  font-weight: 700;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}

.share-primary:hover,
.share-primary:focus-visible {
  background: var(--card-hover);
  border-color: rgba(188, 145, 128, 0.32);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.14);
  transform: translateY(-1px);
  outline: none;
}

.share-menu {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 30;
  display: grid;
  min-width: 200px;
  padding: 6px;
  gap: 2px;
  border-radius: var(--radius-md);
  border: 1px solid var(--card-stroke);
  background: var(--menu-bg);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  box-shadow: 0 14px 32px rgba(0, 0, 0, 0.22);
}

.share-menu[hidden] { display: none; }

.share-menu-item {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  border: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 0.88rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  width: 100%;
  text-align: left;
  transition: background 0.12s ease;
}

.share-menu-item:hover,
.share-menu-item:focus-visible {
  background: var(--card-hover);
  outline: none;
}

.tip-jar {
  display: grid;
  gap: 12px;
  padding: 22px 24px;
  border-radius: var(--radius-md);
  border: 1px solid var(--card-stroke);
  background: var(--card);
  box-shadow: var(--shadow-card);
}

.tip-jar header h2 {
  margin: 0 0 4px;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--ink);
}

.tip-jar header p {
  margin: 0 0 4px;
  color: var(--ink-soft);
  font-size: 0.92rem;
  line-height: 1.45;
}

.tip-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.tip-row-value {
  flex: 1;
  min-width: 0;
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--pill-stroke);
  background: var(--surface-inset);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.9rem;
  color: var(--ink);
  overflow-x: auto;
  white-space: nowrap;
}

.tip-hint {
  margin: 4px 0 0;
  font-size: 0.8rem;
  color: var(--muted);
}

.tip-copy,
.tip-link {
  display: inline-flex;
  align-items: center;
  height: 44px;
  padding: 0 16px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--pill-stroke);
  background: var(--pill);
  color: var(--ink);
  font: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  cursor: pointer;
  text-decoration: none;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.tip-copy:hover,
.tip-link:hover {
  background: var(--card-hover);
  border-color: rgba(188, 145, 128, 0.32);
}

/* ------- Responsive ------- */
@media (max-width: 980px) {
  .hero {
    grid-template-columns: 1fr;
    min-height: auto;
  }

  /* On mobile My List view, the "Shipping the most this week" rail
     section pushes other projects into a "your projects" surface where
     it doesn't belong. Other rail sections (security patches, hot in
     24h) still make sense as ecosystem context, so just this one is
     hidden. Desktop keeps it.
     The second rule handles the degenerate case where shipped is the
     only section: without it the rail container still renders its
     border-top + padding-top as a visible empty band. */
  body.view-favorites .rail-section--shipped {
    display: none;
  }

  body.view-favorites .rail:not(:has(.rail-section:not(.rail-section--shipped))) {
    display: none;
  }

  .rail {
    border-top: 1px solid var(--line-soft);
    padding-top: 18px;
  }

  .rail::before {
    inset: 8px 0 0;
  }

  .feed-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .topbar {
    grid-template-columns: 1fr;
  }

  .topbar-actions {
    width: 100%;
  }

  .search {
    flex: 1;
    max-width: none;
    min-width: 0;
  }

  .pill-nav {
    overflow-x: auto;
    flex-wrap: nowrap;
    margin: 0 -16px;
    padding: 2px 16px;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    /* Soft right-edge fade hint that more pills exist off-screen. */
    mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 28px), transparent 100%);
    -webkit-mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 28px), transparent 100%);
  }

  .pill-nav button,
  .pill-nav a {
    flex-shrink: 0;
  }

  .pill-nav::-webkit-scrollbar {
    display: none;
  }
}

@media (max-width: 640px) {
  .glass-frame {
    padding: clamp(14px, 4vw, 22px);
  }

  /* Phone-only topbar layout: brand on the left, search + theme toggle on
     the right of the SAME row, filter pills wrap underneath. Saves a full
     row of vertical real estate vs. the tablet stacked layout above. */
  .topbar {
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
      "brand   actions"
      "pills   pills";
    row-gap: 10px;
    column-gap: 10px;
  }

  .brand {
    grid-area: brand;
    padding: 0;
    font-size: 0.85rem;
  }

  .topbar-actions {
    grid-area: actions;
    justify-self: end;
    width: auto;
    min-width: 0;
    gap: 8px;
  }

  .pill-nav {
    grid-area: pills;
  }

  /* Replace the inline search field with an icon-only trigger that's the
     same shape and size as the theme toggle. Tapping it opens the search
     drawer (see #search-drawer). */
  .topbar .search {
    display: none;
  }

  .topbar .search-trigger {
    display: grid;
    width: 38px;
    height: 38px;
    flex: 0 0 38px;
  }

  .topbar .theme-toggle {
    width: 38px;
    height: 38px;
    flex: 0 0 38px;
  }

  .pill-nav {
    margin: 0;
    padding: 2px 0;
  }

  .feed-grid {
    grid-template-columns: 1fr;
  }

  .hero {
    gap: 16px;
  }

  .hero-copy {
    gap: 18px;
    padding: 0;
  }

  .hero-panel {
    width: 100%;
    max-width: 100%;
    padding: 14px;
    overflow: hidden;
  }

  /* Hero headline reflow — logo top-right, title block left.
     The default mobile layout stacked the logo above the title block which
     wasted vertical space and pushed the headline below the fold on phones.
     This puts both in a single row, logo small + right-anchored, title
     block taking the rest. */
  .hero-headline {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    gap: 12px;
    margin-top: 14px;
  }

  .hero-headline > div {
    flex: 1;
    min-width: 0;
    order: 0;
  }

  .hero-headline .logo {
    order: 1;
    flex-shrink: 0;
  }

  .hero-headline .logo.logo-lg {
    width: 48px;
    height: 48px;
    border-radius: 12px;
    font-size: 1.3rem;
  }

  .hero-headline .hero-meta {
    margin-top: 0;
  }

  /* Home-page hero specifically — keep the logo in the title row on
     phones. The previous absolute-positioned treatment saved a little
     height, but it made longer headlines run underneath the logo. */
  .hero-panel .hero-headline {
    display: flex;
    align-items: flex-start;
    margin-top: 12px;
    gap: 12px;
  }

  .hero-panel .hero-headline .logo {
    position: static;
    margin: 0;
  }

  .hero-panel .hero-headline .logo.logo-lg {
    width: 52px;
    height: 52px;
    border-radius: 12px;
  }

  .hero-panel .eyebrow {
    margin-right: 0;
  }

  .hero-panel .hero-topline {
    margin-right: 0;
    min-height: 0;
  }

  .hero-panel .hero-topline .eyebrow {
    margin-right: 0;  /* topline handles the right clearance now */
  }

  /* Trim a few pixels off the meta on mobile so the text doesn't sit
     directly against the logo's glow halo. The logo box ends 14px to
     the right of the meta's right edge already, but the logo's
     box-shadow extends inward — this padding compensates. */
  .hero-panel .hero-topline .hero-meta {
    padding-right: 6px;
  }

  .hero-panel .hero-headline > div { padding-right: 0; }

  .hero h1 {
    font-size: 1.48rem;
    line-height: 1.1;
  }

  .hero .post-summary {
    font-size: 0.95rem;
    width: auto;
    max-width: none;
    white-space: normal;
  }

  .hero .post-summary span {
    width: auto;
    max-width: 100%;
    white-space: normal;
  }

  .hero-signals {
    gap: 6px;
    margin-top: 14px;
  }

  .hero-signal {
    flex: 1 1 100%;
    justify-content: flex-start;
    min-width: 0;
  }

  .hero-actions {
    align-items: flex-start;
    margin-top: 14px;
  }

  .hero-source-note {
    width: 100%;
  }

  .cta {
    height: 44px;
    padding: 0 18px 0 20px;
    font-size: 0.9rem;
  }

  .feed-head {
    gap: 8px;
  }

  /* Mobile rail-list: column-stacked, same as desktop. The old design used a
     horizontal-scroll snap strip — that was tuned for a single "Latest
     releases" rail. The new multi-section rail ("Most shipped this week" +
     "Security patches" + "Hot in last 24h") would have produced three
     independent horizontal strips with no visible scroll indicators and
     cards cut off off-screen. Stacking vertically is honest and obvious. */
  .rail-list {
    flex-direction: column;
    gap: 10px;
  }

  .rail-list li {
    width: 100%;
  }

  .rail-card {
    height: 100%;
    grid-template-columns: 48px minmax(0, 1fr);
    gap: 10px;
    padding: 10px 12px;
  }

  /* Shrink the thumb so the meta + title have room on a narrow snap card. */
  .rail-card .rail-thumb,
  .rail-card .logo {
    width: 48px;
    height: 48px;
  }

  /* Meta in the carousel cards was breaking text word-by-word; stack it
     vertically so each line truncates cleanly. */
  .rail-card-meta {
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    min-width: 0;
    font-size: 0.72rem;
  }

  .rail-card-meta > span:not(.sep) {
    min-width: 0;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .rail-card-meta .sep {
    display: none;
  }

  .rail-card h4 {
    font-size: 0.9rem;
  }

  /* Post page — tighten the meta strip so the dash separators don't wrap mid-line. */
  .post-page {
    padding: 0;
  }

  .post-article h1 {
    font-size: 1.5rem;
  }

  .hero-headline .logo.logo-md,
  .post-article .hero-headline .logo {
    width: 48px;
    height: 48px;
    border-radius: 12px;
  }

  .hero-meta {
    flex-wrap: wrap;
    gap: 6px 10px;
    font-size: 0.78rem;
  }

  .hero-meta .sep {
    display: none;
  }

  .post-summary {
    font-size: 0.98rem;
  }

  .post-body {
    font-size: 0.96rem;
  }

  .post-sources {
    padding: 18px 18px;
  }

  /* Tip jar — make the address row stack so the email never gets clipped. */
  .tip-jar {
    padding: 18px 18px;
  }

  .tip-row {
    gap: 8px;
  }

  .tip-row-value {
    flex: 1 1 100%;
    min-width: 0;
    text-align: center;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .tip-link,
  .tip-copy {
    flex: 1 1 calc(50% - 4px);
    justify-content: center;
  }

  .footer {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
  }

  .footer-stats {
    margin-left: 0;
    margin-right: 0;
  }

  .footer-links {
    gap: 8px 12px;
  }

  .footer-links a {
    display: inline-flex;
    align-items: center;
    min-height: 36px;
  }

  .source-name {
    white-space: normal;
    overflow-wrap: anywhere;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
  }

  /* Archive header inside a glass frame should not feel cramped. */
  .post-page .post-summary {
    margin-bottom: 18px;
  }
}

@media (max-width: 820px) {
  .footer {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
  }

  .footer-brand {
    flex-shrink: 0;
  }

  .footer-stats {
    margin-left: 0;
    margin-right: 0;
  }
}

@media (max-width: 480px) {
  .post-article .hero-headline {
    grid-template-columns: 1fr;
    gap: 12px;
  }

  .post-article .hero-headline .logo {
    justify-self: start;
  }

  .post-article .hero-headline .hero-meta {
    margin-top: 0;
  }
}

/* .editorial-lead — paragraph generated by scripts/editor.mjs that frames
   what today's brief is about. Renders between the post summary and the
   markdown body on brief detail pages. Visually distinct (italic, accent-
   tinted left border) so readers can tell the editorial layer apart from
   the source-driven summary line above. */
.editorial-lead {
  margin-top: 18px;
  padding: 14px 18px;
  border-left: 3px solid var(--accent);
  background: linear-gradient(90deg, rgba(188, 145, 128, 0.06), rgba(46, 224, 196, 0.0));
  border-radius: 4px;
}

.editorial-lead p {
  margin: 0;
  font-size: 1.02rem;
  line-height: 1.55;
  font-style: italic;
  color: var(--ink);
}

/* .nostr-discuss — "Discuss on Nostr" callout on published brief pages.
   Surfaces a clear path off the static page into the user's preferred Nostr
   client so replies and zaps land on the protocol, not the site. */
.nostr-discuss {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 14px;
  margin-top: 18px;
  padding: 14px 16px;
  border-radius: var(--radius-md);
  border: 1px solid var(--pill-stroke);
  background: linear-gradient(135deg, rgba(188, 145, 128, 0.06), rgba(46, 224, 196, 0.06));
  color: var(--ink);
}

.nostr-discuss > svg {
  color: var(--accent);
}

.nostr-discuss strong {
  display: block;
  font-size: 0.95rem;
  font-weight: 800;
  color: var(--ink);
}

.nostr-discuss p {
  margin: 2px 0 0;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--ink-soft);
}

.nostr-discuss .cta {
  white-space: nowrap;
  height: 38px;
  font-size: 0.85rem;
}

@media (max-width: 560px) {
  .nostr-discuss {
    grid-template-columns: auto 1fr;
  }
  .nostr-discuss .cta {
    grid-column: 1 / -1;
    justify-self: stretch;
  }
}

/* /admin/ — unified admin dashboard. Tabs, stat cards, panel layout. */
.admin-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 18px;
  padding: 4px;
  background: var(--pill-bg);
  border: 1px solid var(--pill-stroke);
  border-radius: var(--radius-pill);
}

.admin-tab {
  appearance: none;
  background: transparent;
  border: 0;
  color: var(--muted);
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  padding: 8px 14px;
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}

.admin-tab:hover {
  color: var(--ink);
}

.admin-tab.is-active {
  background: var(--card);
  color: var(--ink);
  box-shadow: 0 1px 4px rgba(20, 14, 50, 0.08);
}

.admin-panel {
  margin-top: 18px;
}

.admin-panel h2 {
  font-size: 1.15rem;
  font-weight: 800;
  color: var(--ink);
  letter-spacing: 0;
}

.admin-panel h3 {
  font-size: 0.95rem;
  font-weight: 800;
  color: var(--ink);
  letter-spacing: 0;
}

.admin-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 10px;
  margin-top: 14px;
}

.admin-stat {
  padding: 14px 16px;
  border-radius: var(--radius-md);
  border: 1px solid var(--card-stroke);
  background: var(--card);
  box-shadow: var(--shadow-card);
}

.admin-stat-label {
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

.admin-stat-value {
  margin-top: 4px;
  font-size: 1.6rem;
  font-weight: 800;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}

.admin-stat-sub {
  margin-top: 4px;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--muted);
}

#admin-login .stats-controls {
  margin-top: 18px;
}

/* ---- Mobile responsive fixes (batched) -------------------------------- */

/* Default: long form of back-link / project-link is visible, short form hidden.
   Flip below 700px so the nav row never wraps onto two lines. */
.post-back-short { display: none; }
.post-back-long  { display: inline; }

@media (max-width: 700px) {
  .post-back-long  { display: none; }
  .post-back-short { display: inline; }

  /* Tighter gap below 700px so the nav row doesn't wrap when both back +
     project links + share + theme toggle are visible. Heights are already
     pinned at 42px (matching the theme toggle) — see .post-back and
     .share-primary. */
  .post-back {
    gap: 6px;
  }

  .post-nav-row {
    gap: 8px;
  }

  .post-nav-actions {
    gap: 8px;
  }
}

/* Related-card grid — auto-fit was letting two narrow cards squeeze side-
   by-side on phones, which clipped the badge + date meta row. Force a
   single column below 720px. */
@media (max-width: 720px) {
  .related-grid {
    grid-template-columns: 1fr;
  }
}

/* Long URLs (e.g. release changelog links to github.com/.../compare/v0.23.x)
   need to wrap, not overflow the post-body column on narrow screens. */
.post-body {
  overflow-wrap: anywhere;
  word-break: break-word;
}

.post-body a {
  overflow-wrap: anywhere;
  word-break: break-word;
}

/* Force long inline code (URLs, hashes) to wrap on mobile too. */
@media (max-width: 640px) {
  .post-body code,
  .post-body pre {
    overflow-wrap: anywhere;
    word-break: break-word;
    white-space: pre-wrap;
  }
}
