/* ==========================================================================
   Shopsiguide — Main Stylesheet
   Modern editorial theme. Warm paper ground, Fraunces display serif over
   Inter, category colour as the only chroma.

   Everything visual is a token in section 1. Change the design there, not
   in the component rules below.
   ========================================================================== */

/* ==========================================================================
   1. Design Tokens
   ========================================================================== */

:root {
  /* Typeface */
  --font-display: 'Outfit', 'Inter', system-ui, -apple-system, sans-serif;
  --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;

  /* Type scale — 1.25 minor third, fluid at the display end */
  --text-2xs: 0.6875rem;  /* 11px */
  --text-xs:  0.75rem;    /* 12px */
  --text-sm:  0.8125rem;  /* 13px */
  --text-base:0.9375rem;  /* 15px */
  --text-md:  1rem;       /* 16px */
  --text-lg:  1.125rem;   /* 18px */
  --text-xl:  1.375rem;   /* 22px */
  --text-2xl: clamp(1.5rem, 1.2rem + 1.4vw, 1.875rem);
  --text-3xl: clamp(1.875rem, 1.4rem + 2.2vw, 2.75rem);

  --leading-tight: 1.18;
  --leading-snug: 1.35;
  --leading-body: 1.72;

  /* Spacing — 4px base */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;
  --space-16: 4rem;
  --space-20: 5rem;

  /* Colour — Aurora. A lilac-tinted ground under a violet-to-pink wash, with
     deep indigo ink. The ten category hues remain the only other chroma, so
     the brand violet sits beside them without competing. Light is the bare
     :root default; the dark palette below only swaps these same tokens. */
  --ground: #f7f6fb;
  --surface: #ffffff;
  --surface-sunken: #eeecf7;
  --ink: #16142b;
  --ink-soft: #413d60;
  --ink-muted: #5c5780;
  --ink-faint: #726d94;
  --border: #e5e1f2;
  --border-strong: #d2ccea;

  --brand: #6d4aff;
  --brand-hover: #5a35f0;
  --brand-soft: #efeaff;
  --brand-ring: rgba(109, 74, 255, 0.22);

  --accent: #16142b;
  --accent-contrast: #ffffff;
  --link: var(--brand);
  --focus: var(--brand);
  --overlay: rgba(12, 10, 26, 0.58);
  --glow: radial-gradient(80% 110% at 50% 0%, rgba(109, 74, 255, 0.13), rgba(255, 120, 200, 0.09) 45%, transparent 75%);

  /* Glass — the masthead island. Tint is deliberately low so the page shows
     through; sheen and edge are what actually make it read as glass rather
     than as a flat translucent panel. */
  --glass-bg: rgba(255, 255, 255, 0.55);
  --glass-bg-solid: rgba(255, 255, 255, 0.90);
  --glass-sheen: rgba(255, 255, 255, 0.85);
  --glass-sheen-mid: rgba(255, 255, 255, 0.20);
  --glass-edge: rgba(255, 255, 255, 0.90);
  --glass-edge-low: rgba(109, 74, 255, 0.09);
  --glass-drop: rgba(60, 40, 140, 0.38);


  /* Form */
  --radius-sm: 8px;
  --radius: 14px;
  --radius-lg: 22px;
  --radius-xl: 28px;
  --radius-pill: 999px;

  --shadow-sm: 0 2px 8px rgba(80, 60, 160, 0.07);
  --shadow: 0 8px 26px rgba(80, 60, 160, 0.10);
  --shadow-lg: 0 22px 60px rgba(80, 60, 160, 0.18);

  /* 1200 left ~360px of dead gutter each side on a 1920 screen, which read
     as a cramped column rather than a deliberate measure. Article pages keep
     their own narrower shell below — that one is a reading constraint. */
  --container: 1320px;
  /* Footer watermark: sized in container-query units so the wordmark spans
     the column band at every width. "Shopsiguide" in Outfit 700 at this
     tracking runs ~4.67x its font-size. Sized against the VIEWPORT, not the
     column band, so it can grow past the 1320px container and still show the
     whole word — 21cqw was the ceiling while it was boxed into the band. */
  --watermark-size: 21vw;
  --measure: 40rem; /* article reading column ~66 chars */

  /* Article page geometry. The page spans the same --container as every
     other template; a left contents rail and a right merchant rail flank the
     text so the reading column stays ~70 characters instead of stretching to
     the full width. --article-main is whatever the shell leaves over. */
  --article-toc: 200px;
  --article-rail: 300px;
  --article-gap: var(--space-12);
  --article-main: calc(var(--container) - (var(--space-5) * 2)
                       - var(--article-toc) - var(--article-rail)
                       - (var(--article-gap) * 2));

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --transition: 0.2s var(--ease);
}

/* Dark theme — only the tokens change. Default (no data-theme) follows the OS. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --ground: #0f0d1c;
    --surface: #171431;
    --surface-sunken: #1d1940;
    --ink: #f3f1fc;
    --ink-soft: #cdc8e8;
    --ink-muted: #9b95bf;
    --ink-faint: #8b85b0;
    --border: #2a2550;
    --border-strong: #3c3570;

    --brand: #a78bff;
    --brand-hover: #bda6ff;
    --brand-soft: #241e48;
    --brand-ring: rgba(167, 139, 255, 0.3);

    --accent: #f3f1fc;
    --accent-contrast: #0f0d1c;
    --link: var(--brand);
    --focus: var(--brand);
    --overlay: rgba(0, 0, 0, 0.62);
    --glow: radial-gradient(80% 110% at 50% 0%, rgba(167, 139, 255, 0.16), rgba(255, 120, 200, 0.07) 45%, transparent 75%);

    --glass-bg: rgba(15, 13, 28, 0.52);
    --glass-bg-solid: rgba(15, 13, 28, 0.90);
    --glass-sheen: rgba(255, 255, 255, 0.10);
    --glass-sheen-mid: rgba(255, 255, 255, 0.02);
    --glass-edge: rgba(255, 255, 255, 0.13);
    --glass-edge-low: rgba(0, 0, 0, 0.55);
    --glass-drop: rgba(0, 0, 0, 0.85);

    --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.45);
    --shadow: 0 8px 26px rgba(0, 0, 0, 0.5);
    --shadow-lg: 0 22px 60px rgba(0, 0, 0, 0.65);
  }
}

:root[data-theme='dark'] {
  --ground: #0f0d1c;
  --surface: #171431;
  --surface-sunken: #1d1940;
  --ink: #f3f1fc;
  --ink-soft: #cdc8e8;
  --ink-muted: #9b95bf;
  --ink-faint: #8b85b0;
  --border: #2a2550;
  --border-strong: #3c3570;

  --brand: #a78bff;
  --brand-hover: #bda6ff;
  --brand-soft: #241e48;
  --brand-ring: rgba(167, 139, 255, 0.3);

  --accent: #f3f1fc;
  --accent-contrast: #0f0d1c;
  --link: var(--brand);
  --focus: var(--brand);
  --overlay: rgba(0, 0, 0, 0.62);
  --glow: radial-gradient(80% 110% at 50% 0%, rgba(167, 139, 255, 0.16), rgba(255, 120, 200, 0.07) 45%, transparent 75%);

  --glass-bg: rgba(15, 13, 28, 0.52);
  --glass-bg-solid: rgba(15, 13, 28, 0.90);
  --glass-sheen: rgba(255, 255, 255, 0.10);
  --glass-sheen-mid: rgba(255, 255, 255, 0.02);
  --glass-edge: rgba(255, 255, 255, 0.13);
  --glass-edge-low: rgba(0, 0, 0, 0.55);
  --glass-drop: rgba(0, 0, 0, 0.85);

  --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.45);
  --shadow: 0 8px 26px rgba(0, 0, 0, 0.5);
  --shadow-lg: 0 22px 60px rgba(0, 0, 0, 0.65);
}

/* ==========================================================================
   2. Reset & Base
   ========================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 16px;
  scroll-behavior: smooth;
  color-scheme: light dark;
}

/* Lenis animates the scroll position itself; leaving CSS smooth scrolling on
   would have the browser and the library easing the same property at once. */
html.has-lenis {
  scroll-behavior: auto;
}

body {
  font-family: var(--font-sans);
  background-color: var(--ground);
  color: var(--ink);
  line-height: var(--leading-body);
  font-size: var(--text-md);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

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

img {
  max-width: 100%;
  display: block;
}

ul {
  list-style: none;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  /* Outfit is a geometric sans — it takes tighter tracking than the serif it
     replaced without the counters closing up. */
  letter-spacing: -0.028em;
  line-height: var(--leading-tight);
  color: var(--ink);
  text-wrap: balance;
}

::selection {
  background: var(--ink);
  color: var(--ground);
}

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

/* ==========================================================================
   3. Container
   ========================================================================== */

.container {
  max-width: var(--container);
  margin: 0 auto;
  padding-inline: var(--space-5);
}

/* ==========================================================================
   4. Header
   ========================================================================== */

/* A floating glass island rather than a full-bleed bar: the wrapper stays
   transparent and only .header-inner is painted, so page content slides
   visibly beneath a detached, rounded pill. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: none;
  border: 0;
  /* Padding on the transparent wrapper, not a sticky offset — the pill then
     sits the same distance from the top whether stuck or at rest. */
  padding: var(--space-3) var(--space-4);
}

.site-header .container,
.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-6);
  min-height: 60px;
  padding-block: var(--space-2);
  padding-inline: var(--space-5);

  /* Also the positioning context for the mobile drawer — see the note in
     the 768px block. */
  position: relative;

  /* The glass, in three layers:
       1. a sheen gradient — the specular band that sells it as a curved
          surface rather than a flat translucent rectangle;
       2. a low tint of the theme's own ground colour, kept transparent
          enough that the page is visibly refracted underneath;
       3. the blur, with saturation pushed up so colour passing beneath
          blooms through instead of going grey.
     Sheen and edges do most of the work — a blur alone over a pale page has
     nothing to refract and just reads as a solid panel. */
  background-image: linear-gradient(
    to bottom,
    var(--glass-sheen) 0%,
    var(--glass-sheen-mid) 42%,
    transparent 72%);
  background-color: var(--glass-bg);
  -webkit-backdrop-filter: saturate(200%) blur(26px);
  backdrop-filter: saturate(200%) blur(26px);
  border: 1px solid var(--glass-edge);
  border-radius: var(--radius-xl);
  box-shadow:
    /* a bright top lip and a darker bottom lip give the pill thickness */
    inset 0 1px 0 var(--glass-sheen),
    inset 0 -1px 0 var(--glass-edge-low),
    inset 0 0 22px -12px var(--glass-sheen),
    0 12px 34px -20px var(--glass-drop);
  transition: background-color var(--transition), border-color var(--transition),
              box-shadow var(--transition), min-height var(--transition),
              border-radius var(--transition);
}

/* Without backdrop-filter the pill would be a see-through box over live text,
   so fall back to a near-opaque tint. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .site-header .container,
  .header-inner {
    background-color: color-mix(in srgb, var(--ground) 96%, transparent);
    background-image: none;
  }
}

.logo {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  /* The wordmark must read as the brand, not as the first nav item. This
     margin is the separation; the container gap alone collapses once twelve
     links claim the remaining width. */
  margin-inline-end: var(--space-8);
}

.logo-word {
  font-family: var(--font-display);
  font-size: 1.5rem;
  letter-spacing: -0.03em;
  line-height: 1;
  white-space: nowrap;
}

.logo-strong {
  font-weight: 700;
  color: var(--ink);
}

.logo-soft {
  font-weight: 400;
  color: var(--ink-muted);
}

.nav-links {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  /* Must not wrap: the theme toggle sits beside it, and a wrapped nav
     doubles the masthead height. Links compress at the breakpoints below.

     flex-start + auto start-margin, NOT justify-content:flex-end. They look
     identical while the links fit, but under overflow flex-end pushes the
     first items out of the box's START edge — sliding them left, underneath
     the wordmark, unreachable. Auto-margin degrades forward instead. */
  flex-wrap: nowrap;
  justify-content: flex-start;
  margin-inline-start: auto;
  min-width: 0;
}

.nav-links li a {
  display: block;
  font-size: var(--text-sm);
  font-weight: 500;
  /* ink-soft, not ink-muted: at 13px these are normal-size text for WCAG, and
     muted measured 4.3:1 against the glass with a photo passing beneath —
     under the 4.5:1 floor. Size and weight still keep it visually secondary. */
  color: var(--ink-soft);
  padding: var(--space-2) var(--space-2);
  border-radius: var(--radius-pill);
  white-space: nowrap;
  transition: color var(--transition), background-color var(--transition);
}

.nav-links li a:hover {
  color: var(--ink);
  background: var(--surface-sunken);
}

/* build.js marks the current section with an inline style or attribute */
.nav-links li a[aria-current],
.nav-links li a.active {
  color: var(--ink);
  background: var(--surface-sunken);
  font-weight: 600;
}

/* ==========================================================================
   5. Hamburger Menu
   ========================================================================== */

.hamburger {
  display: none;
  flex-direction: column;
  justify-content: space-between;
  width: 22px;
  height: 16px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  z-index: 200;
  color: var(--ink);
}

.hamburger span {
  display: block;
  width: 100%;
  height: 2px;
  background-color: currentColor;
  border-radius: 2px;
  transition: transform 0.25s var(--ease), opacity 0.25s var(--ease);
}

.hamburger.active span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.hamburger.active span:nth-child(2) { opacity: 0; }
.hamburger.active span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* ==========================================================================
   6. Hero
   ========================================================================== */

.hero-section {
  padding-block: var(--space-8) 0;
}

.hero-grid {
  display: grid;
  grid-template-columns: 1.85fr 1fr;
  gap: var(--space-4);
}

.hero-small-col {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.hero-card {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  min-height: 420px;
  background-size: cover;
  background-position: center;
  background-color: var(--surface-sunken);
  isolation: isolate;
  transition: transform var(--transition), box-shadow var(--transition);
}

.hero-card.small {
  min-height: 202px;
}

/* Two stops: a soft top veil for the badge, a deep foot for the text block.
   The old single 30% gradient left titles sitting on bare photo. */
.hero-card::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to top,
      rgba(10, 9, 7, 0.92) 0%,
      rgba(10, 9, 7, 0.78) 22%,
      rgba(10, 9, 7, 0.35) 48%,
      rgba(10, 9, 7, 0.08) 72%,
      rgba(10, 9, 7, 0.22) 100%);
  z-index: 1;
  transition: opacity var(--transition);
}

.hero-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg);
}

.hero-card .card-content {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: var(--space-6);
  color: #fff;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
}

.hero-card .card-content .card-title {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 600;
  line-height: var(--leading-tight);
  letter-spacing: -0.02em;
  color: #fff;
  text-wrap: balance;
}

/* Small cards carry a 2–3 line title plus a byline in ~200px of height, so
   the text block reaches well up the image. They need a taller, denser veil
   than the large card or titles land on bare photo. */
.hero-card.small::after {
  background:
    linear-gradient(to top,
      rgba(10, 9, 7, 0.95) 0%,
      rgba(10, 9, 7, 0.9) 42%,
      rgba(10, 9, 7, 0.62) 68%,
      rgba(10, 9, 7, 0.28) 88%,
      rgba(10, 9, 7, 0.18) 100%);
}

.hero-card.small .card-content {
  padding: var(--space-4);
}

.hero-card.small .card-content .card-title {
  font-size: var(--text-lg);
  font-weight: 600;
}

/* The byline under a hero title */
.hero-card .card-content .card-meta,
.card-row .card .card-content .card-meta {
  font-size: var(--text-xs);
  color: rgba(255, 255, 255, 0.78);
  font-weight: 500;
}

/* ==========================================================================
   7. Card Row
   ========================================================================== */

.card-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-4);
  margin-block: 0;
}

.card-row .card {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  min-height: 210px;
  background-size: cover;
  background-position: center;
  background-color: var(--surface-sunken);
  isolation: isolate;
  transition: transform var(--transition), box-shadow var(--transition);
}

.card-row .card::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to top,
      rgba(10, 9, 7, 0.92) 0%,
      rgba(10, 9, 7, 0.74) 26%,
      rgba(10, 9, 7, 0.3) 55%,
      rgba(10, 9, 7, 0.06) 80%);
  z-index: 1;
}

.card-row .card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg);
}

.card-row .card .card-content {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: var(--space-4);
  color: #fff;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
}

.card-row .card .card-content .card-title {
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 600;
  line-height: var(--leading-snug);
  color: #fff;
}

/* ==========================================================================
   8. Category Badge
   ========================================================================== */

.category-badge {
  display: inline-block;
  font-family: var(--font-sans);
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  color: #fff;
  line-height: 1.5;
  white-space: nowrap;
}

/* On photo cards, let the badge read as a label rather than a colour block. */
.hero-card .category-badge,
.card-row .card .category-badge {
  background: rgba(255, 255, 255, 0.16) !important;
  border: 1px solid rgba(255, 255, 255, 0.3);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

/* ==========================================================================
   9. Section Heading
   ========================================================================== */

/* Section rhythm lives in ONE place. Previously a 48px margin here stacked
   with 20px of inline wrapper padding on both sides of the gap, giving 136px
   between every band — the margins could not collapse across the wrappers. */
.home-band {
  padding-block: 0;
}

.home-band + .home-band {
  margin-top: var(--space-16);
}

/* The card row is a continuation of the hero cluster, not a new section, so
   it keeps the hero grid's own 16px gap rather than the 64px band rhythm.
   It is the first .home-band, so the sibling rule above never applies to it —
   which is exactly why it collapsed to 0 when this rule was missing. */
.home-band--tight {
  margin-top: var(--space-4);
}

.category-section {
  margin-block: 0;
}

.category-section .section-title,
.latest-blog-section .section-title {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 600;
  letter-spacing: -0.02em;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-6);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--border);
  color: var(--ink);
}

.section-bar {
  width: 3px;
  height: 22px;
  border-radius: var(--radius-pill);
  flex-shrink: 0;
}

/* ==========================================================================
   10. Category Section (featured + list)
   ========================================================================== */

.category-content {
  display: grid;
  grid-template-columns: 1.6fr 1fr;
  gap: var(--space-10);
  align-items: start;
}

.category-featured a {
  display: block;
  text-decoration: none;
}

.category-featured img {
  width: 100%;
  border-radius: var(--radius-lg);
  aspect-ratio: 16 / 10;
  height: auto;
  object-fit: cover;
  background: var(--surface-sunken);
  transition: transform 0.4s var(--ease);
}

.category-featured a:hover img {
  transform: scale(1.015);
}

.category-featured .featured-media {
  overflow: hidden;
  border-radius: var(--radius-lg);
}

.category-featured .featured-title {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ink);
  margin-top: var(--space-4);
  line-height: var(--leading-tight);
  text-wrap: balance;
  transition: color var(--transition);
}

.category-featured a:hover .featured-title {
  color: var(--link);
}

.category-featured .featured-date {
  font-size: var(--text-xs);
  color: var(--ink-muted);
  margin-top: var(--space-2);
  letter-spacing: 0.01em;
}

.category-list {
  list-style: none;
}

.category-list-item {
  padding-block: var(--space-4);
  border-bottom: 1px solid var(--border);
}

.category-list-item:first-child { padding-top: 0; }
.category-list-item:last-child { border-bottom: none; }

.category-list-item a {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  text-decoration: none;
}

.category-list-item img {
  width: 68px;
  height: 68px;
  object-fit: cover;
  border-radius: var(--radius);
  flex-shrink: 0;
  background: var(--surface-sunken);
}

.category-list-item .list-item-info {
  flex: 1;
  min-width: 0;
}

.category-list-item .list-item-title {
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--ink);
  line-height: var(--leading-snug);
  letter-spacing: -0.01em;
  transition: color var(--transition);
}

.category-list-item a:hover .list-item-title {
  color: var(--link);
}

.category-list-item .list-item-date {
  font-size: var(--text-xs);
  color: var(--ink-muted);
  margin-top: var(--space-1);
}

/* ==========================================================================
   11. Article Card
   ========================================================================== */

.article-card {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
  display: flex;
  flex-direction: column;
  transition: transform var(--transition), box-shadow var(--transition),
              border-color var(--transition);
}

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

/* --- Media ---------------------------------------------------------------- */

.article-card-media {
  position: relative;
  overflow: hidden;
  background: var(--surface-sunken);
}

.article-card-media img {
  width: 100%;
  aspect-ratio: 3 / 2;
  height: auto;
  object-fit: cover;
  display: block;
  transition: transform 0.6s var(--ease);
}

.article-card:hover .article-card-media img { transform: scale(1.05); }

/* The badge moves onto the photograph, matching the hero cards and giving the
   body room for the standfirst. A scrim keeps it legible on pale images. */
.article-card-media::after {
  content: '';
  position: absolute;
  inset-inline: 0;
  inset-block-start: 0;
  height: 40%;
  background: linear-gradient(to bottom, rgba(10, 9, 7, 0.42), transparent);
  pointer-events: none;
}

.article-card-media .category-badge {
  position: absolute;
  top: var(--space-3);
  left: var(--space-3);
  z-index: 2;
  background: rgba(255, 255, 255, 0.16) !important;
  border: 1px solid rgba(255, 255, 255, 0.3);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

/* --- Body ----------------------------------------------------------------- */

.article-card .card-body {
  padding: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  align-items: flex-start;
  flex: 1;
}

.article-card-brand {
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.13em;
  color: var(--brand);
}

.article-card-brand:empty { display: none; }

.article-card .card-body .article-card-title {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 600;
  color: var(--ink);
  line-height: var(--leading-snug);
  letter-spacing: -0.015em;
  text-wrap: balance;
  transition: color var(--transition);
}

.article-card-title a { color: inherit; }

/* One tab stop, whole-card click target. Sits above the spotlight layer. */
.article-card-title a::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 3;
}

.article-card:hover .article-card-title { color: var(--brand); }

/* The standfirst the card never used to show. Two lines, so every card in a
   row stays the same height regardless of how long the excerpt runs. */
.article-card-dek {
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--ink-muted);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.article-card-dek:empty { display: none; }

.article-card-meta {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  margin-top: auto;
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
  font-size: var(--text-2xs);
  color: var(--ink-faint);
  letter-spacing: 0.01em;
}

.article-card-dot { color: var(--ink-faint); }

.article-card-go {
  width: 15px;
  height: 15px;
  margin-left: auto;
  color: var(--ink-faint);
  transition: transform var(--transition), color var(--transition);
}

.article-card:hover .article-card-go {
  color: var(--brand);
  transform: translateX(3px);
}

/* ==========================================================================
   12. Latest Blog Grid
   ========================================================================== */

.latest-blog-section {
  margin-block: 0;
}

.latest-blog {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-6);
}

/* ==========================================================================
   13. Article Page
   ========================================================================== */

.article-container {
  max-width: var(--measure);
  margin-inline: auto;
  margin-block: var(--space-16);
  padding-inline: var(--space-5);
}

.article-category {
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.09em;
}

.article-title {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -0.028em;
  margin-block: var(--space-4) var(--space-5);
  color: var(--ink);
  text-wrap: balance;
}

.article-meta {
  font-size: var(--text-sm);
  color: var(--ink-muted);
  margin-bottom: var(--space-8);
  padding-bottom: var(--space-6);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.article-meta .author-name {
  color: var(--ink);
  font-weight: 600;
}

.article-image {
  width: 100%;
  border-radius: var(--radius-lg);
  margin-bottom: var(--space-10);
  object-fit: cover;
  background: var(--surface-sunken);
}

/* Optical: the article body is the one place with a longer measure and a
   slightly larger body size — it is the thing people came to read. */
.article-body {
  font-size: 1.0625rem;
}

.article-body h2 {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 600;
  letter-spacing: -0.022em;
  margin-block: var(--space-12) var(--space-4);
  color: var(--ink);
  line-height: var(--leading-tight);
}

.article-body h3 {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 600;
  margin-block: var(--space-8) var(--space-3);
  color: var(--ink);
}

.article-body p {
  font-size: inherit;
  line-height: var(--leading-body);
  color: var(--ink-soft);
  margin-bottom: var(--space-5);
}

.article-body > p:first-of-type {
  font-size: 1.1875rem;
  line-height: 1.62;
  color: var(--ink);
}

.article-body ul,
.article-body ol {
  padding-left: var(--space-6);
  margin-bottom: var(--space-5);
}

.article-body ul { list-style: disc; }
.article-body ol { list-style: decimal; }

.article-body li {
  font-size: inherit;
  line-height: var(--leading-body);
  color: var(--ink-soft);
  margin-block: var(--space-2);
  padding-left: var(--space-1);
}

.article-body li::marker {
  color: var(--ink-faint);
}

.article-body a {
  color: var(--link);
  text-decoration: underline;
  text-underline-offset: 0.18em;
  text-decoration-thickness: 1px;
  transition: text-decoration-thickness var(--transition);
}

.article-body a:hover {
  text-decoration-thickness: 2px;
}

.article-body strong {
  color: var(--ink);
  font-weight: 600;
}

/* ==========================================================================
   14. CTA Callout
   ========================================================================== */

/* build.js sets `style="border-color: <category>"` inline, which paints all
   four sides. So only the left border is given a width — the other three stay
   at 0 and the inline colour has nothing to paint. */
.cta-callout {
  background: var(--surface);
  border: 0 solid;
  border-left-width: 3px;
  padding: var(--space-5) var(--space-6);
  border-radius: 0 var(--radius) var(--radius) 0;
  margin-block: var(--space-8);
  box-shadow: var(--shadow-sm);
}

.cta-callout p {
  font-size: var(--text-base);
  line-height: var(--leading-snug);
  color: var(--ink-soft);
  margin-bottom: 0;
}

.cta-callout a {
  font-weight: 600;
  color: var(--ink);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  border-bottom: 1.5px solid currentColor;
  transition: gap var(--transition);
}

.cta-callout a:hover {
  gap: var(--space-2);
  text-decoration: none;
}

/* ==========================================================================
   15. Category Page
   ========================================================================== */

.cat-hero {
  border-bottom: 1px solid var(--border);
  padding-block: var(--space-10);
  margin-bottom: var(--space-8);
  background: linear-gradient(to bottom,
    color-mix(in srgb, var(--brand) 5%, transparent), transparent 85%);
}

.cat-hero .breadcrumb { margin-bottom: var(--space-6); }

.cat-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  margin-bottom: var(--space-3);
}

.cat-eyebrow-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
}

.cat-title {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.05;
  color: var(--ink);
  margin-bottom: var(--space-3);
}

.cat-lede {
  font-size: var(--text-base);
  color: var(--ink-muted);
  max-width: 52ch;
}

.cat-body { padding-bottom: var(--space-16); }

.cat-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding-bottom: var(--space-5);
  margin-bottom: var(--space-6);
  border-bottom: 1px solid var(--border);
}

.cat-count {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}

.cat-empty {
  padding: var(--space-12);
  text-align: center;
  color: var(--ink-muted);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

.breadcrumb a { color: var(--ink-muted); text-decoration: none; }
.breadcrumb span { color: var(--ink-faint); }

.article-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-6);
  margin-bottom: var(--space-12);
}

/* --- Pagination ----------------------------------------------------------- */

.pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding-top: var(--space-8);
  border-top: 1px solid var(--border);
}

.page-nums {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  flex-wrap: wrap;
  justify-content: center;
}

.page-num,
.page-gap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  height: 40px;
  padding-inline: var(--space-2);
  border-radius: var(--radius-pill);
  font-size: var(--text-sm);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--ink-muted);
  transition: color var(--transition), background-color var(--transition);
}

.page-num:hover { color: var(--ink); background: var(--surface-sunken); }

.page-num.is-current {
  background: var(--brand);
  color: #fff;
}

.page-gap { color: var(--ink-faint); min-width: 24px; }

.page-step {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-5);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink-soft);
  white-space: nowrap;
  transition: border-color var(--transition), color var(--transition),
              gap var(--transition);
}

.page-step svg { width: 15px; height: 15px; }

.page-step:hover { border-color: var(--brand); color: var(--brand); gap: var(--space-3); }

.page-step.is-disabled {
  opacity: 0.4;
  pointer-events: none;
  border-color: var(--border);
}

@media (max-width: 1024px) {
  .article-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 768px) {
  .cat-hero {
    padding-block: var(--space-6) var(--space-8);
    margin-bottom: var(--space-6);
  }

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

  .pagination {
    flex-wrap: wrap;
    justify-content: center;
  }

  .page-nums { order: -1; width: 100%; margin-bottom: var(--space-2); }
  .page-step { flex: 1; justify-content: center; }
}

/* ==========================================================================
   16. Footer
   ========================================================================== */

.site-footer {
  position: relative;
  overflow: hidden;
  background: linear-gradient(180deg, var(--surface-sunken),
    color-mix(in srgb, var(--brand) 8%, var(--surface-sunken)));
  border-top: 1px solid var(--border);
  color: var(--ink);
  padding-block: var(--space-16) 0;
  margin-top: var(--space-20);
}

/* Warm bloom rising from the foot of the page, mirroring the masthead's. */
.site-footer::before {
  content: '';
  position: absolute;
  inset-inline: 0;
  inset-block-start: 0;
  height: 420px;
  pointer-events: none;
  background: radial-gradient(70% 120% at 50% 0%,
    color-mix(in srgb, var(--brand) 9%, transparent), transparent 70%);
}

.site-footer > .container {
  position: relative;
  z-index: 1;
}

/* --- Statement band ------------------------------------------------------ */

.footer-lead {
  display: grid;
  grid-template-columns: 1.25fr 1fr;
  gap: var(--space-12);
  align-items: end;
  padding-bottom: var(--space-12);
  border-bottom: 1px solid var(--border);
}

.footer-eyebrow {
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--brand);
  margin-bottom: var(--space-4);
}

.footer-statement {
  font-family: var(--font-display);
  font-size: clamp(1.9rem, 1.2rem + 2.6vw, 3.1rem);
  font-weight: 600;
  line-height: 1.04;
  letter-spacing: -0.03em;
  color: var(--ink);
}

.footer-lede {
  font-size: var(--text-base);
  line-height: 1.65;
  color: var(--ink-muted);
  max-width: 44ch;
  margin-bottom: var(--space-6);
}

.footer-cta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-6);
  border-radius: var(--radius-pill);
  background: var(--brand);
  color: #fff;
  font-size: var(--text-base);
  font-weight: 600;
  box-shadow: 0 8px 22px -12px var(--brand);
  transition: background-color var(--transition), transform var(--transition),
              box-shadow var(--transition), gap var(--transition);
}

.footer-cta svg { width: 16px; height: 16px; }

.footer-cta:hover {
  background: var(--brand-hover);
  transform: translateY(-2px);
  gap: var(--space-3);
  box-shadow: 0 14px 28px -12px var(--brand);
}

/* --- Category chips ------------------------------------------------------ */

.footer-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding-block: var(--space-8);
  border-bottom: 1px solid var(--border);
}

.footer-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--surface);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--ink-soft);
  transition: border-color var(--transition), color var(--transition),
              transform var(--transition), box-shadow var(--transition);
}

.footer-chip-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
}

.footer-chip-n {
  font-size: var(--text-2xs);
  font-variant-numeric: tabular-nums;
  color: var(--ink-faint);
}

.footer-chip:hover {
  color: var(--ink);
  border-color: var(--border-strong);
  transform: translateY(-2px);
  box-shadow: var(--shadow);
}

/* --- Columns ------------------------------------------------------------- */

.footer-grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1.6fr;
  gap: var(--space-10);
  padding-block: var(--space-10);
}

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

.footer-logo .logo-word { font-size: 1.375rem; }

.footer-tagline {
  font-size: var(--text-sm);
  color: var(--ink-muted);
  line-height: 1.65;
  max-width: 34ch;
}

.footer-heading {
  font-family: var(--font-sans);
  font-size: var(--text-2xs);
  font-weight: 600;
  /* ink-muted, not ink-faint: these 11px labels sit directly over the
     watermark, which costs about half a point of contrast and put the faint
     tone under the 4.5:1 floor. */
  color: var(--ink-muted);
  margin-bottom: var(--space-5);
  text-transform: uppercase;
  letter-spacing: 0.14em;
}

.footer-links { list-style: none; }
.footer-links li { margin-block: var(--space-3); }

.footer-links li a {
  color: var(--ink-muted);
  font-size: var(--text-base);
  text-decoration: none;
}

.footer-post {
  display: flex;
  gap: var(--space-4);
  margin-bottom: var(--space-5);
  align-items: flex-start;
}

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

.footer-post img {
  width: 60px;
  height: 60px;
  border-radius: var(--radius);
  object-fit: cover;
  flex-shrink: 0;
  background: var(--border);
}

.footer-post-info { flex: 1; min-width: 0; }

.footer-post-title {
  font-family: var(--font-display);
  font-size: var(--text-base);
  color: var(--ink-soft);
  line-height: var(--leading-snug);
  font-weight: 600;
  text-decoration: none;
  display: block;
}

.footer-post-title:hover { color: var(--brand); }

.footer-post-date {
  font-size: var(--text-2xs);
  /* ink-faint measured 4.46:1 here even on the opaque panel — an 11px date
     has no headroom to spare, and it only gets worse as the panel is made
     more transparent over the wordmark. */
  color: var(--ink-muted);
  margin-top: var(--space-1);
}

/* --- Disclosure ---------------------------------------------------------- */

/* Affiliate disclosure. Required, and deliberately legible rather than
   buried — it is a trust signal, not fine print to hide. */
.footer-disclosure {
  font-size: var(--text-xs);
  line-height: 1.7;
  color: var(--ink-muted);
  padding: var(--space-5) var(--space-6);
  border: 1px solid var(--border);
  border-left: 3px solid var(--brand);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--surface);
  margin-bottom: var(--space-10);
}

/* Full width would give a ~160-character line, so split it into two columns
   rather than letting it strand a void on the right. */
@media (min-width: 900px) {
  .footer-disclosure {
    column-count: 2;
    column-gap: var(--space-10);
    column-rule: 1px solid var(--border);
  }
}

/* --- Bottom bar ---------------------------------------------------------- */

.footer-bottom {
  border-top: 1px solid var(--border);
  padding-block: var(--space-6);
  font-size: var(--text-xs);
  color: var(--ink-muted);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.footer-bottom-links {
  display: flex;
  gap: var(--space-5);
  list-style: none;
}

.footer-bottom a {
  color: var(--ink-muted);
  text-decoration: none;
}

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

/* --- Watermark ----------------------------------------------------------- */

/* Oversized wordmark sitting behind the footer columns, filling what was a
   large empty block under the brand blurb. Presentational only, hidden from
   assistive tech, and clipped by .footer-mid rather than the footer itself. */
.footer-mid {
  position: relative;
  isolation: isolate;
  /* Tall enough for the full letterforms; the mark is the constraint here,
     not the columns. Clipping is left to .site-footer so the wordmark can
     run wider than this band. */
  min-height: var(--watermark-size);
  display: flex;
  align-items: center;
}

.footer-mid > .footer-grid {
  position: relative;
  z-index: 1;
  width: 100%;
}

.footer-watermark {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: max-content;
  z-index: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--watermark-size);
  line-height: 0.95;
  letter-spacing: -0.045em;
  color: var(--ink);
  opacity: 0.05;
  pointer-events: none;
  user-select: none;
  white-space: nowrap;
}

/* ==========================================================================
   17. Search Page
   ========================================================================== */

.search-hero {
  border-bottom: 1px solid var(--border);
  padding-block: var(--space-10) var(--space-10);
  margin-bottom: var(--space-10);
  background: linear-gradient(to bottom,
    color-mix(in srgb, var(--brand) 5%, transparent), transparent 85%);
}

.search-hero .breadcrumb { margin-bottom: var(--space-6); }

.search-eyebrow {
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--brand);
  margin-bottom: var(--space-3);
}

.search-title {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.05;
  color: var(--ink);
  margin-bottom: var(--space-3);
}

.search-lede {
  font-size: var(--text-base);
  color: var(--ink-muted);
  margin-bottom: var(--space-8);
  max-width: 52ch;
}

.search-body { padding-bottom: var(--space-16); }

/* --- Field ---------------------------------------------------------------- */

.search-box {
  position: relative;
  max-width: 44rem;
}

.search-icon {
  position: absolute;
  left: var(--space-5);
  top: 50%;
  transform: translateY(-50%);
  width: 20px;
  height: 20px;
  color: var(--ink-faint);
  pointer-events: none;
}

.search-input {
  width: 100%;
  padding: var(--space-4) var(--space-12) var(--space-4) calc(var(--space-12) + var(--space-1));
  font-size: var(--text-md);
  font-family: inherit;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--ink);
  outline: none;
  box-shadow: var(--shadow-sm);
  transition: border-color var(--transition), box-shadow var(--transition);
  -webkit-appearance: none;
  appearance: none;
}

/* Safari draws its own clear widget on type=search, beside ours. */
.search-input::-webkit-search-decoration,
.search-input::-webkit-search-cancel-button { -webkit-appearance: none; }

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

.search-input:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 4px var(--brand-ring);
}

.search-clear {
  position: absolute;
  right: var(--space-4);
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  font-size: 22px;
  line-height: 1;
  color: var(--ink-faint);
  cursor: pointer;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-pill);
  transition: color var(--transition), background-color var(--transition);
}

.search-clear:hover {
  color: var(--ink);
  background: var(--surface-sunken);
}

.search-meta {
  font-size: var(--text-sm);
  color: var(--ink-muted);
  margin-bottom: var(--space-5);
  font-weight: 500;
}

/* --- Results -------------------------------------------------------------- */

.search-results-list {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-5);
}

.sr-card {
  display: grid;
  /* Fixed media column + flexible content keeps every row the same shape
     regardless of image aspect; the old auto-height flex row left tall cards
     with a band of dead space under the byline. */
  grid-template-columns: 180px minmax(0, 1fr);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition), border-color var(--transition),
              transform var(--transition);
}

.sr-card:hover {
  box-shadow: var(--shadow-lg);
  border-color: var(--border-strong);
  transform: translateY(-2px);
}

.sr-card-img {
  display: block;
  overflow: hidden;
  background: var(--surface-sunken);
}

.sr-card-img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.5s var(--ease);
}

.sr-card:hover .sr-card-img img { transform: scale(1.05); }

.sr-card-content {
  padding: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 0;
}

.sr-card-tags {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.sr-card-domain {
  font-size: var(--text-xs);
  color: var(--ink-muted);
  font-weight: 500;
}

.sr-card-id {
  font-size: var(--text-2xs);
  color: var(--ink-muted);
  font-family: var(--font-mono);
  background: var(--surface-sunken);
  padding: 2px var(--space-2);
  border-radius: var(--radius-sm);
}

.sr-card-title {
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--ink);
  line-height: var(--leading-snug);
  letter-spacing: -0.012em;
  margin: 0;
}

.sr-card-title a { color: inherit; text-decoration: none; }
.sr-card:hover .sr-card-title a { color: var(--brand); }

.sr-card-brand {
  font-size: var(--text-xs);
  color: var(--ink-muted);
  margin: 0;
}

.sr-card-brand strong { color: var(--ink-soft); font-weight: 600; }

.sr-card-btns {
  display: flex;
  gap: var(--space-2);
  margin-top: auto;
  padding-top: var(--space-3);
  flex-wrap: wrap;
}

.sr-btn {
  display: inline-flex;
  align-items: center;
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-xs);
  font-weight: 600;
  border-radius: var(--radius-pill);
  text-decoration: none;
  white-space: nowrap;
  transition: background-color var(--transition), border-color var(--transition),
              color var(--transition);
}

/* Ember, matching every other primary action on the site — this was the one
   place still using the near-black accent. */
.sr-btn-primary {
  background: var(--brand);
  color: #fff;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  display: inline-block;
}

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

.sr-btn-outline {
  border: 1px solid var(--border-strong);
  color: var(--ink-soft);
  background: transparent;
}

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

/* --- Panels (empty / initial) --------------------------------------------- */

.search-panel {
  padding: var(--space-10);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  text-align: center;
}

.search-panel-title {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ink);
  margin-bottom: var(--space-2);
}

.search-panel-hint {
  font-size: var(--text-base);
  color: var(--ink-muted);
  margin-bottom: var(--space-8);
}

.search-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  justify-content: center;
}

.search-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--ground);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--ink-soft);
  transition: border-color var(--transition), color var(--transition),
              transform var(--transition), box-shadow var(--transition);
}

.search-chip-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
}

.search-chip-n {
  font-size: var(--text-2xs);
  font-variant-numeric: tabular-nums;
  color: var(--ink-faint);
}

.search-chip:hover {
  color: var(--ink);
  border-color: var(--brand);
  transform: translateY(-2px);
  box-shadow: var(--shadow);
}

/* --- Responsive ----------------------------------------------------------- */

@media (max-width: 1100px) {
  .search-results-list { grid-template-columns: 1fr; }
}

@media (max-width: 560px) {
  .sr-card { grid-template-columns: 1fr; }

  .sr-card-img { height: 180px; }

  .search-panel { padding: var(--space-6) var(--space-5); }

  .search-hero {
    padding-block: var(--space-6) var(--space-8);
    margin-bottom: var(--space-8);
  }
}

@media (prefers-reduced-motion: reduce) {
  .sr-card:hover,
  .search-chip:hover { transform: none; }
  .sr-card:hover .sr-card-img img { transform: none; }
}

/* ==========================================================================
   18. Utilities & Misc
   ========================================================================== */

.text-center { text-align: center; }
.text-muted { color: var(--ink-muted); }

.mt-8  { margin-top: var(--space-2); }
.mt-16 { margin-top: var(--space-4); }
.mt-24 { margin-top: var(--space-6); }
.mt-32 { margin-top: var(--space-8); }
.mb-8  { margin-bottom: var(--space-2); }
.mb-16 { margin-bottom: var(--space-4); }
.mb-24 { margin-bottom: var(--space-6); }
.mb-32 { margin-bottom: var(--space-8); }

@keyframes imgFadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

img.lazy { opacity: 0; }
img.lazy.loaded { animation: imgFadeIn 0.35s var(--ease) forwards; }

.section-divider {
  border: none;
  border-top: 1px solid var(--border);
  margin-block: var(--space-12);
}

.view-all {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink-muted);
  text-decoration: none;
  margin-top: var(--space-5);
  transition: color var(--transition), gap var(--transition);
}

.view-all:hover {
  color: var(--ink);
  gap: var(--space-2);
}

.skip-link {
  position: absolute;
  top: -60px;
  left: var(--space-4);
  background: var(--ink);
  color: var(--ground);
  padding: var(--space-3) var(--space-5);
  font-size: var(--text-base);
  font-weight: 600;
  z-index: 9999;
  text-decoration: none;
  border-radius: 0 0 var(--radius) var(--radius);
  transition: top var(--transition);
}

.skip-link:focus { top: 0; }

a:focus-visible,
button:focus-visible,
input:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

/* ==========================================================================
   19. Responsive
   ========================================================================== */

/* Eleven category links plus a search icon and the theme toggle is a lot of
   masthead. Tighten in two steps before the drawer takes over at 768px. */
@media (max-width: 1320px) {
  .logo { margin-inline-end: var(--space-6); }

  .nav-links li a {
    padding-inline: var(--space-2);
    font-size: var(--text-xs);
  }
}

@media (max-width: 1120px) {
  .site-header .container,
  .header-inner { gap: var(--space-4); }

  .logo { margin-inline-end: var(--space-4); }

  .nav-links { gap: 0; }

  .nav-links li a {
    padding-inline: 5px;
    letter-spacing: -0.01em;
  }

  .logo-word { font-size: 1.25rem; }
}

/* Below this the twelve links stop fitting honestly, so hand over to the
   drawer early rather than shaving them to illegibility. */
@media (max-width: 960px) and (min-width: 769px) {
  .nav-links li a { font-size: 0.6875rem; padding-inline: 4px; }
}

@media (max-width: 1024px) {
  .article-grid,
  .search-results-grid,
  .latest-blog {
    grid-template-columns: repeat(2, 1fr);
  }

  .hero-card { min-height: 360px; }
  .hero-card.small { min-height: 172px; }

  .category-content {
    grid-template-columns: 1fr;
    gap: var(--space-8);
  }

  .footer-grid {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-8);
  }
}

@media (max-width: 768px) {
  .hamburger { display: flex; }

  /* NOT position:fixed. The pill carries backdrop-filter, which makes it the
     containing block for fixed descendants — a fixed drawer would resolve its
     offsets against the 60px pill, not the viewport, and collapse. Anchoring
     it to the pill on purpose is both correct and simpler: it tracks the
     island as that sticks. */
  .nav-links {
    display: none;
    position: absolute;
    top: calc(100% + var(--space-3));
    /* Offsets resolve against the pill's PADDING box, so cancel its inline
       padding to line the drawer's edges up with the island above it. */
    left: calc(var(--space-5) * -1);
    right: calc(var(--space-5) * -1);
    max-height: calc(100vh - 112px);
    max-height: calc(100dvh - 112px);

    /* flex-start is load-bearing. The desktop nav uses flex-end, and on a
       column flex box whose content overflows, flex-end pushes the first
       items ABOVE the container where scrolling cannot reach them — the nav
       sits within a couple of pixels of that threshold, so it flipped between
       fine and broken depending on when the webfont landed. */
    justify-content: flex-start;

    /* Solid, and deliberately NOT glass. A backdrop-filter nested inside the
       pill's own backdrop-filter does not composite against the page behind
       it — measured 0.96 alpha still rendered roughly 40% transparent, with
       article photos legible through the menu. The island above keeps the
       glass; the drawer only has to be readable. */
    background: var(--ground);
    border: 1px solid color-mix(in srgb, var(--border) 70%, transparent);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-lg);
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: var(--space-2) var(--space-5);
    z-index: 99;
    overflow-y: auto;
  }

  .nav-links li:last-child { border-bottom: none; }

  .nav-links.open { display: flex; }

  .nav-links li {
    width: 100%;
    border-bottom: 1px solid var(--border);
  }

  .nav-links li a {
    display: block;
    padding: var(--space-4) 0;
    font-size: var(--text-md);
    font-weight: 500;
    border-radius: 0;
  }

  .nav-links li a:hover { background: transparent; }

  .nav-links { margin-inline-start: 0; }

  .hero-section { padding-top: var(--space-5); }
  .hero-grid { grid-template-columns: 1fr; }
  .hero-card { min-height: 300px; }
  .hero-card.small { min-height: 210px; }
  .hero-small-col { gap: var(--space-4); }

  .card-row {
    grid-template-columns: 1fr;
    margin-bottom: var(--space-8);
  }
  .card-row .card { min-height: 200px; }

  .home-band + .home-band { margin-top: var(--space-10); }
  .category-featured img { aspect-ratio: 16 / 11; }

  .article-grid,
  .search-results-grid,
  .latest-blog {
    grid-template-columns: 1fr;
  }

  .search-input {
    font-size: var(--text-md);
    padding: var(--space-3) var(--space-10) var(--space-3) var(--space-12);
  }

  .search-empty { padding: var(--space-10) var(--space-4); }

  .article-container { margin-block: var(--space-8); }
  .article-body > p:first-of-type { font-size: 1.0625rem; }

  .footer-grid {
    grid-template-columns: 1fr;
    gap: var(--space-8);
  }

  .site-footer { padding-top: var(--space-10); }

  .sr-card { flex-direction: column; }
  .sr-card-img {
    width: 100%;
    height: 200px;
    min-height: auto;
  }
}

@media (max-width: 480px) {
  .container { padding-inline: var(--space-4); }
  .hero-card { min-height: 260px; }
  .hero-card.small { min-height: 190px; }
  .hero-card .card-content { padding: var(--space-4); }
  .category-list-item img { width: 60px; height: 60px; }
}

/* ==========================================================================
   20. Motion & Interaction

   Ground rules for everything in this section:
   - Content is never hidden unless JS confirmed it can reveal it again
     (`.js.reveal-ready`), so crawlers and no-JS visitors see a complete page.
   - Every transform animation is opacity + translate only, so nothing here
     triggers layout and nothing shifts (no CLS).
   - The reduced-motion block at the end switches all of it off.
   ========================================================================== */

/* Anchor targets clear the sticky header instead of hiding under it. */
html {
  scroll-padding-top: 92px;
}

/* Cross-document fade on same-origin navigation. Chromium-only today and a
   no-op everywhere else, which is exactly the right failure mode. */
@view-transition {
  navigation: auto;
}

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 0.26s;
  animation-timing-function: var(--ease);
}

/* A single warm bloom behind the masthead, so the page does not begin as a
   flat slab of paper. */
body {
  background-image: var(--glow);
  background-repeat: no-repeat;
  background-size: 100% 620px;
  background-attachment: fixed;
}

::selection {
  background: var(--brand);
  color: #fff;
}

/* --------------------------------------------------------------------------
   Reading progress
   -------------------------------------------------------------------------- */

.scroll-progress {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  height: 3px;
  z-index: 200;
  pointer-events: none;
  background: transparent;
}

.scroll-progress span {
  display: block;
  height: 100%;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--brand), var(--brand-hover));
  will-change: transform;
}

/* On non-article pages the bar is noise, so app.js flags it out. */
.scroll-progress.is-page-level {
  display: none;
}

/* --------------------------------------------------------------------------
   Header
   -------------------------------------------------------------------------- */

/* Without this, content scrolling past the top edge is sliced mid-letter in
   the gap above the island. A short scrim fades it out instead. It only
   appears once scrolled, so the top of the page stays clean. */
.site-header::before {
  content: '';
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  /* Only as tall as the gap above the pill. It used to run 96px, which
     veiled the whole area behind the island to near-ground — leaving the
     glass nothing to refract and making it read as a solid panel. */
  height: 30px;
  z-index: -1;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--transition);
  background: linear-gradient(
    to bottom,
    var(--ground) 0%,
    color-mix(in srgb, var(--ground) 82%, transparent) 55%,
    transparent 100%);
}

.site-header.is-scrolled::before {
  opacity: 1;
}

/* Scrolled: the glass thickens and the island contracts slightly, so the
   masthead reads as "lifted off" the page rather than merely stuck to it. */
.site-header.is-scrolled .header-inner,
.site-header.is-scrolled .container {
  /* Content slides underneath now, so the tint thickens. Sheen and edges
     stay, so it still reads as glass — just less see-through. */
  background-color: var(--glass-bg-solid);
  min-height: 54px;
  box-shadow:
    inset 0 1px 0 var(--glass-sheen),
    inset 0 -1px 0 var(--glass-edge-low),
    inset 0 0 22px -12px var(--glass-sheen),
    0 16px 40px -20px var(--glass-drop);
}

.header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-shrink: 0;
  order: 3;
}

/* A nav link grows its underline from the centre on hover; the current
   section keeps one permanently. */
.nav-links li a {
  position: relative;
}

.nav-links li a::after {
  content: '';
  position: absolute;
  left: 50%;
  right: 50%;
  bottom: 4px;
  height: 1.5px;
  border-radius: var(--radius-pill);
  background: var(--brand);
  opacity: 0;
  transition: left var(--transition), right var(--transition), opacity var(--transition);
}

.nav-links li a:hover::after {
  left: var(--space-2);
  right: var(--space-2);
  opacity: 1;
}

.nav-links li a[aria-current],
.nav-links li a.active {
  color: var(--ink);
  background: var(--brand-soft);
}

/* --------------------------------------------------------------------------
   Theme toggle
   -------------------------------------------------------------------------- */

.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--ink-muted);
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
  transition: color var(--transition), border-color var(--transition),
              background-color var(--transition), transform var(--transition);
}

.theme-toggle:hover {
  color: var(--brand);
  border-color: var(--brand);
  transform: rotate(-18deg);
}

.theme-toggle:active {
  transform: scale(0.94);
}

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

/* Show exactly one glyph: the moon while light (tap for dark), sun while dark. */
.theme-toggle .icon-moon { display: block; }
.theme-toggle .icon-sun { display: none; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .theme-toggle .icon-moon { display: none; }
  :root:not([data-theme='light']) .theme-toggle .icon-sun { display: block; }
}

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

/* --------------------------------------------------------------------------
   Back to top
   -------------------------------------------------------------------------- */

.to-top {
  position: fixed;
  right: var(--space-6);
  bottom: var(--space-6);
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow-lg);
  cursor: pointer;
  z-index: 90;
  opacity: 0;
  visibility: hidden;
  transform: translateY(12px) scale(0.9);
  transition: opacity var(--transition), transform var(--transition),
              visibility var(--transition), color var(--transition),
              border-color var(--transition);
}

.to-top.is-visible {
  opacity: 1;
  visibility: visible;
  transform: none;
}

.to-top:hover {
  color: var(--brand);
  border-color: var(--brand);
  transform: translateY(-2px);
}

.to-top svg {
  width: 18px;
  height: 18px;
}

/* --------------------------------------------------------------------------
   Scroll reveal
   -------------------------------------------------------------------------- */

.js.reveal-ready .reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.55s var(--ease), transform 0.55s var(--ease);
  will-change: opacity, transform;
}

.js.reveal-ready .reveal.is-in {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* --------------------------------------------------------------------------
   Entrance — masthead and hero, on first paint only
   -------------------------------------------------------------------------- */

@keyframes sg-rise {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: none; }
}

.js .site-header {
  animation: sg-rise 0.45s var(--ease) both;
}

/* --------------------------------------------------------------------------
   Card hover refinements
   -------------------------------------------------------------------------- */

.article-card img,
.category-list-item img,
.sr-card-img img {
  transition: transform 0.5s var(--ease);
}

.article-card:hover img,
.category-list-item a:hover img,
.sr-card:hover .sr-card-img img {
  transform: scale(1.04);
}

/* The image needs a clipping parent or the zoom escapes the rounded corner. */
.article-card a,
.sr-card-img,
.category-list-item img {
  overflow: hidden;
}

/* Hero and card-row use background-images, so they deepen rather than zoom. */
.hero-card:hover::after,
.card-row .card:hover::after {
  opacity: 0.88;
}

.article-card:active,
.hero-card:active,
.card-row .card:active {
  transform: translateY(0);
}

/* Section bars pick up a gradient toward the brand. */
.section-bar {
  background-image: linear-gradient(to bottom, currentColor, var(--brand));
}

/* --------------------------------------------------------------------------
   Links & buttons
   -------------------------------------------------------------------------- */

.footer-links li a,
.footer-post-title,
.breadcrumb a {
  transition: color var(--transition);
}

.footer-links li a:hover,
.breadcrumb a:hover {
  color: var(--brand);
}

.view-all:hover {
  color: var(--brand);
}

.cta-callout {
  transition: box-shadow var(--transition), transform var(--transition);
}

.cta-callout:hover {
  box-shadow: var(--shadow);
  transform: translateY(-1px);
}

.sr-btn-primary:hover {
  background: var(--brand);
  color: #fff;
}

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

.search-input:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 4px var(--brand-ring);
}

/* --------------------------------------------------------------------------
   Reduced motion — opt everything above back out
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .js.reveal-ready .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .js .site-header { animation: none; }

  .theme-toggle:hover,
  .to-top:hover,
  .cta-callout:hover { transform: none; }

  .article-card:hover img,
  .category-list-item a:hover img,
  .sr-card:hover .sr-card-img img { transform: none; }

  @view-transition { navigation: none; }
}

@media (max-width: 768px) {
  .to-top {
    right: var(--space-4);
    bottom: var(--space-4);
    width: 40px;
    height: 40px;
  }

  /* The drawer replaces the inline nav, so the wordmark needs no separation. */
  .header-actions { gap: var(--space-3); }
  .logo { margin-inline-end: 0; }
}

/* ==========================================================================
   21. Depth & Detail
   ========================================================================== */

/* --- Section headers with a "view all" affordance ------------------------ */

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

/* The rule now lives on .section-head, so drop it from the title itself. */
.section-head .section-title {
  margin-bottom: 0;
  padding-bottom: 0;
  border-bottom: 0;
}

.section-more {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  flex-shrink: 0;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink-muted);
  white-space: nowrap;
  transition: color var(--transition), gap var(--transition);
}

.section-more svg { width: 15px; height: 15px; }

.section-more:hover {
  color: var(--brand);
  gap: var(--space-3);
}

/* --- Paper grain ---------------------------------------------------------
   A single tiled SVG turbulence over the whole page. It is what stops large
   flat areas of ground colour reading as a blank slab on a wide monitor.
   Very low opacity by design: it should be felt, not seen. */

body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 9998;
  pointer-events: none;
  opacity: 0.035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) body::after { opacity: 0.055; }
}

:root[data-theme='dark'] body::after { opacity: 0.055; }

/* --- Card surfaces ------------------------------------------------------- */

/* A hairline top highlight reads as a lit edge and lifts cards off the page
   far more cheaply than a heavier shadow would. */
.article-card,
.sr-card {
  box-shadow: var(--shadow-sm);
}

.article-card::before,
.sr-card::before {
  content: '';
  position: absolute;
  inset-inline: 0;
  inset-block-start: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent,
    color-mix(in srgb, #fff 70%, transparent), transparent);
  opacity: 0;
  transition: opacity var(--transition);
  z-index: 2;
}

.article-card,
.sr-card { position: relative; }

.article-card:hover::before,
.sr-card:hover::before { opacity: 1; }

/* Category colour bleeds faintly into the card on hover. */
.article-card .category-badge { box-shadow: 0 2px 8px -3px currentColor; }

/* --- Photo cards --------------------------------------------------------- */

/* A slow drift on the hero background gives the masthead area life without
   anything moving enough to distract from the headline. */
.hero-card {
  background-size: 106% auto;
  transition: transform var(--transition), box-shadow var(--transition),
              background-size 0.8s var(--ease);
}

.hero-card:hover { background-size: 112% auto; }

.card-row .card {
  background-size: 106% auto;
  transition: transform var(--transition), box-shadow var(--transition),
              background-size 0.8s var(--ease);
}

.card-row .card:hover { background-size: 112% auto; }

/* --- Featured article ---------------------------------------------------- */

.category-featured a {
  display: block;
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.category-featured .featured-title,
.category-featured .featured-date {
  padding-inline: var(--space-1);
}

/* --- Article page flourishes --------------------------------------------- */

/* Drop cap on the lead paragraph — the clearest single signal that a page is
   an edited article rather than a content dump. */
.article-body > p:first-of-type::first-letter {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 3.1em;
  float: left;
  line-height: 0.82;
  margin: 0.06em 0.09em 0 0;
  color: var(--brand);
}

.article-meta .author-name {
  position: relative;
}

/* Section headings get a small brand tick in the left margin. */
.article-body h2 {
  position: relative;
}

.article-body h2::before {
  content: '';
  position: absolute;
  left: -0.85em;
  top: 0.34em;
  width: 3px;
  height: 0.72em;
  border-radius: var(--radius-pill);
  background: var(--brand);
  opacity: 0.85;
}

@media (max-width: 880px) {
  .article-body h2::before { display: none; }
}

/* --- Footer responsive --------------------------------------------------- */

@media (max-width: 1024px) {
  .footer-lead {
    grid-template-columns: 1fr;
    gap: var(--space-8);
    align-items: start;
  }

  .footer-grid {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-8);
  }

  .footer-latest { grid-column: 1 / -1; }
}

@media (max-width: 768px) {
  .site-footer { padding-top: var(--space-12); margin-top: var(--space-12); }

  /* The columns stack here, so there is no empty block for the mark to fill —
     it would sit between content instead of behind it and read as a stray
     artifact rather than a flourish. */
  .footer-watermark { display: none; }

  .footer-grid { grid-template-columns: 1fr; }
  .footer-latest { grid-column: auto; }

  .section-head {
    flex-wrap: wrap;
    gap: var(--space-2);
  }

  .footer-bottom {
    flex-direction: column;
    align-items: flex-start;
  }

  .footer-disclosure {
    padding: var(--space-4) var(--space-5);
  }

  .article-body > p:first-of-type::first-letter { font-size: 2.7em; }
}

@media (prefers-reduced-motion: reduce) {
  .hero-card:hover,
  .card-row .card:hover { background-size: 106% auto; }

  .footer-cta:hover,
  .footer-chip:hover { transform: none; }
}

/* ==========================================================================
   22. Legal Pages
   ========================================================================== */

.legal-hero {
  position: relative;
  border-bottom: 1px solid var(--border);
  padding-block: var(--space-10) var(--space-10);
  margin-bottom: var(--space-12);
  background: linear-gradient(to bottom,
    color-mix(in srgb, var(--brand) 5%, transparent), transparent 85%);
}

.legal-hero .breadcrumb { margin-bottom: var(--space-6); }

.legal-eyebrow {
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--brand);
  margin-bottom: var(--space-3);
}

.legal-title {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.05;
  color: var(--ink);
  margin-bottom: var(--space-4);
}

.legal-updated {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--ink-muted);
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--surface);
}

.legal-updated svg { width: 14px; height: 14px; }

/* --- Layout --------------------------------------------------------------- */

.legal-layout {
  display: grid;
  grid-template-columns: 230px minmax(0, 1fr);
  gap: var(--space-16);
  align-items: start;
  padding-bottom: var(--space-16);
}

.legal-toc {
  position: sticky;
  /* clears the floating masthead */
  top: 104px;
}

.legal-toc-head {
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--ink-faint);
  margin-bottom: var(--space-4);
}

.legal-toc ol {
  list-style: none;
  counter-reset: toc;
  border-left: 1px solid var(--border);
}

.legal-toc li { counter-increment: toc; }

.legal-toc a {
  display: block;
  padding: var(--space-2) var(--space-4);
  margin-left: -1px;
  border-left: 2px solid transparent;
  font-size: var(--text-sm);
  line-height: 1.4;
  color: var(--ink-muted);
  transition: color var(--transition), border-color var(--transition);
}

.legal-toc a::before {
  content: counter(toc) '. ';
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

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

.legal-toc a.is-current {
  color: var(--brand);
  border-left-color: var(--brand);
  font-weight: 600;
}

.legal-toc a.is-current::before { color: var(--brand); }

/* --- Body ----------------------------------------------------------------- */

.legal-body {
  max-width: 68ch;
}

/* A drop cap belongs on an article, not on a privacy policy. */
.legal-body > .legal-intro > p:first-of-type::first-letter {
  font-family: inherit;
  font-size: inherit;
  font-weight: inherit;
  float: none;
  margin: 0;
  line-height: inherit;
  color: inherit;
}

.legal-intro p {
  font-size: 1.125rem;
  line-height: 1.65;
  color: var(--ink);
  padding-bottom: var(--space-8);
  border-bottom: 1px solid var(--border);
  margin-bottom: var(--space-4);
}

.legal-section {
  scroll-margin-top: 104px;
  padding-block: var(--space-6);
}

.legal-section h2 {
  margin-top: var(--space-4);
}

.legal-section + .legal-section {
  border-top: 1px solid var(--border);
}

/* --- Contact card --------------------------------------------------------- */

.legal-contact {
  scroll-margin-top: 104px;
  margin-top: var(--space-10);
  padding: var(--space-8);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
}

.legal-contact h2 {
  margin-top: 0;
  margin-bottom: var(--space-3);
  font-size: var(--text-xl);
}

/* The section tick belongs to running text, not to the card. */
.legal-contact h2::before { display: none; }

.legal-contact p { margin-bottom: 0; }

/* The address sits inline mid-sentence, so the chip must not add height —
   padding here pushes the whole line and breaks the leading. */
.legal-contact strong {
  font-family: var(--font-mono);
  font-size: 0.9em;
  font-weight: 500;
  color: var(--brand);
  padding: 0.12em 0.5em;
  border-radius: var(--radius-sm);
  background: var(--brand-soft);
  white-space: nowrap;
}

/* --- Responsive ----------------------------------------------------------- */

@media (max-width: 1024px) {
  .legal-layout {
    grid-template-columns: 1fr;
    gap: var(--space-8);
  }

  .legal-toc {
    position: static;
    padding-bottom: var(--space-6);
    border-bottom: 1px solid var(--border);
  }

  .legal-toc ol {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    border-left: 0;
  }

  .legal-toc a {
    margin-left: 0;
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    padding: var(--space-2) var(--space-4);
  }

  .legal-toc a.is-current {
    border-color: var(--brand);
  }

  .legal-body { max-width: none; }
}

@media (max-width: 768px) {
  .legal-hero {
    padding-block: var(--space-6) var(--space-8);
    margin-bottom: var(--space-8);
  }

  .legal-contact { padding: var(--space-6); }
}

/* ==========================================================================
   23. Article / Product Detail Page
   ========================================================================== */

/* One grid for the whole page. Head, hero and related span it edge to edge
   so the article matches the width of every other template; only the body
   text is inset, between the two rails. */
.article-page {
  display: grid;
  grid-template-columns:
    var(--article-toc)
    minmax(0, 1fr)
    var(--article-rail);
  column-gap: var(--article-gap);
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--space-5);
  padding-top: var(--space-10);
}

.article-head     { grid-column: 1 / -1; grid-row: 1; }
.article-hero     { grid-column: 1 / -1; grid-row: 2; }
.article-rail-left{ grid-column: 1;      grid-row: 3; }
.article-main     { grid-column: 2;      grid-row: 3; }
.article-aside    { grid-column: 3;      grid-row: 3; }
.article-foot     { grid-column: 1 / -1; grid-row: 4; }

/* The rails themselves are plain full-height grid items; the sticky element
   is the child inside. Putting sticky on the grid item AND shrinking it with
   align-self:start stops it being clamped to the row, so it slides on past
   the body and lands on top of the related articles below. Letting the rail
   stretch to the row height gives the sticky child a containing block that
   ends where the body ends. */
.article-rail-left,
.article-aside {
  align-self: stretch;
  min-height: 0;
}

/* Running text in the head keeps a readable measure, left-aligned to the
   page edge rather than centred in the shell. */
.article-head-text {
  max-width: 46rem;
}

.article-head .breadcrumb { margin-bottom: var(--space-5); }

.article-head .article-category { margin-bottom: var(--space-4); display: inline-block; }

/* Standfirst — the excerpt already in the data, which the page never showed. */
.article-dek {
  font-size: 1.1875rem;
  line-height: 1.55;
  color: var(--ink-muted);
  margin-bottom: var(--space-6);
  text-wrap: pretty;
}

.article-meta {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--text-sm);
  color: var(--ink-muted);
  margin-bottom: var(--space-8);
  padding-bottom: var(--space-6);
  border-bottom: 1px solid var(--border);
}

.article-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--brand-soft);
  color: var(--brand);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.04em;
}

.article-meta-text { display: flex; flex-direction: column; line-height: 1.35; }
.article-meta-sub { color: var(--ink-faint); font-size: var(--text-xs); }

.article-image {
  width: 100%;
  border-radius: var(--radius-lg);
  margin-bottom: var(--space-10);
  aspect-ratio: 21 / 9;
  object-fit: cover;
  background: var(--surface-sunken);
}

/* --- Two-column body + merchant rail ------------------------------------- */

.article-main { min-width: 0; }

.article-rail-left > .article-toc,
.article-aside > .offer-panel {
  position: sticky;
  top: 104px;
}

.article-hero { margin: 0; }

/* --- Contents ------------------------------------------------------------- */

.article-toc {
  padding-right: var(--space-4);
  border-left: 1px solid var(--border);
  padding-left: var(--space-4);
}

.article-toc a {
  display: block;
  padding-block: var(--space-1);
}

.article-toc-head {
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--ink-faint);
  margin-bottom: var(--space-3);
}

.article-toc ol {
  list-style: none;
  counter-reset: atoc;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.article-toc li { counter-increment: atoc; }

.article-toc a {
  font-size: var(--text-base);
  color: var(--ink-soft);
  transition: color var(--transition);
}

.article-toc a::before {
  content: counter(atoc) '. ';
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

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

.article-body h2 { scroll-margin-top: 104px; }

/* --- Merchant panel ------------------------------------------------------- */

.offer-panel {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}

.offer-panel-head {
  display: flex;
  flex-direction: column;
}

.offer-panel-media {
  width: 100%;
  aspect-ratio: 16 / 10;
  background: var(--surface-sunken);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.offer-panel-media img { width: 100%; height: 100%; }

/* A product photo fills the frame. */
.offer-panel-media.is-photo img { object-fit: cover; }

/* A wordmark must never be cropped, so it sits contained with breathing room
   on a neutral field. */
.offer-panel-media.is-mark {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  padding: var(--space-5) var(--space-6);
}

.offer-panel-media.is-mark img { object-fit: contain; }

/* Typographic plate for merchants with no usable artwork. Tinted from the
   category colour so it still reads as part of the page rather than as a
   missing asset. */
.offer-panel-media.is-fallback {
  background:
    radial-gradient(120% 100% at 50% 0%,
      color-mix(in srgb, var(--tile-tint, var(--brand)) 20%, transparent),
      transparent 70%),
    var(--surface-sunken);
  border-bottom: 1px solid var(--border);
  padding: var(--space-5);
}

.offer-panel-mark {
  font-family: var(--font-display);
  font-size: 3rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1;
  color: color-mix(in srgb, var(--tile-tint, var(--brand)) 72%, var(--ink));
  opacity: 0.9;
}

.offer-panel-id { padding: var(--space-5) var(--space-5) var(--space-4); }

.offer-panel-label {
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--ink-faint);
  margin-bottom: var(--space-2);
}

.offer-panel-brand {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ink);
  line-height: 1.15;
}

.offer-panel-host {
  font-size: var(--text-xs);
  color: var(--ink-muted);
  margin-top: var(--space-1);
  word-break: break-all;
}

.offer-panel-cta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  margin: 0 var(--space-5);
  padding: var(--space-4);
  border-radius: var(--radius-pill);
  background: var(--brand);
  color: #fff;
  font-size: var(--text-base);
  font-weight: 600;
  box-shadow: 0 8px 20px -12px var(--brand);
  transition: background-color var(--transition), transform var(--transition),
              box-shadow var(--transition);
}

.offer-panel-cta svg { width: 15px; height: 15px; }

.offer-panel-cta:hover {
  background: var(--brand-hover);
  transform: translateY(-2px);
  box-shadow: 0 14px 26px -12px var(--brand);
}

.offer-panel-note {
  font-size: var(--text-2xs);
  line-height: 1.55;
  color: var(--ink-faint);
  padding: var(--space-4) var(--space-5) var(--space-5);
  text-align: center;
}

/* --- Sticky CTA ----------------------------------------------------------- */

/* Appears once the reader is past the inline panel. On phones the rail is
   stacked below the text, so this is the only persistent route to the offer. */
.sticky-cta {
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  z-index: 95;
  padding: var(--space-3) var(--space-4);
  background: color-mix(in srgb, var(--ground) 86%, transparent);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  backdrop-filter: saturate(180%) blur(18px);
  border-top: 1px solid var(--border);
  transform: translateY(110%);
  visibility: hidden;
  transition: transform 0.3s var(--ease), visibility 0.3s var(--ease);
}

.sticky-cta.is-visible { transform: none; visibility: visible; }

.sticky-cta-inner {
  max-width: 1060px;
  margin-inline: auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}

.sticky-cta-text { display: flex; flex-direction: column; min-width: 0; }

.sticky-cta-brand {
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--brand);
}

.sticky-cta-title {
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sticky-cta-btn {
  flex-shrink: 0;
  padding: var(--space-3) var(--space-6);
  border-radius: var(--radius-pill);
  background: var(--brand);
  color: #fff;
  font-size: var(--text-base);
  font-weight: 600;
  white-space: nowrap;
  transition: background-color var(--transition);
}

.sticky-cta-btn:hover { background: var(--brand-hover); }

/* The back-to-top button would sit on top of the bar. */
.sticky-cta.is-visible ~ .to-top { bottom: calc(var(--space-6) + 68px); }

/* --- Related -------------------------------------------------------------- */

.article-related {
  margin-top: var(--space-16);
  padding-top: var(--space-10);
  border-top: 1px solid var(--border);
}

.article-related-head {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 600;
  letter-spacing: -0.02em;
  margin-bottom: var(--space-6);
}

.article-related-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-5);
}

.related-card { display: block; }

.related-card img {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  border-radius: var(--radius);
  background: var(--surface-sunken);
  margin-bottom: var(--space-3);
  transition: transform 0.5s var(--ease);
}

.related-card { overflow: hidden; border-radius: var(--radius); }
.related-card:hover img { transform: scale(1.04); }

.related-card-title {
  display: block;
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 600;
  line-height: var(--leading-snug);
  color: var(--ink);
  transition: color var(--transition);
}

.related-card:hover .related-card-title { color: var(--brand); }

.related-card-date {
  display: block;
  font-size: var(--text-2xs);
  color: var(--ink-muted);
  margin-top: var(--space-1);
}

/* --- Responsive ----------------------------------------------------------- */

/* Not enough room for two rails — contents moves inline above the text. */
@media (max-width: 1200px) {
  .article-page {
    grid-template-columns: minmax(0, 1fr) var(--article-rail);
  }

  .article-rail-left {
    grid-column: 1;
    grid-row: 3;
  }

  .article-rail-left > .article-toc { position: static; }

  .article-main  { grid-column: 1; grid-row: 4; }
  .article-aside { grid-column: 2; grid-row: 3 / span 2; }

  .article-toc {
    border-left: 0;
    padding: var(--space-5) var(--space-6);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--surface);
    margin-bottom: var(--space-8);
  }
}

@media (max-width: 1024px) {
  .article-page {
    grid-template-columns: minmax(0, 1fr);
    max-width: 48rem;
  }

  .article-head,
  .article-hero,
  .article-rail-left,
  .article-main,
  .article-aside,
  .article-foot { grid-column: 1; }

  .article-rail-left { grid-row: 3; }
  .article-main  { grid-row: 4; }
  /* Stacked below the text, so nothing should try to stick. */
  .article-aside { grid-row: 5; margin-top: var(--space-10); }
  .article-aside > .offer-panel { position: static; }
  .article-foot  { grid-row: 6; }

  .article-head-text { max-width: none; }
  .article-image { aspect-ratio: 16 / 9; }

  .offer-panel-head { flex-direction: row; align-items: stretch; }
  .offer-panel-media { width: 180px; aspect-ratio: auto; flex-shrink: 0; }
  .offer-panel-id { flex: 1; }
}

@media (max-width: 768px) {
  .article-related-grid { grid-template-columns: 1fr; gap: var(--space-6); }
  .article-image { aspect-ratio: 4 / 3; margin-bottom: var(--space-8); }
  .sticky-cta-title { display: none; }
  .sticky-cta-inner { justify-content: space-between; }
  .sticky-cta-btn { flex: 1; text-align: center; }
  .offer-panel-media { width: 120px; }
}

@media (prefers-reduced-motion: reduce) {
  .offer-panel-cta:hover { transform: none; }
  .related-card:hover img { transform: none; }
}

/* ==========================================================================
   24. Premium Motion

   Reveals prefer native scroll-driven animation (`animation-timeline: view()`)
   which the compositor runs off the main thread — smoother than an
   IntersectionObserver toggling classes, and zero JS per frame. app.js adds
   .reveal-native when the browser supports it and then skips its observer
   entirely; everything else falls back to the JS path in section 20.
   ========================================================================== */

@keyframes sg-enter {
  from {
    opacity: 0;
    transform: translateY(26px) scale(0.985);
    filter: blur(6px);
  }
  to {
    opacity: 1;
    transform: none;
    filter: blur(0);
  }
}

@supports (animation-timeline: view()) {
  html.reveal-native :is(
    .hero-card,
    .card-row .card,
    .category-section,
    .article-card,
    .sr-card,
    .latest-blog > *,
    .article-hero,
    .cta-callout,
    .related-card,
    .footer-chip
  ) {
    animation: sg-enter linear both;
    animation-timeline: view();
    /* Resolves while the element travels the first third of the viewport, so
       it has finished well before the reader's eye arrives. */
    animation-range: entry 4% cover 26%;
  }

  /* Cards in a row resolve as a sweep rather than together. */
  html.reveal-native .card-row .card:nth-child(2),
  html.reveal-native .article-related-grid .related-card:nth-child(2) {
    animation-range: entry 4% cover 30%;
  }

  html.reveal-native .card-row .card:nth-child(3),
  html.reveal-native .article-related-grid .related-card:nth-child(3) {
    animation-range: entry 4% cover 34%;
  }

  /* Section rules draw themselves in. */
  html.reveal-native .section-head {
    animation: sg-rule linear both;
    animation-timeline: view();
    animation-range: entry 10% cover 28%;
  }

  @keyframes sg-rule {
    from { border-bottom-color: transparent; }
    to   { border-bottom-color: var(--border); }
  }

  /* Hero photographs drift as they cross the viewport. Background-position
     is used rather than transform so the card's own corners stay put. */
  html.reveal-native .hero-card,
  html.reveal-native .card-row .card {
    animation: sg-enter linear both, sg-drift linear both;
    animation-timeline: view(), view();
    animation-range: entry 4% cover 26%, cover 0% cover 100%;
  }

  @keyframes sg-drift {
    from { background-position: center 42%; }
    to   { background-position: center 58%; }
  }
}

/* --------------------------------------------------------------------------
   Pointer spotlight
   A soft highlight tracks the cursor across a card. Coordinates come from a
   rAF-throttled pointermove in app.js as --mx / --my percentages.
   -------------------------------------------------------------------------- */

.article-card,
.sr-card,
.related-card,
.offer-panel {
  --mx: 50%;
  --my: 50%;
}

.article-card::after,
.sr-card::after,
.offer-panel::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.35s var(--ease);
  background: radial-gradient(
    22rem circle at var(--mx) var(--my),
    color-mix(in srgb, var(--brand) 14%, transparent),
    transparent 62%);
}

.article-card:hover::after,
.sr-card:hover::after,
.offer-panel:hover::after { opacity: 1; }

/* The gradient must sit under the text, not over it. */
.article-card .card-body,
.sr-card-content,
.offer-panel > * { position: relative; z-index: 2; }

/* The title link's stretched ::after must clear the spotlight layer. */
.article-card .card-body { z-index: 2; }

/* --------------------------------------------------------------------------
   Image arrival
   A wipe rather than a fade: it reads as the photograph being placed.
   -------------------------------------------------------------------------- */

@keyframes sg-wipe {
  from { clip-path: inset(0 0 100% 0); opacity: 0; }
  to   { clip-path: inset(0 0 0 0); opacity: 1; }
}

html.js .article-image,
html.js .category-featured img {
  animation: sg-wipe 0.7s var(--ease) both;
}

@supports (animation-timeline: view()) {
  html.reveal-native .category-featured img {
    animation: sg-wipe linear both;
    animation-timeline: view();
    animation-range: entry 0% cover 22%;
  }
}

/* --------------------------------------------------------------------------
   Link and control polish
   -------------------------------------------------------------------------- */

.section-more svg,
.footer-cta svg,
.offer-panel-cta svg {
  transition: transform var(--transition);
}

.section-more:hover svg,
.footer-cta:hover svg { transform: translateX(3px); }

.offer-panel-cta:hover svg { transform: translate(2px, -2px); }

/* Titles pick up an underline that grows from the left. */
.article-card-title,
.sr-card-title a,
.related-card-title {
  background-image: linear-gradient(var(--brand), var(--brand));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 1px;
  transition: background-size 0.35s var(--ease), color var(--transition);
}

.article-card:hover .article-card-title,
.sr-card:hover .sr-card-title a,
.related-card:hover .related-card-title { background-size: 100% 1px; }

/* --------------------------------------------------------------------------
   Reduced motion — everything above is decoration and switches off.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html.reveal-native :is(
    .hero-card, .card-row .card, .category-section, .article-card, .sr-card,
    .latest-blog > *, .article-hero, .cta-callout, .related-card, .footer-chip,
    .section-head, .category-featured img
  ) {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    clip-path: none !important;
  }

  html.js .article-image,
  html.js .category-featured img { animation: none; }

  .article-card::after,
  .sr-card::after,
  .offer-panel::after { display: none; }

  .article-card-title,
  .sr-card-title a,
  .related-card-title { transition: color var(--transition); }
}

/* ==========================================================================
   25. Article Footer & 404
   ========================================================================== */

/* --- Share --------------------------------------------------------------- */

.article-share {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding-block: var(--space-8);
  border-top: 1px solid var(--border);
}

.article-share-label {
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--ink-faint);
  margin-right: var(--space-1);
}

.article-share-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--ink-muted);
  cursor: pointer;
  padding: 0;
  transition: color var(--transition), border-color var(--transition),
              transform var(--transition);
}

.article-share-btn svg { width: 16px; height: 16px; }

.article-share-btn:hover {
  color: var(--brand);
  border-color: var(--brand);
  transform: translateY(-2px);
}

.article-share-btn.is-copied {
  color: #fff;
  background: var(--brand);
  border-color: var(--brand);
}

/* --- Previous / next ------------------------------------------------------ */

.article-nav {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
  padding-bottom: var(--space-4);
}

.article-nav-link {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-5) var(--space-6);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  transition: border-color var(--transition), transform var(--transition),
              box-shadow var(--transition);
}

.article-nav-link.is-empty {
  border: 0;
  background: none;
  pointer-events: none;
}

.article-nav-link.is-next { text-align: right; }

.article-nav-link:hover {
  border-color: var(--brand);
  transform: translateY(-2px);
  box-shadow: var(--shadow);
}

.article-nav-dir {
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--brand);
}

.article-nav-title {
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 600;
  line-height: var(--leading-snug);
  color: var(--ink);
}

/* --- 404 ------------------------------------------------------------------ */

.nf {
  padding-block: var(--space-20) var(--space-16);
  text-align: center;
  background: linear-gradient(to bottom,
    color-mix(in srgb, var(--brand) 6%, transparent), transparent 70%);
}

.nf-code {
  font-family: var(--font-display);
  font-size: clamp(4rem, 3rem + 8vw, 8rem);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.05em;
  color: color-mix(in srgb, var(--brand) 26%, transparent);
  margin-bottom: var(--space-4);
}

.nf-title {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 600;
  letter-spacing: -0.03em;
  color: var(--ink);
  margin-bottom: var(--space-4);
}

.nf-lede {
  font-size: var(--text-base);
  color: var(--ink-muted);
  max-width: 46ch;
  margin-inline: auto;
  margin-bottom: var(--space-8);
}

.nf-actions {
  display: flex;
  gap: var(--space-3);
  justify-content: center;
  flex-wrap: wrap;
  margin-bottom: var(--space-16);
}

.nf-btn {
  display: inline-flex;
  align-items: center;
  padding: var(--space-3) var(--space-6);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--ink-soft);
  transition: border-color var(--transition), color var(--transition),
              background-color var(--transition), transform var(--transition);
}

.nf-btn:hover { border-color: var(--brand); color: var(--brand); transform: translateY(-2px); }

.nf-btn-primary {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
  box-shadow: 0 8px 22px -12px var(--brand);
}

.nf-btn-primary:hover { background: var(--brand-hover); color: #fff; }

.nf-browse-head {
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--ink-faint);
  margin-bottom: var(--space-5);
}

@media (max-width: 640px) {
  .article-nav { grid-template-columns: 1fr; }
  .article-nav-link.is-next { text-align: left; }
  .nf { padding-block: var(--space-12) var(--space-10); }
}

@media (prefers-reduced-motion: reduce) {
  .article-share-btn:hover,
  .article-nav-link:hover,
  .nf-btn:hover { transform: none; }
}
