/* ==========================================================================
   CRYPTOREAL NEWS — DESIGN SYSTEM
   "Forensic intelligence desk" — ink-navy base, mono data layer, risk index.
   No build step. Plain CSS + custom properties. Mobile-first.
   Section index:
     1.  Font faces (self-hosted)
     2.  Tokens — dark theme (default) + light theme override
     3.  Reset / base element rules
     4.  Typography primitives (display, body, mono, eyebrow)
     5.  Layout (container, grid, section rhythm)
     6.  Header / nav / theme toggle
     7.  Footer (masthead, disclaimer, legal)
     8.  Buttons
     9.  Forms + consent
     10. Tags / eyebrows / status / risk badge / sponsored label
     11. Risk Index meter (signature device)
     12. Case-file / dossier strip
     13. Article cards (hero / standard / compact)
     14. Ledger / leaderboard
     15. Callouts (redflag / tip) + pullquote
     16. Byline / timestamp / amount mono helpers
     17. Breadcrumbs / pagination
     18. CTA band / lead strip
     19. Reveal + motion utilities
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. FONT FACES — self-hosted, woff2, font-display: swap
   Files live in assets/fonts/. Variable-font sources are reused across the
   static weights Google serves them under (identical bytes, different
   declared weight) — this is expected, not a mistake.
   -------------------------------------------------------------------------- */
@font-face {
  font-family: "Bricolage Grotesque";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("fonts/bricolage-grotesque-700.woff2") format("woff2");
}
@font-face {
  font-family: "Bricolage Grotesque";
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url("fonts/bricolage-grotesque-800.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/ibm-plex-sans-400.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/ibm-plex-sans-500.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("fonts/ibm-plex-sans-600.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/ibm-plex-mono-500.woff2") format("woff2");
}

/* --------------------------------------------------------------------------
   2. TOKENS
   -------------------------------------------------------------------------- */
:root {
  /* -- surfaces / text (dark, default) -- */
  --ink: #090c14;
  --ink-2: #10151f;
  --ink-3: #171e2b;
  --ink-4: #1e2635;
  --line: #232c3d;
  --text: #eaeef6;
  --text-dim: #8a94a9;

  /* -- signal system (colour = meaning) -- */
  --brand: #37d6a8;
  --brand-strong: #59e6bd;
  --brand-dim: rgba(55, 214, 168, 0.12);
  --warn: #f5b841;
  --warn-dim: rgba(245, 184, 65, 0.12);
  --danger: #f5544e;
  --danger-dim: rgba(245, 84, 78, 0.12);

  /* -- on-brand text (buttons filled with signal colours) -- */
  --on-brand: #04140f;
  --on-warn: #1a1102;
  --on-danger: #260605;

  /* -- type -- */
  --font-display: "Bricolage Grotesque", "Arial Black", sans-serif;
  --font-body: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;

  /* -- spacing scale -- */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 2.75rem;
  --space-8: 3.5rem;
  --space-9: 5rem;
  --space-10: 7rem;

  /* -- radius: crisp, dossier-like — not zero, not soft -- */
  --radius-sm: 3px;
  --radius-md: 6px;
  --radius-lg: 10px;

  /* -- shadow: dark theme leans on borders, shadow just for depth on hover -- */
  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-raised: 0 12px 32px -12px rgba(0, 0, 0, 0.55);

  /* -- layout -- */
  --container-w: 1280px;
  --gutter: clamp(1.25rem, 4vw, 2.5rem);

  /* -- motion -- */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --dur-fast: 150ms;
  --dur-med: 320ms;
  --dur-slow: 900ms;

  color-scheme: dark;
}

/* -- light theme override -- */
:root[data-theme="light"] {
  --ink: #f5f7fb;
  --ink-2: #ffffff;
  --ink-3: #eef2f8;
  --ink-4: #e4eaf3;
  --line: #d9e0ec;
  --text: #0b1220;
  --text-dim: #55617a;

  --brand: #0fb98a;
  --brand-strong: #0a9c73;
  --brand-dim: rgba(15, 185, 138, 0.1);
  --warn: #c7861a;
  --warn-dim: rgba(199, 134, 26, 0.12);
  --danger: #e23b36;
  --danger-dim: rgba(226, 59, 54, 0.1);

  --on-brand: #04140f;
  --on-warn: #1a1102;
  --on-danger: #ffffff;

  --shadow-card: 0 1px 2px rgba(20, 30, 50, 0.06);
  --shadow-raised: 0 16px 40px -16px rgba(20, 30, 50, 0.22);

  color-scheme: light;
}

/* respect OS-level preference when the user hasn't chosen explicitly —
   the JS toggle stamps data-theme and always wins over this */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --ink: #f5f7fb;
    --ink-2: #ffffff;
    --ink-3: #eef2f8;
    --ink-4: #e4eaf3;
    --line: #d9e0ec;
    --text: #0b1220;
    --text-dim: #55617a;
    --brand: #0fb98a;
    --brand-strong: #0a9c73;
    --brand-dim: rgba(15, 185, 138, 0.1);
    --warn: #c7861a;
    --warn-dim: rgba(199, 134, 26, 0.12);
    --danger: #e23b36;
    --danger-dim: rgba(226, 59, 54, 0.1);
    --on-brand: #04140f;
    --on-warn: #1a1102;
    --on-danger: #ffffff;
    --shadow-card: 0 1px 2px rgba(20, 30, 50, 0.06);
    --shadow-raised: 0 16px 40px -16px rgba(20, 30, 50, 0.22);
    color-scheme: light;
  }
}

/* --------------------------------------------------------------------------
   3. RESET / BASE
   -------------------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: 1.7;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  transition: background-color var(--dur-med) var(--ease-out), color var(--dur-med) var(--ease-out);
}

img,
picture,
svg {
  display: block;
  max-width: 100%;
  height: auto;
}

a {
  color: inherit;
  text-decoration: none;
}

ul,
ol {
  margin: 0;
  padding: 0;
  list-style: none;
}

button {
  font-family: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

input,
textarea,
select {
  font-family: inherit;
  font-size: 1rem;
  color: inherit;
}

hr {
  border: 0;
  border-top: 1px solid var(--line);
  margin: 0;
}

/* visible, high-contrast focus ring everywhere — WCAG AA keyboard support */
:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

::selection {
  background: var(--brand-dim);
  color: var(--text);
}

/* --------------------------------------------------------------------------
   4. TYPOGRAPHY PRIMITIVES
   -------------------------------------------------------------------------- */
.h-display {
  font-family: var(--font-display);
  font-weight: 800;
  line-height: 1.04;
  letter-spacing: -0.02em;
  margin: 0;
}

.h-hero {
  font-size: clamp(2.6rem, 6vw, 5rem);
}

.h-section {
  font-size: clamp(1.75rem, 3.2vw, 2.5rem);
  line-height: 1.08;
}

.h-section--sm {
  font-size: clamp(1.5rem, 2.6vw, 2rem);
}

.h-card {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.01em;
  margin: 0;
}

.deck {
  font-size: clamp(1.05rem, 1.6vw, 1.3rem);
  line-height: 1.55;
  color: var(--text-dim);
  font-weight: 400;
  max-width: 54ch;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--brand);
}

.eyebrow--dim {
  color: var(--text-dim);
}

.mono {
  font-family: var(--font-mono);
  font-weight: 500;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}

.lede {
  font-size: 1.1875rem;
  line-height: 1.7;
  color: var(--text);
}

/* --------------------------------------------------------------------------
   5. LAYOUT
   -------------------------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--container-w);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section {
  padding-block: var(--space-9);
  border-top: 1px solid var(--line);
}

.section:first-of-type {
  border-top: 0;
}

.section--tight {
  padding-block: var(--space-7);
}

.section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}

.section-head__title {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.section-link {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--brand);
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  transition: gap var(--dur-fast) var(--ease-out);
}

.section-link:hover {
  gap: 0.65em;
}

.grid {
  display: grid;
  gap: var(--space-5);
}

.grid--latest {
  grid-template-columns: repeat(12, 1fr);
}

.grid--latest .article-card--hero {
  grid-column: span 12;
}

.grid--latest .article-card--standard {
  grid-column: span 12;
}

/* bočný stĺpec (2 kompaktné karty vedľa hero) — base span je NUTNÝ:
   bez neho grid item defaultne na span 1 = 1/12 šírky (~30px prúžok
   na mobile aj tablete); na 980px+ ho prepíše span 5 vedľa hero(7) */
.grid--latest .article-card--side {
  grid-column: span 12;
}

.grid--two {
  grid-template-columns: repeat(12, 1fr);
}

.grid--two > * {
  grid-column: span 12;
}

/* uniform standard-card grid — listing page 1 tail rows + pages 2+ */
.grid--cards {
  grid-template-columns: repeat(12, 1fr);
}

.grid--cards > * {
  grid-column: span 12;
}

.grid--latest + .grid--cards {
  margin-top: var(--space-5);
}

/* hero case-file — single-column, text-only block (no media panel) */
.hero-grid {
  display: grid;
  gap: var(--space-6);
  padding-block: var(--space-6);
  max-width: 54rem;
}

.hero-risk {
  max-width: 34rem;
  margin-top: var(--space-5);
}

.hero-stats {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-6);
  align-items: flex-end;
  margin-top: var(--space-6);
}

.hero-actions {
  display: flex;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-top: var(--space-6);
}

@media (min-width: 720px) {
  .grid--latest .article-card--standard {
    grid-column: span 6;
  }
  .grid--cards > * {
    grid-column: span 6;
  }
}

@media (min-width: 980px) {
  .grid--latest .article-card--hero {
    grid-column: span 7;
  }
  .grid--latest .article-card--side {
    grid-column: span 5;
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
  }
  .grid--latest .article-card--standard {
    grid-column: span 4;
  }
  .grid--two > * {
    grid-column: span 6;
  }
  .grid--cards > * {
    grid-column: span 4;
  }
}

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

.skip-link {
  position: absolute;
  left: var(--space-4);
  top: -100px;
  background: var(--brand);
  color: var(--on-brand);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: 0.875rem;
  z-index: 1000;
  transition: top var(--dur-fast) var(--ease-out);
}

.skip-link:focus {
  top: var(--space-4);
}

/* --------------------------------------------------------------------------
   6. HEADER / NAV
   -------------------------------------------------------------------------- */
.masthead {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--ink-2);
  border-bottom: 1px solid var(--line);
  backdrop-filter: saturate(1.1) blur(10px);
}

.masthead__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-4);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  text-decoration: none;
}

.brand__mark {
  width: 26px;
  height: 26px;
  color: var(--brand);
  flex: none;
}

.brand__word {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.2rem;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--text);
}

.brand__real {
  color: var(--brand);
}

.nav-primary {
  display: none;
}

.nav-primary__list {
  display: flex;
  align-items: center;
  gap: var(--space-6);
}

.nav-primary__link {
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--text-dim);
  position: relative;
  padding-block: var(--space-1);
  background-image: linear-gradient(var(--brand), var(--brand));
  background-repeat: no-repeat;
  background-position: left bottom;
  background-size: 0% 2px;
  transition: color var(--dur-fast) var(--ease-out), background-size var(--dur-med) var(--ease-out);
}

.nav-primary__link:hover,
.nav-primary__link[aria-current="page"] {
  color: var(--text);
}

.nav-primary__link:not([aria-current="page"]):hover {
  background-size: 100% 2px;
}

.nav-primary__link[aria-current="page"]::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -13px;
  height: 2px;
  background: var(--brand);
}

.masthead__actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  color: var(--text-dim);
  transition: border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}

.theme-toggle:hover {
  color: var(--brand);
  border-color: var(--brand);
}

.theme-toggle svg {
  width: 18px;
  height: 18px;
}

.theme-toggle .icon-moon {
  display: block;
}
.theme-toggle .icon-sun {
  display: none;
}
:root[data-theme="light"] .theme-toggle .icon-moon {
  display: none;
}
:root[data-theme="light"] .theme-toggle .icon-sun {
  display: block;
}

.nav-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
}

.nav-toggle span {
  display: block;
  width: 16px;
  height: 2px;
  background: currentColor;
  position: relative;
}

.nav-toggle span::before,
.nav-toggle span::after {
  content: "";
  position: absolute;
  left: 0;
  width: 16px;
  height: 2px;
  background: currentColor;
  transition: transform var(--dur-fast) var(--ease-out);
}

.nav-toggle span::before {
  top: -5px;
}
.nav-toggle span::after {
  top: 5px;
}

.nav-toggle[aria-expanded="true"] span {
  background: transparent;
}
.nav-toggle[aria-expanded="true"] span::before {
  transform: translateY(5px) rotate(45deg);
}
.nav-toggle[aria-expanded="true"] span::after {
  transform: translateY(-5px) rotate(-45deg);
}

.mobile-nav {
  display: none;
  border-top: 1px solid var(--line);
  background: var(--bg);
  box-shadow: var(--shadow-raised);
}

.mobile-nav.is-open {
  display: block;
  animation: mobile-nav-open 260ms var(--ease-out) both;
}

@keyframes mobile-nav-open {
  from {
    opacity: 0;
    transform: translateY(-8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.mobile-nav__inner {
  padding-block: var(--space-5) var(--space-6);
}

.mobile-nav__eyebrow {
  display: block;
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--text-dim);
  margin-bottom: var(--space-3);
}

.mobile-nav__list {
  display: flex;
  flex-direction: column;
}

.mobile-nav__item {
  border-bottom: 1px solid var(--line);
}

/* stagger — každý link nabehne o 45 ms neskôr (--i z markupu) */
.mobile-nav.is-open .mobile-nav__item {
  animation: mobile-nav-item-in 320ms var(--ease-out) both;
  animation-delay: calc(var(--i, 0) * 45ms);
}

@keyframes mobile-nav-item-in {
  from {
    opacity: 0;
    transform: translateX(-10px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

.mobile-nav__link {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  padding-block: var(--space-4);
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--text);
  transition: color var(--dur-fast) var(--ease-out), padding-left var(--dur-fast) var(--ease-out);
}

.mobile-nav__link:hover,
.mobile-nav__link:focus-visible {
  color: var(--brand);
}

.mobile-nav__num {
  font-size: 0.75rem;
  color: var(--brand);
  letter-spacing: 0.08em;
}

.mobile-nav__cta {
  display: block;
  width: 100%;
  text-align: center;
  margin-top: var(--space-5);
}

.mobile-nav__link {
  font-size: 1rem;
  font-weight: 500;
  color: var(--text);
}

@media (min-width: 900px) {
  .nav-primary {
    display: block;
  }
  .nav-toggle {
    display: none;
  }
  .mobile-nav {
    display: none !important;
  }
}

/* --------------------------------------------------------------------------
   7. FOOTER
   -------------------------------------------------------------------------- */
.site-footer {
  background: var(--ink-2);
  border-top: 1px solid var(--line);
  padding-block: var(--space-8) var(--space-6);
}

.footer-grid {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: 1fr;
  padding-bottom: var(--space-6);
  border-bottom: 1px solid var(--line);
}

@media (min-width: 780px) {
  .footer-grid {
    grid-template-columns: 1.4fr 1fr 1fr 1fr;
  }
}

.footer-brand__desc {
  color: var(--text-dim);
  font-size: 0.9375rem;
  max-width: 32ch;
  margin-top: var(--space-3);
}

.footer-col h3 {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--text-dim);
  margin: 0 0 var(--space-4);
}

.footer-col ul {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.footer-col a {
  font-size: 0.9375rem;
  color: var(--text-dim);
  transition: color var(--dur-fast) var(--ease-out);
}

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

.footer-bottom {
  padding-top: var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.footer-masthead-line {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  color: var(--text-dim);
}

.footer-masthead-line strong {
  color: var(--text);
  font-weight: 500;
}

.footer-disclaimer {
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--text-dim);
  padding: var(--space-4);
  background: var(--ink-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  border-left: 3px solid var(--warn);
}

.footer-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  font-size: 0.8125rem;
  color: var(--text-dim);
}

.footer-legal {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
}

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

/* --------------------------------------------------------------------------
   8. BUTTONS
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: 0.75rem 1.375rem;
  border-radius: var(--radius-md);
  font-size: 0.9375rem;
  font-weight: 600;
  border: 1px solid transparent;
  transition: background-color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out),
    color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
  white-space: nowrap;
}

.btn:active {
  transform: translateY(1px);
}

.btn-primary {
  background: var(--brand);
  color: var(--on-brand);
}

.btn-primary:hover {
  background: var(--brand-strong);
}

.btn-ghost {
  background: transparent;
  border-color: var(--line);
  color: var(--text);
}

.btn-ghost:hover {
  border-color: var(--brand);
  color: var(--brand);
}

.btn-danger {
  background: var(--danger-dim);
  border-color: var(--danger);
  color: var(--danger);
}

.btn-danger:hover {
  background: var(--danger);
  color: var(--on-danger);
}

.btn-sm {
  padding: 0.5rem 0.875rem;
  font-size: 0.8125rem;
}

.btn-block {
  width: 100%;
}

/* --------------------------------------------------------------------------
   9. FORMS + CONSENT
   -------------------------------------------------------------------------- */
.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

.field--last {
  margin-bottom: 0;
}

/* two-up field row, e.g. email + optional phone side by side */
.form-fields {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  align-items: flex-start;
}

.form-fields .field {
  flex: 1 1 200px;
  min-width: 200px;
  margin-bottom: 0;
}

.field label {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-dim);
}

.field .optional-tag {
  text-transform: none;
  letter-spacing: normal;
  font-style: italic;
  opacity: 0.8;
}

.field input,
.field textarea {
  background: var(--ink-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: 0.75rem 0.9rem;
  color: var(--text);
  transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}

.field input::placeholder,
.field textarea::placeholder {
  color: var(--text-dim);
}

.field input:focus,
.field textarea:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-dim);
  outline: none;
}

.field.has-error input,
.field.has-error textarea {
  border-color: var(--danger);
}

.field-error {
  font-size: 0.8125rem;
  color: var(--danger);
  display: none;
}

.field.has-error .field-error {
  display: block;
}

.form-consent {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  margin-block: var(--space-5);
}

.form-consent input[type="checkbox"] {
  margin-top: 0.2em;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  accent-color: var(--brand);
}

.form-consent label {
  font-size: 0.875rem;
  color: var(--text-dim);
  line-height: 1.55;
}

.form-consent a {
  color: var(--brand);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.form-note {
  font-size: 0.8125rem;
  color: var(--text-dim);
  margin-top: var(--space-3);
}

.form-success {
  display: none;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4);
  background: var(--brand-dim);
  border: 1px solid var(--brand);
  border-radius: var(--radius-md);
  color: var(--text);
  font-size: 0.9375rem;
}

.form-success.is-visible {
  display: flex;
}

.lead-form.is-submitted .form-fields,
.lead-form.is-submitted .form-consent,
.lead-form.is-submitted .form-note,
.lead-form.is-submitted button[type="submit"] {
  display: none;
}

.form-consent.has-error label {
  color: var(--danger);
}

/* --------------------------------------------------------------------------
   10. TAGS / EYEBROWS / STATUS / RISK BADGE / SPONSORED
   -------------------------------------------------------------------------- */
.tag-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
  justify-content: flex-start;
}

.tag-row--tight {
  margin-bottom: 0.1rem;
}

.tag-row--split {
  justify-content: space-between;
}

/* --- filter tab row: reuses .tag as a static filter/toggle pill ---
   built on the same tokens as .status-tag / .pagination__link so the
   "active" state matches the site's existing selected-state language. */
.tag-row--filters {
  padding-bottom: var(--space-1);
}

a.tag {
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out),
    background-color var(--dur-fast) var(--ease-out);
}

a.tag:hover {
  color: var(--text);
  border-color: var(--brand);
}

.tag[aria-current="page"] {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--on-brand);
  font-weight: 600;
}

.tag {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 500;
  padding: 0.25rem 0.6rem;
  border-radius: var(--radius-sm);
  background: var(--ink-3);
  border: 1px solid var(--line);
  color: var(--text-dim);
}

.status-tag {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  padding: 0.25rem 0.5rem;
  border-radius: var(--radius-sm);
  white-space: nowrap;
  align-self: flex-start;
}

.status-tag::before {
  content: "[ ";
}
.status-tag::after {
  content: " ]";
}

.status-tag--confirmed {
  color: var(--danger);
  background: var(--danger-dim);
}

.status-tag--alleged {
  color: var(--warn);
  background: var(--warn-dim);
}

.status-tag--resolved {
  color: var(--brand);
  background: var(--brand-dim);
}

.status-tag--developing {
  color: var(--text-dim);
  background: var(--ink-3);
  border: 1px solid var(--line);
}

.risk-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 500;
  padding: 0.3rem 0.6rem;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
}

.risk-badge::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
}

.risk-badge--low {
  color: var(--brand);
  background: var(--brand-dim);
  border-color: rgba(55, 214, 168, 0.35);
}

.risk-badge--med {
  color: var(--warn);
  background: var(--warn-dim);
  border-color: rgba(245, 184, 65, 0.35);
}

.risk-badge--high {
  color: var(--danger);
  background: var(--danger-dim);
  border-color: rgba(245, 84, 78, 0.35);
}

.sponsored-label {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-dim);
  padding: 0.2rem 0.5rem;
  border: 1px dashed var(--line);
  border-radius: var(--radius-sm);
}

.sponsored-label::before {
  content: "\25C8";
  color: var(--warn);
}

/* filter chip — static category/year filters (leaderboard, listings) */
.tag--active {
  color: var(--brand);
  background: var(--brand-dim);
  border-color: rgba(55, 214, 168, 0.4);
}

/* --------------------------------------------------------------------------
   11. RISK INDEX METER (signature device)
   Markup contract:
   <div class="risk-index" data-risk="8.7" data-max="10">
     <div class="risk-index__head">...</div>
     <div class="risk-index__track"><div class="risk-index__fill"></div><div class="risk-index__marker"></div></div>
     <p class="risk-index__label mono">RISK 8.7 / 10 · HIGH</p>
   </div>
   JS sets --risk-pct and toggles .is-animated on load (see cryptoreal.js).
   -------------------------------------------------------------------------- */
.risk-index {
  --risk-pct: 0%;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.risk-index__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
}

.risk-index__title {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--text-dim);
}

.risk-index__track {
  position: relative;
  height: 10px;
  border-radius: 999px;
  background: linear-gradient(
    90deg,
    var(--brand) 0%,
    var(--brand) 28%,
    var(--warn) 50%,
    var(--danger) 78%,
    var(--danger) 100%
  );
  opacity: 0.22;
  overflow: visible;
}

.risk-index__fill {
  position: absolute;
  inset: 0;
  width: var(--risk-pct);
  border-radius: 999px;
  background: linear-gradient(
    90deg,
    var(--brand) 0%,
    var(--brand) 28%,
    var(--warn) 50%,
    var(--danger) 78%,
    var(--danger) 100%
  );
  transition: width var(--dur-slow) var(--ease-out);
}

.risk-index.is-animated .risk-index__fill {
  width: var(--risk-pct);
}

.risk-index__marker {
  position: absolute;
  top: 50%;
  left: var(--risk-pct);
  width: 18px;
  height: 18px;
  transform: translate(-50%, -50%) scale(0);
  border-radius: 50%;
  background: var(--ink);
  border: 3px solid var(--text);
  box-shadow: var(--shadow-raised);
  transition: left var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out) 120ms;
}

.risk-index.is-animated .risk-index__marker {
  transform: translate(-50%, -50%) scale(1);
}

.risk-index__label {
  font-size: 0.9375rem;
  color: var(--text);
}

.risk-index__label .risk-index__score {
  font-size: 1.0625rem;
  font-weight: 500;
}

.risk-index--low .risk-index__label .risk-index__score,
.risk-index--low .risk-index__marker {
  color: var(--brand);
}
.risk-index--med .risk-index__label .risk-index__score,
.risk-index--med .risk-index__marker {
  color: var(--warn);
}
.risk-index--high .risk-index__label .risk-index__score,
.risk-index--high .risk-index__marker {
  color: var(--danger);
}

.risk-index--sm .risk-index__track {
  height: 6px;
}
.risk-index--sm .risk-index__marker {
  width: 13px;
  height: 13px;
  border-width: 2px;
}

/* --------------------------------------------------------------------------
   12. CASE-FILE / DOSSIER STRIP
   -------------------------------------------------------------------------- */
.case-file {
  position: relative;
}

.dossier-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-5);
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  color: var(--text-dim);
  padding-block: var(--space-3);
  border-block: 1px solid var(--line);
}

.dossier-strip__item {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  white-space: nowrap;
}

.dossier-strip__item strong {
  color: var(--text);
  font-weight: 500;
}

.dossier-strip__sep {
  color: var(--line);
}

.dossier-strip + .tag-row {
  margin-top: var(--space-4);
}

/* --------------------------------------------------------------------------
   13. ARTICLE CARDS — hero / standard / compact
   -------------------------------------------------------------------------- */
.article-card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  opacity: 0;
  transform: translateY(14px);
  transition: transform var(--dur-med) var(--ease-out), border-color var(--dur-fast) var(--ease-out),
    box-shadow var(--dur-fast) var(--ease-out), opacity var(--dur-med) var(--ease-out);
}

.article-card.is-visible {
  opacity: 1;
  transform: translateY(0);
}

.article-card:hover {
  border-color: var(--brand);
  box-shadow: var(--shadow-raised);
  transform: translateY(-3px);
}

.article-card.is-visible:hover {
  transform: translateY(-3px);
}

.article-card__media {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--ink-3);
  overflow: hidden;
}

.article-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.article-card__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5);
  flex: 1;
}

.article-card__title {
  font-size: 1.25rem;
}

.article-card__title a::after {
  content: "";
  position: absolute;
  inset: 0;
}

.article-card__title a {
  position: relative;
}

.article-card__dek {
  color: var(--text-dim);
  font-size: 0.9375rem;
  line-height: 1.6;
}

.article-card__meta {
  margin-top: auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1) var(--space-3);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--text-dim);
  padding-top: var(--space-3);
}

.article-card--hero {
  position: relative;
}

@media (min-width: 640px) {
  .article-card--hero {
    flex-direction: row;
  }
  .article-card--hero .article-card__media {
    width: 46%;
    aspect-ratio: auto;
  }
  .article-card--hero .article-card__body {
    width: 54%;
    padding: var(--space-6);
  }
  .article-card--hero .article-card__title {
    font-size: 1.75rem;
  }
  .article-card--hero .article-card__dek {
    font-size: 1.05rem;
  }
}

.article-card--standard .article-card__title {
  font-size: 1.15rem;
}

/* rating cards carry no media panel — body needs its own top padding */
.article-card__body--flush {
  padding-top: var(--space-5);
}

.article-card__title--lg {
  font-size: 1.3rem;
}

.article-card--compact {
  flex-direction: row;
  align-items: center;
  gap: var(--space-4);
  background: transparent;
  border: 0;
  border-radius: 0;
  padding-block: var(--space-4);
}

.article-card--compact:hover {
  box-shadow: none;
  transform: none;
}

.article-card--compact + .article-card--compact {
  border-top: 1px solid var(--line);
}

.article-card--compact .article-card__media {
  width: 96px;
  min-width: 96px;
  aspect-ratio: 1 / 1;
  border-radius: var(--radius-md);
}

.article-card--compact .article-card__body {
  padding: 0;
  gap: var(--space-1);
}

.article-card--compact .article-card__title {
  font-size: 1rem;
  position: relative;
}

/* compact rows carry no visible border/media frame — skip the scan-sweep
   accent (13b below), it would render as a stray ring with nothing to hug */
.article-card--compact::before,
.article-card--compact::after {
  display: none;
}

/* --------------------------------------------------------------------------
   14. LEDGER / LEADERBOARD
   -------------------------------------------------------------------------- */
.ledger {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--ink-2);
}

.ledger__row {
  display: grid;
  grid-template-columns: 2.5rem 1fr auto;
  gap: var(--space-3);
  align-items: center;
  padding: var(--space-4) var(--space-5);
}

.ledger__row + .ledger__row {
  border-top: 1px solid var(--line);
}

.ledger__head {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-dim);
  background: var(--ink-3);
}

.ledger__rank {
  font-family: var(--font-mono);
  font-size: 0.9375rem;
  color: var(--text-dim);
}

.ledger__row--1 .ledger__rank,
.ledger__row--2 .ledger__rank,
.ledger__row--3 .ledger__rank {
  color: var(--danger);
}

.ledger__entity {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  min-width: 0;
}

.ledger__entity-name {
  font-weight: 600;
  font-size: 0.9375rem;
  color: var(--text);
}

.ledger__entity-meta {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--text-dim);
  display: flex;
  gap: var(--space-2);
  align-items: center;
  flex-wrap: wrap;
}

.ledger__figures {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  text-align: right;
}

.ledger__amount {
  font-size: 1rem;
  color: var(--danger);
  white-space: nowrap;
}

.ledger__head-amount {
  text-align: right;
}

@media (max-width: 560px) {
  .ledger__row {
    grid-template-columns: 2rem 1fr;
  }
  .ledger__figures {
    grid-column: 1 / -1;
    justify-content: space-between;
    padding-top: var(--space-2);
  }
}

/* amount coloured by severity — default (.ledger__amount) stays danger-red
   for the homepage teaser; the full leaderboard opts into all three */
.ledger__amount--low {
  color: var(--brand);
}
.ledger__amount--med {
  color: var(--warn);
}
.ledger__amount--high {
  color: var(--danger);
}

/* -- full leaderboard variant: rank / entity / category / date / amount / risk --
   Desktop: six-column grid table. Mobile: collapses into a scannable case
   card, with data-label attributes surfacing column names via ::before. */
.ledger--leaderboard .ledger__row {
  grid-template-columns: 2.75rem 1.7fr 1fr 0.95fr 1fr 0.85fr;
  gap: var(--space-3) var(--space-4);
}

.ledger--leaderboard a.ledger__row {
  color: inherit;
  transition: background-color var(--dur-fast) var(--ease-out);
}

.ledger--leaderboard a.ledger__row:hover,
.ledger--leaderboard a.ledger__row:focus-visible {
  background: var(--ink-3);
}

.ledger__category,
.ledger__date {
  font-size: 0.875rem;
  color: var(--text-dim);
  min-width: 0;
}

.ledger__date {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
}

.ledger--leaderboard .ledger__amount {
  font-size: 1.0625rem;
  text-align: right;
}

.ledger--leaderboard .ledger__risk {
  display: flex;
  justify-content: flex-end;
}

@media (max-width: 860px) {
  .ledger--leaderboard .ledger__row {
    grid-template-columns: 2rem 1fr auto;
    row-gap: var(--space-2);
  }
  .ledger--leaderboard .ledger__head {
    display: none;
  }
  .ledger--leaderboard .ledger__category,
  .ledger--leaderboard .ledger__date,
  .ledger--leaderboard .ledger__risk {
    grid-column: 2 / -1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-family: var(--font-mono);
    font-size: 0.75rem;
  }
  .ledger--leaderboard .ledger__category::before,
  .ledger--leaderboard .ledger__date::before,
  .ledger--leaderboard .ledger__risk::before {
    content: attr(data-label);
    color: var(--text-dim);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    font-size: 0.6875rem;
  }
  .ledger--leaderboard .ledger__risk {
    justify-content: space-between;
  }
}

/* --------------------------------------------------------------------------
   15. CALLOUTS + PULLQUOTE
   -------------------------------------------------------------------------- */
.callout {
  display: flex;
  gap: var(--space-4);
  padding: var(--space-5);
  border-radius: var(--radius-md);
  border: 1px solid var(--line);
  background: var(--ink-3);
  margin-block: var(--space-6);
}

.callout__icon {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  margin-top: 0.15em;
}

.callout__title {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 500;
  margin: 0 0 var(--space-2);
}

.callout__body {
  font-size: 0.9375rem;
  color: var(--text-dim);
  line-height: 1.65;
}

.callout--redflag {
  border-color: rgba(245, 84, 78, 0.35);
  background: var(--danger-dim);
}

.callout--redflag .callout__title,
.callout--redflag .callout__icon {
  color: var(--danger);
}

.callout--tip {
  border-color: rgba(55, 214, 168, 0.35);
  background: var(--brand-dim);
}

.callout--tip .callout__title,
.callout--tip .callout__icon {
  color: var(--brand);
}

.pullquote {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.4rem, 2.6vw, 2rem);
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: var(--text);
  border-left: 3px solid var(--brand);
  padding-left: var(--space-5);
  margin-block: var(--space-7);
}

.pullquote cite {
  display: block;
  font-family: var(--font-mono);
  font-style: normal;
  font-weight: 500;
  font-size: 0.8125rem;
  color: var(--text-dim);
  margin-top: var(--space-3);
  letter-spacing: 0.02em;
}

/* --------------------------------------------------------------------------
   16. BYLINE / TIMESTAMP / AMOUNT MONO HELPERS
   -------------------------------------------------------------------------- */
.byline {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: 0.875rem;
}

.byline__avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--ink-4);
  border: 1px solid var(--line);
  flex-shrink: 0;
  overflow: hidden;
}

.byline__avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* profile masthead variant — author page header (larger avatar + stacked meta) */
.byline--profile {
  align-items: center;
  gap: var(--space-5);
}

.byline__avatar--lg {
  width: 84px;
  height: 84px;
  border-width: 2px;
}

@media (min-width: 640px) {
  .byline__avatar--lg {
    width: 108px;
    height: 108px;
  }
}

.byline__name {
  color: var(--text);
  font-weight: 600;
}

.byline__meta {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--text-dim);
  display: flex;
  gap: 0.6em;
  align-items: center;
  flex-wrap: wrap;
}

.timestamp {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--text-dim);
  letter-spacing: 0.02em;
}

.amount {
  font-family: var(--font-mono);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

.amount--lg {
  font-size: clamp(2rem, 5vw, 3.25rem);
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.01em;
  color: var(--danger);
  display: inline-flex;
  align-items: baseline;
  gap: 0.3rem;
}

.amount--lg small {
  font-size: 0.35em;
  font-weight: 500;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.addr {
  font-family: var(--font-mono);
  font-size: 0.85em;
  color: var(--text-dim);
  background: var(--ink-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 0.1em 0.4em;
}

/* --------------------------------------------------------------------------
   17. BREADCRUMBS / PAGINATION
   -------------------------------------------------------------------------- */
.breadcrumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  color: var(--text-dim);
  padding-block: var(--space-4);
}

.breadcrumbs a:hover {
  color: var(--brand);
}

.breadcrumbs__sep {
  color: var(--line);
}

.breadcrumbs [aria-current="page"] {
  color: var(--text);
}

.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding-top: var(--space-6);
}

.pagination__link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.25rem;
  height: 2.25rem;
  padding-inline: 0.4rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  color: var(--text-dim);
  transition: border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out),
    box-shadow var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}

.pagination__link:hover {
  border-color: var(--brand);
  color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-dim);
  transform: translateY(-1px);
}

.pagination__link[aria-current="page"] {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--on-brand);
  font-weight: 500;
}

.pagination__link--disabled {
  opacity: 0.4;
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   18. CTA BAND / LEAD STRIP
   -------------------------------------------------------------------------- */
.cta-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-6);
  padding: var(--space-7);
  border-radius: var(--radius-lg);
  background: linear-gradient(135deg, var(--ink-3), var(--ink-2));
  border: 1px solid var(--line);
  position: relative;
  overflow: hidden;
}

.cta-banner::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 85% 20%, var(--brand-dim), transparent 60%);
  pointer-events: none;
}

.cta-banner__copy {
  max-width: 46ch;
  position: relative;
}

.cta-banner__copy h2 {
  margin: var(--space-2) 0 var(--space-3);
}

.cta-banner__copy p {
  color: var(--text-dim);
  margin: 0;
}

.cta-banner__action {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  align-items: flex-start;
}

.cta-banner__fineprint {
  font-size: 0.75rem;
  color: var(--text-dim);
}

.lead-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-5);
  border: 1px dashed var(--line);
  border-radius: var(--radius-lg);
  background: var(--ink-2);
}

.lead-strip__copy {
  flex: 1;
  min-width: 220px;
}

.lead-strip__copy .eyebrow {
  margin-bottom: var(--space-2);
}

.lead-strip__text {
  margin: 0;
  color: var(--text-dim);
}

.lead-strip .lead-form {
  flex: 1 1 280px;
  min-width: 280px;
  max-width: 30rem;
}

/* --------------------------------------------------------------------------
   19b. ARTICLE / CASE-FILE DETAIL PAGE
   Small additions for the long-form case-file screen (article.html):
   heading rhythm below the dossier strip, the stat note under the
   amount--lg lead figure, the long-form body column, and spacing for a
   cta-banner / callout button dropped inline in article flow.
   -------------------------------------------------------------------------- */
.case-file__title {
  margin-top: var(--space-5);
}

.case-file__stats {
  margin-top: var(--space-5);
}

.case-file__stat-note {
  color: var(--text-dim);
  font-size: 0.9375rem;
  margin-top: var(--space-2);
}

.article-body {
  grid-column: 1 / -1;
  max-width: 72ch;
}

.cta-banner--article {
  margin-block: var(--space-7);
}

.callout__cta {
  margin-top: var(--space-3);
}

/* --------------------------------------------------------------------------
   20. REVEAL + MOTION UTILITIES
   -------------------------------------------------------------------------- */
[data-reveal] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--dur-med) var(--ease-out), transform var(--dur-med) var(--ease-out);
}

[data-reveal].is-visible {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  .article-card,
  [data-reveal] {
    opacity: 1;
    transform: none;
  }

  .risk-index__fill,
  .risk-index__marker {
    transition: none !important;
  }

  .article-card:hover {
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   20. PROSE (legal / content pages — about, privacy, terms, 404)
   Reuses existing tokens; provides readable long-form measure + spacing
   rhythm for static copy pages that aren't built from cards/grids.
   -------------------------------------------------------------------------- */
.prose {
  max-width: 68ch;
}

.prose > * + * {
  margin-top: var(--space-4);
}

.prose h2 {
  position: relative;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.4rem, 2.4vw, 1.9rem);
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: var(--text);
  margin-top: var(--space-8);
  padding-left: 1.15em;
}

.prose h2:first-child {
  margin-top: 0;
}

/* animated marker — scrolled-into-view accent, driven by cryptoreal.js
   (IntersectionObserver adds .is-marked once). Heading text itself is never
   hidden, so long-form pages read fine with JS off. */
.prose h2::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.32em;
  width: 0.5em;
  height: 0.5em;
  background: var(--brand);
  border-radius: 2px;
  transform: scale(0) rotate(45deg);
  transition: transform 480ms var(--ease-out);
}

.prose h2.is-marked::before {
  transform: scale(1) rotate(45deg);
}

.prose h3 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.15rem;
  line-height: 1.3;
  color: var(--text);
  margin-top: var(--space-6);
}

.prose p {
  color: var(--text-dim);
}

.prose strong {
  color: var(--text);
  font-weight: 600;
}

.prose ul,
.prose ol {
  color: var(--text-dim);
  padding-left: 1.25rem;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.prose ul {
  list-style: disc;
}

.prose ol {
  list-style: decimal;
}

.prose li::marker {
  color: var(--text-dim);
}

.prose a {
  color: var(--brand);
  text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-position: left bottom;
  background-size: 100% 1px;
  padding-bottom: 0.05em;
  transition: color var(--dur-fast) var(--ease-out), background-size var(--dur-fast) var(--ease-out);
}

.prose a:hover {
  color: var(--brand-strong);
  background-size: 100% 2px;
}

/* Markdown extras used by article.content (rendered via 'marked'):
   blockquote / inline + block code / rule / table. */
.prose h1 {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.6rem, 3vw, 2.1rem);
  line-height: 1.15;
  color: var(--text);
  margin-top: var(--space-8);
}

.prose blockquote {
  border-left: 3px solid var(--brand);
  padding-left: var(--space-4);
  color: var(--text-dim);
  font-style: italic;
  transition: border-color var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out);
}

.prose blockquote:hover {
  border-left-color: var(--brand-strong);
  background: var(--brand-dim);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

.prose code {
  font-family: var(--font-mono);
  font-size: 0.875em;
  background: var(--ink-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 0.1em 0.4em;
}

.prose pre {
  background: var(--ink-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  overflow-x: auto;
}

.prose pre code {
  background: none;
  border: 0;
  padding: 0;
}

.prose hr {
  border: 0;
  border-top: 1px solid var(--line);
  margin-block: var(--space-6);
}

.prose img {
  max-width: 100%;
  border-radius: var(--radius-md);
}

.prose table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9375rem;
}

.prose th,
.prose td {
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line);
  text-align: left;
}

.prose th {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-dim);
  background: var(--ink-3);
}

/* --------------------------------------------------------------------------
   21. ADMIN (utilitarian screen — login card + article table)
   Reuses .field, .btn, .status-tag, .tag, .form-success, .pagination.
   -------------------------------------------------------------------------- */
.container--narrow {
  max-width: 30rem;
}

.admin-mode-tag {
  border: 1px dashed var(--line);
  border-radius: var(--radius-sm);
  padding: 0.2rem 0.5rem;
}

.admin-card {
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
}

.admin-card__lead {
  margin: var(--space-2) 0 var(--space-6);
}

.admin-login-form .field {
  margin-bottom: var(--space-4);
}

.admin-form-error {
  font-size: 0.8125rem;
  color: var(--danger);
  background: var(--danger-dim);
  border: 1px solid var(--danger);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  margin: 0 0 var(--space-4);
}

.admin-flash {
  margin-bottom: var(--space-5);
}

.admin-table-wrap {
  width: 100%;
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--ink-2);
}

.admin-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9375rem;
}

.admin-table th,
.admin-table td {
  padding: var(--space-4) var(--space-5);
  text-align: left;
  white-space: nowrap;
}

.admin-table th {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-dim);
  background: var(--ink-3);
  border-bottom: 1px solid var(--line);
}

.admin-table tbody tr + tr td {
  border-top: 1px solid var(--line);
}

.admin-table__title {
  white-space: normal;
  min-width: 22rem;
  color: var(--text);
  font-weight: 500;
}

.admin-table__actions,
.admin-table__actions-head {
  text-align: right;
}

.admin-table__actions {
  display: flex;
  gap: var(--space-2);
  justify-content: flex-end;
}

.site-footer--admin {
  padding-block: var(--space-6);
}

/* --------------------------------------------------------------------------
   21. LEAD-FORM STANDALONE HEAD + BENEFIT LIST (ebook.html)
   -------------------------------------------------------------------------- */
/* lead-strip used stand-alone (form only, no copy column) — e.g. the
   e-book landing page's primary capture form gets a heading of its own
   in place of the usual .lead-strip__copy sibling */
.lead-form__head {
  margin-bottom: var(--space-5);
}

/* Compact checkmark list for lead-magnet / landing copy */
.benefit-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin: var(--space-6) 0;
}

.benefit-list__item {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--text);
}

.benefit-list__icon {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  margin-top: 0.15em;
  color: var(--brand);
}

/* --------------------------------------------------------------------------
   21. ICO RATINGS / ICO DETAIL ADD-ONS
   New, minimal additions for the ratings grid + single-project profile.
   Kept on the existing token system (space/ink/line/radius/font vars).
   -------------------------------------------------------------------------- */

/* project logo — circular avatar, same visual family as .byline__avatar
   but built to hold an <img> (card size default, --lg for profile header) */
.ico-logo {
  width: 3rem;
  height: 3rem;
  flex-shrink: 0;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--ink-3);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

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

.ico-logo--lg {
  width: 4.5rem;
  height: 4.5rem;
}

/* logo + name row, used in rating cards and the detail-page header */
.ico-card__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

/* sub-score breakdown grid (team / tokenomics / audit / liquidity) */
.subscore-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--space-5);
}

.subscore-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5);
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
}

.subscore-card__note {
  font-size: 0.875rem;
  color: var(--text-dim);
  line-height: 1.6;
  margin: 0;
}

/* red-flags list */
.flag-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.flag-list__item {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  padding: var(--space-4);
  background: var(--ink-3);
  border: 1px solid var(--line);
  border-left: 3px solid var(--danger);
  border-radius: var(--radius-md);
  font-size: 0.9375rem;
  color: var(--text-dim);
  line-height: 1.55;
}

.flag-list__item .mono {
  color: var(--danger);
  font-weight: 600;
}

.flag-list__item strong {
  color: var(--text);
}

/* --------------------------------------------------------------------------
   22. CONFIRM PANEL (thank-you.html)
   Centered single-column confirmation block for lead-funnel end states.
   -------------------------------------------------------------------------- */
.confirm-panel {
  max-width: 40rem;
  margin-inline: auto;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
}

.confirm-panel__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--brand-dim);
  color: var(--brand);
  border: 1px solid rgba(55, 214, 168, 0.35);
  margin-bottom: var(--space-2);
}

.confirm-panel__deck {
  max-width: 46ch;
  margin-inline: auto;
}

.confirm-panel__actions {
  justify-content: center;
}

/* inline links inside callout copy (e.g. "see our full methodology") —
   no new class, just a link treatment on the existing .callout__body */
.callout__body a {
  color: var(--brand);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.callout__body a:hover {
  color: var(--brand-strong);
}

/* profile header: large logo beside name/category/website, used on the
   ICO detail page above the overall risk index */
.ico-profile-head {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  margin-bottom: var(--space-5);
}

.ico-profile-head h1 {
  margin: var(--space-2) 0 var(--space-2);
}

/* --------------------------------------------------------------------------
   23. MISSION HERO — landing page 1 only (views/index.ejs)
   "What we do" section above the article grid: eyebrow + redacted-bar title
   reveal + lede + CTA pair + stat-grid. Background is a slow-drifting grid
   + glow, kept under the content (z-index 0) and pure transform/opacity.
   -------------------------------------------------------------------------- */
.mission-hero {
  position: relative;
  overflow: hidden;
  padding-block: var(--space-10) var(--space-9);
  border-bottom: 1px solid var(--line);
}

/* cancel the double top-border this would otherwise create on the section
   directly below (see base rule 5: .section:first-of-type) */
.mission-hero + .section {
  border-top: 0;
}

.mission-hero__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.mission-hero__bg::before,
.mission-hero__bg::after {
  content: "";
  position: absolute;
  inset: -10%;
}

.mission-hero__bg::before {
  background-image: linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 64px 64px;
  opacity: 0.46;
  animation: mission-grid-drift 26s linear infinite;
}

.mission-hero__bg::after {
  background: radial-gradient(circle at 82% 12%, var(--brand-dim), transparent 55%),
    radial-gradient(circle at 8% 92%, var(--brand-dim), transparent 50%);
  animation: mission-glow-drift 16s ease-in-out infinite alternate;
}

@keyframes mission-grid-drift {
  to {
    transform: translate(64px, 64px);
  }
}

@keyframes mission-glow-drift {
  from {
    opacity: 0.55;
    transform: translateY(0);
  }
  to {
    opacity: 1;
    transform: translateY(-16px);
  }
}

.mission-hero__inner {
  position: relative;
  z-index: 1;
}

.mission-hero__copy {
  max-width: 54rem;
}

.mission-hero__lede {
  margin-top: var(--space-4);
}

/* redacted-bar reveal: a solid bar covers the headline and wipes off to the
   left on load, dossier-declassification style. Text itself is always in
   the DOM/visible — the bar is a decorative overlay, so nothing depends on
   JS or animation support to be legible. */
.mission-hero__title {
  position: relative;
  display: inline-block;
}

.mission-hero__redact {
  position: absolute;
  inset: -0.05em -0.06em;
  background: var(--text);
  border-radius: var(--radius-sm);
  transform-origin: right;
  animation: mission-redact-wipe 900ms var(--ease-out) 620ms both;
}

@keyframes mission-redact-wipe {
  from {
    transform: scaleX(1);
  }
  to {
    transform: scaleX(0);
  }
}

/* page-load stagger — eyebrow(1) → title(2) → lede(3) → actions(4) → stats(5) */
.mission-hero [data-load-in] {
  opacity: 0;
  filter: blur(6px);
  transform: translateY(18px);
  animation: mission-hero-in 700ms var(--ease-out) both;
}

.mission-hero [data-load-in="1"] {
  animation-delay: 80ms;
}
.mission-hero [data-load-in="2"] {
  animation-delay: 200ms;
}
.mission-hero [data-load-in="3"] {
  animation-delay: 340ms;
}
.mission-hero [data-load-in="4"] {
  animation-delay: 480ms;
}
.mission-hero [data-load-in="5"] {
  animation-delay: 620ms;
}

@keyframes mission-hero-in {
  from {
    opacity: 0;
    filter: blur(6px);
    transform: translateY(18px);
  }
  to {
    opacity: 1;
    filter: blur(0);
    transform: translateY(0);
  }
}

/* --------------------------------------------------------------------------
   24. STAT BOXES + COUNT-UP
   Markup: .stat-box > .stat-box__value > [data-count data-from data-to].
   cryptoreal.js animates the number on scroll-into-view (IntersectionObserver
   + rAF ease-out) and toggles .is-counting for the border-glow pulse below.
   -------------------------------------------------------------------------- */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-4);
  margin-top: var(--space-7);
}

@media (min-width: 720px) {
  .stat-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

.stat-box {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-5) var(--space-4);
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: transform var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out),
    box-shadow var(--dur-fast) var(--ease-out);
}

.stat-box:hover {
  transform: translateY(-3px);
  border-color: var(--brand);
  box-shadow: var(--shadow-raised);
}

/* conic sweep ring, faded in only while the counter is running */
.stat-box::before {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(120deg, transparent, var(--brand), transparent);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: 0;
}

.stat-box.is-counting::before {
  animation: stat-box-pulse 1.6s var(--ease-out);
}

@keyframes stat-box-pulse {
  0% {
    opacity: 0;
  }
  35% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

.stat-box__value {
  font-size: clamp(1.5rem, 3vw, 2.1rem);
  font-weight: 500;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.stat-box__label {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-dim);
}

/* --------------------------------------------------------------------------
   25. ARTICLE CARD MICRO-INTERACTIONS
   Scroll-reveal stagger is applied in JS via a per-card transitionDelay
   (reset after the transition ends so hover stays instant). This section
   covers the hover state: scanning conic-gradient border, thumbnail zoom,
   title underline slide.
   -------------------------------------------------------------------------- */
@property --card-angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

.article-card {
  --card-angle: 0deg;
}

.article-card::before {
  content: "";
  position: absolute;
  inset: -1px;
  z-index: 1;
  border-radius: inherit;
  padding: 1.5px;
  background: conic-gradient(from var(--card-angle), transparent 0deg, var(--brand) 40deg, transparent 100deg, transparent 360deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-fast) var(--ease-out);
}

.article-card:hover::before {
  opacity: 1;
  animation: card-scan 1.8s linear infinite;
}

@keyframes card-scan {
  to {
    --card-angle: 360deg;
  }
}

.article-card__media img {
  transition: transform 600ms var(--ease-out);
}

.article-card:hover .article-card__media img {
  transform: scale(1.06);
}

.article-card__title a {
  background-image: linear-gradient(var(--brand), var(--brand));
  background-repeat: no-repeat;
  background-position: left bottom;
  background-size: 0% 1.5px;
  padding-bottom: 0.05em;
  transition: background-size var(--dur-med) var(--ease-out);
}

.article-card:hover .article-card__title a {
  background-size: 100% 1.5px;
}

/* --------------------------------------------------------------------------
   26. ARTICLE DETAIL — READING PROGRESS BAR
   Fixed hairline above the sticky header, width driven by cryptoreal.js
   (rAF-throttled scroll handler — see initReadingProgress).
   -------------------------------------------------------------------------- */
.reading-progress {
  position: fixed;
  inset: 0 0 auto 0;
  height: 3px;
  z-index: 200;
  pointer-events: none;
}

.reading-progress__bar {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--brand), var(--warn), var(--danger));
  transition: width 80ms linear;
}

/* --------------------------------------------------------------------------
   27. TAG CHIP STAGGER-IN + HOVER POP (article detail tag-row)
   -------------------------------------------------------------------------- */
.tag-row .tag {
  opacity: 0;
  transform: translateY(6px) scale(0.95);
  animation: tag-chip-in 420ms var(--ease-out) both;
  transition: transform 200ms var(--ease-out), border-color 200ms var(--ease-out), color 200ms var(--ease-out);
}

.tag-row .tag:hover {
  transform: translateY(-2px) scale(1.05);
  border-color: var(--brand);
  color: var(--text);
}

@keyframes tag-chip-in {
  from {
    opacity: 0;
    transform: translateY(6px) scale(0.95);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

.tag-row .tag:nth-child(1) {
  animation-delay: 40ms;
}
.tag-row .tag:nth-child(2) {
  animation-delay: 100ms;
}
.tag-row .tag:nth-child(3) {
  animation-delay: 160ms;
}
.tag-row .tag:nth-child(4) {
  animation-delay: 220ms;
}
.tag-row .tag:nth-child(5) {
  animation-delay: 280ms;
}
.tag-row .tag:nth-child(6) {
  animation-delay: 340ms;
}
.tag-row .tag:nth-child(n + 7) {
  animation-delay: 400ms;
}

/* --------------------------------------------------------------------------
   28. NEWSLETTER GLOW REVEAL (partials/newsletter.ejs — listing + article)
   .lead-strip already gets the generic [data-reveal] fade/translate-in from
   section 20; --glow layers a one-shot accent pulse on top once visible.
   -------------------------------------------------------------------------- */
.lead-strip--glow.is-visible {
  animation: lead-strip-glow 1600ms var(--ease-out);
}

@keyframes lead-strip-glow {
  0% {
    box-shadow: 0 0 0 0 var(--brand-dim);
    border-color: var(--line);
  }
  40% {
    box-shadow: 0 0 0 8px var(--brand-dim);
    border-color: var(--brand);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(0, 0, 0, 0);
    border-color: var(--line);
  }
}

/* --------------------------------------------------------------------------
   29. SMOOTH-SCROLL ANCHOR OFFSET
   html{scroll-behavior:smooth} already lives in section 3 (base reset).
   This keeps anchor targets (#latest, #newsletter) from surfacing partly
   under the sticky masthead when a CTA scrolls to them.
   -------------------------------------------------------------------------- */
[id] {
  scroll-margin-top: 5.5rem;
}

/* --------------------------------------------------------------------------
   30. REDUCED MOTION — additions for sections 23-28
   The blanket override in section 20 already forces every animation /
   transition duration to ~0 with a single iteration, so page-load and
   hover keyframes above resolve straight to their end state (bar retracted,
   counters at final value via JS branch, markers visible). These rules
   remove the handful of *infinite/decorative* effects that override alone
   wouldn't otherwise stop from rendering their static first frame.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .mission-hero__bg::before,
  .mission-hero__bg::after,
  .article-card::before,
  .stat-box::before {
    animation: none !important;
  }

  .stat-box:hover,
  .pagination__link:hover {
    transform: none;
  }

  .reading-progress__bar {
    transition: none !important;
  }
}

/* --------------------------------------------------------------------------
   31. AMBIENT MOTION — always-on "the desk is alive" layer
   Everything in this section is a *periodic/infinite* decorative animation
   layered on top of the existing hover/scroll-reveal effects above. Per the
   motion spec: every infinite loop here animates ONLY transform / opacity /
   filter (glow = pre-rendered gradient/shadow on a pseudo-element whose
   OPACITY animates), marquees use translate3d + contain, and every rule is
   paired with a kill-switch in section 32 (prefers-reduced-motion: reduce).
   -------------------------------------------------------------------------- */

/* -- shared pulsing status dot (incident wire label + case-file eyebrow) -- */
@keyframes status-dot-pulse {
  0%,
  100% {
    opacity: 0.4;
    transform: scale(0.85);
  }
  50% {
    opacity: 1;
    transform: scale(1.15);
  }
}

/* --------------------------------------------------------------------------
   31a. INCIDENT WIRE — page-1 ticker, directly under the header
   Markup: .incident-wire > .incident-wire__label + .incident-wire__viewport
   > .incident-wire__track (article list duplicated 2x by the view for a
   seamless loop; the 2nd pass is aria-hidden/tabindex=-1 — decorative dupe).
   -------------------------------------------------------------------------- */
.incident-wire {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-4);
  background: var(--ink-2);
  border-bottom: 1px solid var(--line);
  padding-block: var(--space-2);
}

.incident-wire__label {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  padding-inline-start: var(--gutter);
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--text-dim);
  white-space: nowrap;
}

.incident-wire__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--danger);
  flex: none;
  animation: status-dot-pulse 1.8s ease-in-out infinite;
}

.incident-wire__viewport {
  position: relative;
  flex: 1;
  min-width: 0;
  overflow: hidden;
  contain: layout paint;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 6%, #000 94%, transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 6%, #000 94%, transparent 100%);
}

.incident-wire__track {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  width: max-content;
  padding-inline-end: var(--gutter);
  animation: incident-wire-scroll 45s linear infinite;
  will-change: transform;
}

.incident-wire:hover .incident-wire__track,
.incident-wire:focus-within .incident-wire__track {
  animation-play-state: paused;
}

.incident-wire__item {
  flex: none;
  font-size: 0.75rem;
  color: var(--text-dim);
  white-space: nowrap;
  transition: color var(--dur-fast) var(--ease-out);
}

.incident-wire__item:hover,
.incident-wire__item:focus-visible {
  color: var(--brand);
}

@keyframes incident-wire-scroll {
  from {
    transform: translate3d(0, 0, 0);
  }
  to {
    /* exactly half the track's width (2 identical passes) = seamless loop */
    transform: translate3d(-50%, 0, 0);
  }
}

/* --------------------------------------------------------------------------
   31b. HERO TYPEWRITER — rotating line under the mission-hero lede
   Markup: [data-typewriter][data-phrases="a|b|c"] > [data-typewriter-text]
   + .mission-hero__typewriter-cursor. Text is driven by cryptoreal.js
   (textContent updates); the cursor is a pure-CSS opacity blink so it still
   reads as "alive" even before JS finishes attaching listeners.
   -------------------------------------------------------------------------- */
.mission-hero__typewriter {
  display: flex;
  align-items: center;
  margin-top: var(--space-3);
  min-height: 1.3em;
  font-size: 0.9375rem;
  color: var(--brand);
  opacity: 0;
  filter: blur(6px);
  transform: translateY(18px);
  animation: mission-hero-in 700ms var(--ease-out) 420ms both;
}

.mission-hero__typewriter-cursor {
  display: inline-block;
  width: 0.55em;
  height: 1em;
  margin-left: 0.15em;
  background: var(--brand);
  animation: typewriter-blink 1s step-end infinite;
}

@keyframes typewriter-blink {
  0%,
  49% {
    opacity: 1;
  }
  50%,
  100% {
    opacity: 0;
  }
}

/* --------------------------------------------------------------------------
   31c. MISSION HERO — always-on conic border sweep + periodic scanline
   -------------------------------------------------------------------------- */
@property --hero-ring-angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

.mission-hero__inner {
  --hero-ring-angle: 0deg;
}

.mission-hero__inner::before {
  content: "";
  position: absolute;
  inset: calc(var(--space-6) * -1) calc(var(--space-4) * -1);
  z-index: -1;
  border-radius: var(--radius-lg);
  padding: 1.5px;
  background: conic-gradient(
    from var(--hero-ring-angle),
    transparent 0deg,
    var(--brand) 55deg,
    transparent 140deg,
    transparent 220deg,
    var(--brand-strong) 275deg,
    transparent 340deg,
    transparent 360deg
  );
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: 0.55;
  pointer-events: none;
  animation: hero-ring-sweep 8s linear infinite;
}

@keyframes hero-ring-sweep {
  to {
    --hero-ring-angle: 360deg;
  }
}

.mission-hero__scanline {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

.mission-hero__scanline::before {
  content: "";
  position: absolute;
  top: -30%;
  left: -20%;
  width: 34%;
  height: 160%;
  background: linear-gradient(
    115deg,
    transparent 0%,
    var(--brand-dim) 42%,
    rgba(255, 255, 255, 0.1) 50%,
    var(--brand-dim) 58%,
    transparent 100%
  );
  opacity: 0;
  transform: translate3d(-140%, 0, 0) rotate(6deg);
  animation: hero-scanline-sweep 7s ease-in-out infinite;
}

@keyframes hero-scanline-sweep {
  0%,
  80% {
    transform: translate3d(-140%, 0, 0) rotate(6deg);
    opacity: 0;
  }
  87% {
    opacity: 0.8;
  }
  100% {
    transform: translate3d(260%, 0, 0) rotate(6deg);
    opacity: 0;
  }
}

/* --------------------------------------------------------------------------
   31d. BUTTON AMBIENT ACCENTS — periodic gloss shine + glow breathe
   Additive modifier classes: .btn--shine, .btn--glow-breathe. Applied to the
   hero primary CTA and the newsletter submit buttons (views + partial).
   -------------------------------------------------------------------------- */
.btn--shine,
.btn--glow-breathe {
  position: relative;
}

.btn--shine {
  overflow: hidden;
}

.btn--shine::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 34%;
  height: 100%;
  background: linear-gradient(115deg, transparent 0%, rgba(255, 255, 255, 0.55) 50%, transparent 100%);
  opacity: 0;
  transform: translate3d(-140%, 0, 0) skewX(-18deg);
  pointer-events: none;
  animation: btn-shine-sweep 4.5s ease-in-out infinite;
}

@keyframes btn-shine-sweep {
  0%,
  66% {
    transform: translate3d(-140%, 0, 0) skewX(-18deg);
    opacity: 0;
  }
  74% {
    opacity: 0.9;
  }
  88%,
  100% {
    transform: translate3d(340%, 0, 0) skewX(-18deg);
    opacity: 0;
  }
}

.btn--glow-breathe::before {
  content: "";
  position: absolute;
  inset: -7px;
  z-index: -1;
  border-radius: inherit;
  background: radial-gradient(circle, var(--brand) 0%, transparent 72%);
  filter: blur(11px);
  opacity: 0.25;
  pointer-events: none;
  animation: btn-glow-breathe 3.2s ease-in-out infinite;
}

@keyframes btn-glow-breathe {
  0%,
  100% {
    opacity: 0.22;
  }
  50% {
    opacity: 0.55;
  }
}

/* input focus glow — a finite (non-looping) pulse on focus-in, not subject
   to the "infinite loop" reduced-motion rule; the base blanket override in
   section 20 already collapses its duration to ~0 under reduced motion. */
.field input:focus,
.field textarea:focus {
  animation: input-focus-glow 900ms var(--ease-out);
}

@keyframes input-focus-glow {
  0% {
    box-shadow: 0 0 0 0 var(--brand-dim);
  }
  50% {
    box-shadow: 0 0 0 6px var(--brand-dim);
  }
  100% {
    box-shadow: 0 0 0 3px var(--brand-dim);
  }
}

/* --------------------------------------------------------------------------
   31e. STAT BOXES — always-on staggered breathing border-glow
   (.stat-box::before stays the one-shot count-up pulse from section 24;
   ::after is the new ambient, always-on breathing ring layered under it.)
   -------------------------------------------------------------------------- */
.stat-box::after {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(120deg, var(--brand), transparent 55%, var(--brand));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: 0.15;
  pointer-events: none;
  animation: stat-box-breathe 4s ease-in-out infinite;
}

.stat-grid .stat-box:nth-child(1)::after {
  animation-delay: 0s;
}
.stat-grid .stat-box:nth-child(2)::after {
  animation-delay: 0.6s;
}
.stat-grid .stat-box:nth-child(3)::after {
  animation-delay: 1.2s;
}
.stat-grid .stat-box:nth-child(4)::after {
  animation-delay: 1.8s;
}

@keyframes stat-box-breathe {
  0%,
  100% {
    opacity: 0.15;
  }
  50% {
    opacity: 0.6;
  }
}

/* --------------------------------------------------------------------------
   31f. ARTICLE CARDS — ambient top-border shimmer + hero conic sweep
   (.article-card::before stays the hover-only scan ring from section 25;
   ::after is the new ambient top-edge shimmer, staggered by nth-child so
   the grid comes alive unevenly rather than in lockstep.)
   -------------------------------------------------------------------------- */
.article-card::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 40%;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--brand), transparent);
  opacity: 0.6;
  pointer-events: none;
  z-index: 2;
  transform: translate3d(-100%, 0, 0);
  animation: card-top-shimmer 5.5s linear infinite;
}

@keyframes card-top-shimmer {
  to {
    transform: translate3d(350%, 0, 0);
  }
}

.article-card:nth-child(2n)::after {
  animation-delay: 1.1s;
  animation-duration: 6.4s;
}
.article-card:nth-child(3n)::after {
  animation-delay: 2.4s;
  animation-duration: 4.8s;
}
.article-card:nth-child(4n)::after {
  animation-delay: 0.5s;
  animation-duration: 5.9s;
}

/* hero card: full slow conic border sweep instead of the top-edge shimmer,
   always on (strengthens further — faster + brighter — on hover via the
   existing section-25 hover rule). */
.article-card.article-card--hero::after {
  display: none;
}

.article-card--hero::before {
  opacity: 0.4;
  animation: card-scan 6.5s linear infinite;
}

.article-card--hero:hover::before {
  opacity: 1;
  animation: card-scan 2.2s linear infinite;
}

/* --------------------------------------------------------------------------
   31g. SECTION HEADING — underline pulse + text shimmer sweep
   Markup: <h2/h1 class="h-display h-section h-section--live"><span
   class="h-section__shimmer" aria-hidden="true"></span>Fresh from the
   desk</h2> — applies on every listing page (1 and 2+ alike).
   -------------------------------------------------------------------------- */
.h-section--live {
  position: relative;
  display: inline-block;
}

.h-section--live::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -0.3em;
  height: 2px;
  width: 2.75rem;
  background: var(--brand);
  transform-origin: left center;
  animation: heading-underline-pulse 6s ease-in-out infinite;
}

@keyframes heading-underline-pulse {
  0%,
  55% {
    transform: scaleX(1);
    opacity: 0.65;
  }
  72% {
    transform: scaleX(2.6);
    opacity: 1;
  }
  100% {
    transform: scaleX(1);
    opacity: 0.65;
  }
}

.h-section__shimmer {
  position: absolute;
  top: 0;
  left: -40%;
  width: 30%;
  height: 100%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.5), transparent);
  mix-blend-mode: overlay;
  pointer-events: none;
  opacity: 0;
  transform: translate3d(-40%, 0, 0);
  animation: heading-shimmer-sweep 6s ease-in-out infinite;
}

@keyframes heading-shimmer-sweep {
  0%,
  68% {
    transform: translate3d(-40%, 0, 0);
    opacity: 0;
  }
  76% {
    opacity: 0.9;
  }
  94%,
  100% {
    transform: translate3d(420%, 0, 0);
    opacity: 0;
  }
}

/* --------------------------------------------------------------------------
   31h. NEWSLETTER STRIP — always-on slow conic border sweep
   -------------------------------------------------------------------------- */
@property --lead-angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

.lead-strip {
  --lead-angle: 0deg;
  position: relative;
}

.lead-strip::after {
  content: "";
  position: absolute;
  inset: -1px;
  z-index: 1;
  border-radius: inherit;
  padding: 1.5px;
  background: conic-gradient(
    from var(--lead-angle),
    transparent 0deg,
    var(--brand) 50deg,
    transparent 130deg,
    transparent 230deg,
    var(--brand-strong) 280deg,
    transparent 340deg,
    transparent 360deg
  );
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: 0.5;
  pointer-events: none;
  animation: lead-strip-sweep 9s linear infinite;
}

@keyframes lead-strip-sweep {
  to {
    --lead-angle: 360deg;
  }
}

/* --------------------------------------------------------------------------
   31i. ARTICLE — case-file eyebrow, title redact, staggered header, node bg
   -------------------------------------------------------------------------- */
.case-file-header {
  position: relative;
  overflow: hidden;
}

.case-file-header__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.case-file-header__bg::before {
  content: "";
  position: absolute;
  inset: -10%;
  background-image: linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 64px 64px;
  opacity: 0.24;
  animation: mission-grid-drift 26s linear infinite;
}

.case-file-header .container {
  position: relative;
  z-index: 1;
}

.case-file-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--text-dim);
}

.case-file-eyebrow__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--danger);
  flex: none;
  animation: status-dot-pulse 1.8s ease-in-out infinite;
}

.case-file-header [data-load-in] {
  opacity: 0;
  filter: blur(6px);
  transform: translateY(18px);
  animation: mission-hero-in 700ms var(--ease-out) both;
}

.case-file-header [data-load-in="1"] {
  animation-delay: 60ms;
  margin-bottom: var(--space-3);
}
.case-file-header [data-load-in="2"] {
  animation-delay: 160ms;
}
.case-file-header [data-load-in="3"] {
  animation-delay: 300ms;
}

.article-title {
  position: relative;
  display: inline-block;
}

.article-title__redact {
  position: absolute;
  inset: -0.05em -0.06em;
  background: var(--text);
  border-radius: var(--radius-sm);
  transform-origin: right;
  animation: mission-redact-wipe 900ms var(--ease-out) 180ms both;
}

/* --------------------------------------------------------------------------
   31j. READING PROGRESS — glowing head node
   -------------------------------------------------------------------------- */
.reading-progress__bar {
  position: relative;
}

.reading-progress__bar::after {
  content: "";
  position: absolute;
  right: -1px;
  top: 50%;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--danger);
  box-shadow: 0 0 6px 2px var(--danger);
  transform: translate(50%, -50%);
}

.reading-progress__bar::before {
  content: "";
  position: absolute;
  right: -5px;
  top: 50%;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--danger);
  filter: blur(4px);
  opacity: 0.4;
  pointer-events: none;
  transform: translate(50%, -50%) scale(0.85);
  animation: reading-head-glow 1.6s ease-in-out infinite;
}

@keyframes reading-head-glow {
  0%,
  100% {
    opacity: 0.35;
    transform: translate(50%, -50%) scale(0.85);
  }
  50% {
    opacity: 0.8;
    transform: translate(50%, -50%) scale(1.3);
  }
}

/* --------------------------------------------------------------------------
   31k. ARTICLE TAG CHIPS — sequential glow chase (one chip after another)
   Additive modifier: .tag-row--live (article.ejs only — listing/filter tag
   rows elsewhere keep the plain entrance-only behaviour from section 27).
   -------------------------------------------------------------------------- */
.tag-row--live .tag {
  position: relative;
}

.tag-row--live .tag::after {
  content: "";
  position: absolute;
  inset: -2px;
  border-radius: inherit;
  background: var(--brand);
  filter: blur(6px);
  opacity: 0;
  pointer-events: none;
  animation: tag-glow-cycle 4.8s ease-in-out infinite;
}

.tag-row--live .tag:nth-child(1)::after {
  animation-delay: 0.4s;
}
.tag-row--live .tag:nth-child(2)::after {
  animation-delay: 1s;
}
.tag-row--live .tag:nth-child(3)::after {
  animation-delay: 1.6s;
}
.tag-row--live .tag:nth-child(4)::after {
  animation-delay: 2.2s;
}
.tag-row--live .tag:nth-child(5)::after {
  animation-delay: 2.8s;
}
.tag-row--live .tag:nth-child(n + 6)::after {
  animation-delay: 3.4s;
}

@keyframes tag-glow-cycle {
  0%,
  85%,
  100% {
    opacity: 0;
  }
  8% {
    opacity: 0.55;
  }
  18% {
    opacity: 0;
  }
}

/* --------------------------------------------------------------------------
   31l. BLOCKQUOTES — slow vertical gradient sweep on the left border
   -------------------------------------------------------------------------- */
.prose blockquote {
  position: relative;
}

.prose blockquote::before {
  content: "";
  position: absolute;
  left: -3px;
  top: -15%;
  width: 3px;
  height: 22%;
  background: linear-gradient(var(--brand-strong), transparent);
  opacity: 0.75;
  pointer-events: none;
  animation: blockquote-sweep 4.5s linear infinite;
}

@keyframes blockquote-sweep {
  to {
    transform: translateY(620%);
  }
}

/* --------------------------------------------------------------------------
   32. REDUCED MOTION — kill-switch for every infinite loop in section 31
   Mirrors the section-30 pattern: the blanket override already zeroes
   animation-duration/iteration-count everywhere, these rules additionally
   fully disable (or freeze to a sane static state) anything that would
   otherwise still visibly loop/sweep, and restore full readability
   (ticker → static list, typewriter → first phrase as plain text).
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .incident-wire__track {
    animation: none !important;
    transform: none !important;
  }

  .incident-wire__viewport {
    overflow-x: auto;
  }

  .incident-wire__item[aria-hidden="true"] {
    display: none;
  }

  .incident-wire__dot,
  .case-file-eyebrow__dot,
  .mission-hero__inner::before,
  .mission-hero__scanline::before,
  .mission-hero__typewriter-cursor,
  .btn--shine::after,
  .btn--glow-breathe::before,
  .stat-box::after,
  .article-card::after,
  .article-card--hero::before,
  .h-section--live::after,
  .h-section__shimmer,
  .lead-strip::after,
  .case-file-header__bg::before,
  .reading-progress__bar::before,
  .tag-row--live .tag::after,
  .prose blockquote::before {
    animation: none !important;
  }

  .mission-hero__scanline::before,
  .btn--shine::after,
  .h-section__shimmer,
  .stat-box::after,
  .article-card::after,
  .tag-row--live .tag::after,
  .prose blockquote::before {
    opacity: 0 !important;
  }

  .mission-hero__typewriter-cursor {
    opacity: 0 !important;
  }

  .mission-hero__inner::before,
  .lead-strip::after {
    opacity: 0.35 !important;
  }

  .article-card--hero::before {
    opacity: 0 !important;
  }

  .btn--glow-breathe::before {
    opacity: 0.3 !important;
  }
}

/* --------------------------------------------------------------------------
   33. MOBILE HOTFIX — min-content blowout gridu
   1fr grid tracky majú floor = min-content obsahu. Eyebrow je inline-flex
   (flex default nowrap), takže jeho min-content ("BONZO FINANCE · REKT" v
   jednom riadku ≈ 435px) roztlačil track karty na ~485px a celú stránku na
   505px — na 390px mobile všetko pretekalo doprava. min-width:0 vracia
   trackom/kartám právo zúžiť sa, eyebrow smie wrapovať; overflow-x:clip na
   body je poistka, nech žiadny dekoratívny element nikdy nerozšíri stránku.
   -------------------------------------------------------------------------- */
.grid--latest > *,
.grid--cards > *,
.article-card,
.article-card__body,
.article-card--side {
  min-width: 0;
}

.article-card .eyebrow {
  flex-wrap: wrap;
}

/* rekt obsah je plný dlhých nezalomiteľných stringov (0x hashe, URL) —
   bez tohto jediný hash-link roztiahne .prose (a celý dokument) na ~650px */
.prose {
  overflow-wrap: anywhere;
}

body {
  overflow-x: clip;
}

/* --------------------------------------------------------------------------
   34. ARTICLE ENRICHMENT — cover / card+byline author / case summary /
   in-body visuals / pullquote / lede / section numbering.
   Client feedback fix: articles were "a boring wall of text" with tag combos
   above the title that read like someone else's identity. This section
   covers the card byline chip, the article hero cover, the case-summary
   panel, and the richer in-body furniture lib/enrich.js emits (figures,
   pullquotes, lede paragraph, numbered section heads).
   -------------------------------------------------------------------------- */

/* -- 34a. card byline (replaces the old tag-eyebrow above card titles) -- */
.card-author {
  display: inline-block;
  font-size: 0.6875rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--brand);
}

/* -- 34b. byline avatar — initials circle + 5 deterministic author hues -- */
.byline__avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0;
  color: #fff;
  background: var(--author-color, var(--brand));
  border: 1px solid rgba(255, 255, 255, 0.15);
  flex-shrink: 0;
}

.author-hue-0 {
  --author-color: #4f8cff;
}
.author-hue-1 {
  --author-color: #9d6bff;
}
.author-hue-2 {
  --author-color: #1fbf8f;
}
.author-hue-3 {
  --author-color: #e0a53a;
}
.author-hue-4 {
  --author-color: #ef6fa0;
}

.byline__name {
  color: var(--text);
  font-weight: 600;
}

.byline__meta {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5em;
}

.byline__meta > span[aria-hidden="true"] {
  color: var(--line);
}

/* -- 34c. hero cover — rounded framed figure between byline and body -- */
.article-cover {
  margin: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--ink-2);
  overflow: hidden;
  box-shadow: inset 0 0 40px rgba(0, 0, 0, 0.25);
}

:root[data-theme="light"] .article-cover {
  box-shadow: inset 0 0 30px rgba(20, 30, 50, 0.06);
}

.article-cover img {
  display: block;
  width: 100%;
  height: auto;
}

/* -- 34d. case summary panel — mono micro-labels + definition grid -- */
.case-summary {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5);
  margin-bottom: var(--space-7);
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-left: 3px solid var(--brand);
  border-radius: var(--radius-md);
}

.case-summary__label {
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--text-dim);
}

.case-summary__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3) var(--space-6);
  margin: 0;
}

@media (min-width: 640px) {
  .case-summary__grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

.case-summary__row {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  min-width: 0;
}

.case-summary__row dt {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-dim);
}

.case-summary__row dd {
  margin: 0;
  font-size: 0.9375rem;
  color: var(--text);
  overflow-wrap: anywhere;
}

@media (max-width: 480px) {
  .case-summary {
    padding: var(--space-4);
  }
}

/* -- 34e. in-body visual figures (charts/diagrams emitted by lib/enrich.js) -- */
.article-visual {
  margin-block: var(--space-7);
  padding: var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--ink-2);
}

.article-visual svg,
.article-visual img {
  display: block;
  width: 100%;
  height: auto;
}

.article-visual figcaption {
  margin-top: var(--space-3);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  color: var(--text-dim);
}

/* transparent-friendly variant for inline data charts that shouldn't sit in
   a filled panel (e.g. sparklines dropped directly into the flow) */
.article-visual--chart {
  background: transparent;
  border-style: dashed;
}

/* -- 34f. pullquote — oversized glyph + generous whitespace, subtle reveal -- */
.pullquote {
  position: relative;
  font-size: clamp(1.35rem, 2.4vw, 1.9rem);
  padding-block: var(--space-2);
}

.pullquote::before {
  content: "\201C";
  position: absolute;
  left: -0.02em;
  top: -0.35em;
  font-family: var(--font-display);
  font-size: 3.5em;
  line-height: 1;
  color: var(--brand);
  opacity: 0.25;
  pointer-events: none;
}

/* -- 34g. lede paragraph — first-graf emphasis lib/enrich.js can opt into -- */
.prose-lede {
  font-size: 1.15em;
  line-height: 1.65;
  color: var(--text);
}

/* -- 34h. numbered section heads — mono accent number + thin trailing rule --
   Reuses the existing .prose h2 marker/reveal animation (section 20 in this
   file); .sec-h is applied on the same h2, .sec-num wraps just the digits. */
.sec-h {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  padding-left: 0 !important;
}

/* higher specificity than .prose h2::before (section 20) so the diamond
   marker never double-renders next to the mono section number below */
.prose h2.sec-h::before {
  display: none;
}

.sec-num {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--brand);
  flex-shrink: 0;
}

.sec-h::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
  align-self: center;
  min-width: 1.5rem;
}

/* --------------------------------------------------------------------------
   35. ADMIN PANEL — login card, header, subscriber table, newsletter
   campaigns (badges + progress), AI draft cards, confirm modal, toast,
   article preview banner. Builds on section 21 (.container--narrow,
   .admin-card, .field, .btn, .status-tag, .admin-table*) — this section
   only ADDS what 21 doesn't already cover.
   -------------------------------------------------------------------------- */

/* -- 35a. login page — centred card, no site chrome -- */
.admin-login-body {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background:
    radial-gradient(680px 420px at 50% -10%, var(--brand-dim), transparent 62%),
    var(--ink);
}

.admin-login-wrap {
  width: 100%;
  padding: var(--space-6) var(--gutter);
}

.admin-login-eyebrow {
  display: block;
  margin-bottom: var(--space-2);
}

.admin-card__title {
  font-size: clamp(1.3rem, 2.4vw, 1.6rem);
  margin: 0 0 var(--space-5);
}

.admin-login-submit {
  margin-top: var(--space-2);
}

/* -- 35b. admin shell — custom lean header (not the public masthead/nav) -- */
.admin-body {
  min-height: 100vh;
}

.admin-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--ink-2);
  border-bottom: 1px solid var(--line);
  backdrop-filter: saturate(1.1) blur(10px);
}

.admin-header__bar {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  padding-block: var(--space-4);
  min-width: 0;
}

.admin-header__tag {
  flex-shrink: 0;
}

.admin-header__nav {
  display: none;
  align-items: center;
  gap: var(--space-5);
  margin-left: var(--space-2);
  min-width: 0;
  overflow-x: auto;
}

.admin-header__nav a {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  color: var(--text-dim);
  white-space: nowrap;
  transition: color var(--dur-fast) var(--ease-out);
}

.admin-header__nav a:hover {
  color: var(--brand);
}

.admin-header__logout {
  margin-left: auto;
  flex-shrink: 0;
}

@media (min-width: 720px) {
  .admin-header__nav {
    display: flex;
  }
}

.admin-main .admin-section:first-of-type {
  border-top: 0;
}

/* -- 35c. section head extras -- */
.admin-count-badge {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--brand);
  background: var(--brand-dim);
  border: 1px solid rgba(55, 214, 168, 0.3);
  border-radius: 999px;
  padding: 0.3rem 0.85rem;
  white-space: nowrap;
}

.admin-empty {
  color: var(--text-dim);
  font-size: 0.9375rem;
  padding: var(--space-6);
  border: 1px dashed var(--line);
  border-radius: var(--radius-lg);
  text-align: center;
}

.admin-empty--sub {
  padding: var(--space-5);
  margin-top: var(--space-4);
}

/* -- 35d. subscriber table — scrollable panel so a long list doesn't push
   the newsletter/draft sections far down the page -- */
.admin-table-wrap--scroll {
  max-height: 26rem;
  overflow-y: auto;
}

/* -- 35e. newsletter campaigns — list of cards under the send form -- */
.admin-campaigns {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: var(--space-5);
}

.campaign-item {
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--space-4) var(--space-5);
  min-width: 0;
}

.campaign-item__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
  min-width: 0;
}

.campaign-item__subject {
  font-weight: 600;
  color: var(--text);
  min-width: 0;
  overflow-wrap: anywhere;
}

.campaign-badge {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border-radius: 999px;
  padding: 0.25rem 0.7rem;
  white-space: nowrap;
  flex-shrink: 0;
}

.campaign-badge--pending,
.campaign-badge--sending {
  color: var(--brand);
  background: var(--brand-dim);
  border: 1px solid rgba(55, 214, 168, 0.3);
}

.campaign-badge--sent {
  color: var(--brand-strong);
  background: var(--brand-dim);
  border: 1px solid rgba(55, 214, 168, 0.3);
}

.campaign-badge--partial {
  color: var(--warn);
  background: var(--warn-dim);
  border: 1px solid rgba(245, 184, 65, 0.35);
}

.campaign-badge--failed {
  color: var(--danger);
  background: var(--danger-dim);
  border: 1px solid rgba(245, 84, 78, 0.35);
}

.campaign-progress {
  height: 6px;
  border-radius: 999px;
  background: var(--ink-4);
  overflow: hidden;
  margin-bottom: var(--space-3);
}

.campaign-progress__bar {
  height: 100%;
  background: var(--brand);
  border-radius: 999px;
  transition: width var(--dur-med) var(--ease-out);
}

.campaign-item[data-state="sending"] .campaign-progress__bar {
  background: linear-gradient(90deg, var(--brand), var(--brand-strong), var(--brand));
  background-size: 200% 100%;
  animation: campaign-bar-sweep 1.6s linear infinite;
}

@keyframes campaign-bar-sweep {
  from { background-position: 0% 0; }
  to { background-position: -200% 0; }
}

.campaign-item__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  font-size: 0.8125rem;
  color: var(--text-dim);
}

/* -- 35f. AI draft cards — result of /admin/articles/draft -- */
.admin-draft-result {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  margin-top: var(--space-5);
}

.draft-card {
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  min-width: 0;
}

.draft-card__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2) var(--space-4);
  margin-bottom: var(--space-4);
  min-width: 0;
}

.draft-card__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--text);
  min-width: 0;
  overflow-wrap: anywhere;
}

.draft-card__author {
  font-size: 0.8125rem;
  color: var(--text-dim);
  white-space: nowrap;
}

.draft-card__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.draft-card__note {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--line);
  font-size: 0.875rem;
  color: var(--text-dim);
}

.draft-card__note a {
  color: var(--brand);
}

.btn-danger-ghost {
  background: transparent;
  border-color: rgba(245, 84, 78, 0.4);
  color: var(--danger);
}

.btn-danger-ghost:hover {
  background: var(--danger-dim);
  border-color: var(--danger);
}

/* -- 35g. spinner — inline on buttons mid-request -- */
.btn-spinner {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-top-color: transparent;
  opacity: 0.85;
  animation: btn-spin 700ms linear infinite;
}

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

.btn:disabled {
  opacity: 0.65;
  cursor: default;
  pointer-events: none;
}

/* -- 35h. confirm modal — shared by newsletter send + publish + discard -- */
.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-5);
  background: rgba(3, 6, 10, 0.66);
  backdrop-filter: blur(3px);
}

.modal-backdrop[hidden] {
  display: none;
}

.modal {
  width: 100%;
  max-width: 26rem;
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  box-shadow: var(--shadow-raised);
}

.modal h3 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--text);
  margin: 0 0 var(--space-3);
}

.modal p {
  color: var(--text-dim);
  font-size: 0.9375rem;
  line-height: 1.55;
  margin: 0 0 var(--space-5);
}

.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-3);
}

/* -- 35i. toast -- */
.toast {
  position: fixed;
  left: 50%;
  bottom: var(--space-6);
  transform: translateX(-50%) translateY(16px);
  z-index: 210;
  background: var(--ink-2);
  border: 1px solid var(--brand);
  color: var(--text);
  font-weight: 600;
  font-size: 0.875rem;
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-5);
  box-shadow: var(--shadow-raised);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-med) var(--ease-out), transform var(--dur-med) var(--ease-out);
  max-width: calc(100vw - 2 * var(--space-5));
}

.toast.show {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

.toast--err {
  border-color: var(--danger);
}

/* -- 35j. article preview banner (article.ejs, previewMode:true) — sits
   in normal flow above the masthead, so it never fights the masthead's
   own position:sticky/z-index. -- */
.preview-banner {
  background: var(--brand);
  color: var(--on-brand);
  text-align: center;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.5rem var(--gutter);
}

/* -- 35k. mobile -- */
@media (max-width: 640px) {
  .admin-header__bar {
    gap: var(--space-3);
  }

  .admin-count-badge {
    align-self: flex-start;
  }

  .campaign-item__head {
    flex-direction: column;
    align-items: flex-start;
  }

  .draft-card__head {
    flex-direction: column;
    align-items: flex-start;
  }

  .draft-card__actions {
    width: 100%;
  }

  .draft-card__actions .btn {
    flex: 1 1 auto;
  }

  .modal {
    padding: var(--space-5);
  }
}

/* --------------------------------------------------------------------------
   36. IN-ARTICLE PHOTO INSETS (real Pexels stock photos, lib/enrich.js)
   .article-visual--photo is a variant of .article-visual (section 34e) used
   when enrichArticle() receives a real photo URL instead of falling back to
   generated SVG artwork. The outer figure already gets border/radius/panel
   background from .article-visual — this only styles the <img> itself and
   the caption text alignment. Listing cards (.article-card__media img,
   section ~26) already carry object-fit: cover + aspect-ratio, nothing to
   add there.
   -------------------------------------------------------------------------- */
.article-visual--photo img {
  border-radius: var(--radius-sm);
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

/* no hover scale here on purpose — that treatment stays on listing cards
   (.article-card:hover .article-card__media img, section ~26); in-article
   photo insets stay static so they read as documentary stills, not UI chrome */
