/* ==========================================================================
   Briefcase — static design system
   Pages: index.html (front page) · article.html (single story)
   No build step, no dependencies. Open index.html directly in a browser.
   --------------------------------------------------------------------------
   1  Tokens
   2  Reset & base
   3  Layout primitives
   4  Typography helpers
   5  Buttons, pills, meta
   6  Header / nav
   7  Thumbnails & topics
   8  Cards
   9  Hero
   10 Digest (60-second brief)
   11 Panels
   12 Section heads
   13 Comparison table
   14 Quotes
   15 Newsletter
   16 Article page
   17 Footer
   18 Utilities, motion, print
   ========================================================================== */

/* 0. Fonts ------------------------------------------------------------------ */
/* Self-hosted, so the first paint does not wait on a third-party stylesheet and the reader's IP address
   never leaves for Google's font CDN. Both families are OFL; the files are latin subsets, which is all
   the site's English copy needs (the typographic dashes and quotes it uses are inside U+2000-206F).
   `swap` plus the metric overrides below keeps the trade-off honest: text paints at once in a fallback
   whose size matches, then the real face arrives without moving the layout. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/static/fonts/inter.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Newsreader";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/static/fonts/newsreader.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Newsreader";
  font-style: italic;
  font-weight: 400 600;
  font-display: swap;
  src: url("/static/fonts/newsreader-italic.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* The fallback faces carry the real faces' metrics, so the swap does not move a line. The numbers come
   from the face's own hhea table rounded to the numbers a browser accepts. */
@font-face {
  font-family: "Inter Fallback";
  src: local("Arial"), local("Helvetica"), local("Liberation Sans");
  size-adjust: 106%;
  ascent-override: 90%;
  descent-override: 22%;
  line-gap-override: 0%;
}

@font-face {
  font-family: "Newsreader Fallback";
  src: local("Georgia"), local("Times New Roman"), local("Liberation Serif");
  size-adjust: 107%;
  ascent-override: 91%;
  descent-override: 24%;
  line-gap-override: 0%;
}

/* 1. Tokens ---------------------------------------------------------------- */
:root {
  --font-sans: "Inter", "Inter Fallback", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-serif: "Newsreader", "Newsreader Fallback", ui-serif, Georgia, "Times New Roman", serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --paper: #ffffff;
  --canvas: #fafafa;
  --surface: #ffffff;
  --surface-2: #f4f5f7;
  --ink: #12151a;
  --ink-2: #3a414c;
  /* The article body's own colour: charcoal rather than the secondary grey the chrome uses, because
     long-form text is read, not scanned. */
  --text-body: #212529;
  --muted: #6c727e;
  --line: #e6e8eb;
  --line-2: #d3d7dd;

  --accent: #0969da;
  --accent-strong: #0550ae;
  --accent-soft: #eaf2fd;
  --accent-ink: #ffffff;

  --link: #0b57d0;
  --good: #0f7a5a;

  --dark: #0f1218;
  --dark-2: #171b23;
  --dark-line: #262b35;
  --on-dark: #eceef2;
  --on-dark-muted: #9aa2b0;

  --wrap: 1200px;
  /* 1340 keeps the article text between 680px and 760px once the wrap's padding, the contents column,
     the rail and the two column gaps are taken out of it. */
  --wrap-article: 1340px;
  --wrap-narrow: 700px;

  --r-xs: 6px;
  --r-sm: 10px;
  --r: 14px;
  --r-lg: 22px;

  --shadow-1: 0 1px 2px rgba(17, 20, 25, .05), 0 1px 3px rgba(17, 20, 25, .04);
  --shadow-2: 0 20px 44px -24px rgba(17, 20, 25, .3);

  --header-h: 66px;
}

[data-theme="dark"] {
  --paper: #101319;
  --canvas: #0c0e13;
  --surface: #14171e;
  --surface-2: #1a1e27;
  --ink: #eceef2;
  --ink-2: #c2c7d0;
  --text-body: #dfe3ea;
  --muted: #8c94a2;
  --line: #242832;
  --line-2: #333946;

  --accent: #4c9aff;
  --accent-strong: #79b8ff;
  --accent-soft: #0d1b2e;
  --accent-ink: #06121f;

  --link: #8ab0ff;
  --good: #4ecfa4;

  --dark: #080a0e;
  --dark-2: #12151c;
  --shadow-1: none;
  --shadow-2: 0 20px 44px -24px rgba(0, 0, 0, .7);
}

/* Topic accents (used by .thumb, .t-* wrappers and eyebrows) */
.t-security { --topic: #2f5bd7; --topic-soft: #edf1fe; }
.t-cloud    { --topic: #0f6f8c; --topic-soft: #e8f4f8; }
.t-saas     { --topic: #5b3fd6; --topic-soft: #f0edfe; }
.t-itops    { --topic: #0f6f5c; --topic-soft: #e9f6f1; }
.t-buyers   { --topic: #b3541e; --topic-soft: #fdf0e7; }

[data-theme="dark"] .t-security { --topic-soft: #141c33; }
[data-theme="dark"] .t-cloud    { --topic-soft: #0d2229; }
[data-theme="dark"] .t-saas     { --topic-soft: #1d1633; }
[data-theme="dark"] .t-itops    { --topic-soft: #0f2620; }
[data-theme="dark"] .t-buyers   { --topic-soft: #2a1a10; }

/* 2. Reset & base ---------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 24px;
}

body {
  margin: 0;
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img, svg, video { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; }
hr { border: 0; border-top: 1px solid var(--line); margin: 40px 0; }

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--font-serif);
  font-weight: 600;
  line-height: 1.13;
  letter-spacing: -.015em;
}

p { margin: 0; }
ul, ol { margin: 0; padding: 0; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 3px;
}

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

/* 3. Layout primitives ----------------------------------------------------- */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: 24px;
}

.wrap--article { max-width: var(--wrap-article); }
.wrap--narrow { max-width: var(--wrap-narrow); }

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

.section { padding-block: 56px; }
.section--tight { padding-block: 40px; }
.section + .section { border-top: 1px solid var(--line); }

/* 4. Typography helpers ---------------------------------------------------- */
.eyebrow {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-family: var(--font-sans);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--topic, var(--accent));
}

.eyebrow::before {
  content: "";
  width: 16px;
  height: 2px;
  background: currentColor;
  border-radius: 2px;
}

.eyebrow--plain::before { display: none; }
.eyebrow--light { color: #79b8ff; }
.eyebrow--plain { padding-left: 0; }

.lede { font-size: 19px; line-height: 1.62; color: var(--ink-2); }
.small { font-size: 14.5px; line-height: 1.55; color: var(--muted); }
.serif { font-family: var(--font-serif); }
.mono {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: .02em;
}

/* 5. Buttons, pills, meta -------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 11px 18px;
  border: 1px solid transparent;
  border-radius: 999px;
  background: var(--ink);
  color: var(--canvas);
  font-size: 14.5px;
  font-weight: 600;
  letter-spacing: -.005em;
  cursor: pointer;
  transition: transform .12s ease, background .15s ease, color .15s ease, border-color .15s ease;
}

.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn--accent { background: var(--accent); color: var(--accent-ink); }
.btn--accent:hover { background: var(--accent-strong); }
.btn--ghost {
  background: transparent;
  color: var(--ink);
  border-color: var(--line-2);
}
.btn--ghost:hover { border-color: var(--ink); background: var(--surface); }
.btn--lg { padding: 15px 26px; font-size: 16px; }
.btn--sm { padding: 8px 14px; font-size: 13.5px; }
.btn--block { width: 100%; }

.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--topic-soft, var(--surface-2));
  color: var(--topic, var(--ink-2));
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 7px;
  font-size: 13.5px;
  color: var(--muted);
}
.meta__sep { color: var(--line-2); }

/* 6. Header / nav ---------------------------------------------------------- */
/* The header scrolls away with the page. It stays `relative` because the mobile nav panel is positioned
   against it, and it keeps a stacking context of its own so that panel sits over the stories below. No
   blur: a translucent bar only mattered while it floated over the content, and a transparent layer that
   scrolls out of sight is just paint work. */
.site-header {
  position: relative;
  z-index: 30;
  background: var(--canvas);
  border-bottom: 1px solid var(--line);
}

.site-header__inner {
  display: flex;
  align-items: center;
  gap: 26px;
  min-height: var(--header-h);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-serif);
  font-size: 23px;
  font-weight: 600;
  letter-spacing: -.03em;
  white-space: nowrap;
}

.brand__tld { color: var(--accent); }

.nav { display: flex; align-items: center; gap: 4px; margin-inline-start: 6px; }

.nav__link {
  padding: 8px 11px;
  border-radius: 999px;
  font-size: 14.5px;
  font-weight: 500;
  color: var(--ink-2);
  white-space: nowrap;
  transition: background .15s ease, color .15s ease;
}
.nav__link:hover { background: var(--surface-2); color: var(--ink); }
.nav__link[aria-current="page"] { color: var(--ink); font-weight: 600; }
.nav__link[aria-current="page"]::after {
  content: "";
  display: block;
  height: 2px;
  margin-top: 5px;
  border-radius: 2px;
  background: var(--accent);
}
/* The Buyer Guides door is the only one the header sets apart: it is where a reader who already has a
   decision to make lands, rather than a subject to browse. */
.nav__link--cta {
  color: var(--accent-strong);
  font-weight: 600;
  background: var(--accent-soft);
}
.nav__link--cta:hover { background: var(--accent-soft); color: var(--accent-strong); }

.header__actions { display: flex; align-items: center; gap: 10px; margin-inline-start: auto; }

/* The header search sits immediately before the theme button: an input wide enough for a word or two,
   and the same pill button as the rest of the chrome. On narrow screens the input folds away and the
   button alone opens the search page, which has the full field. */
.header-search {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 3px 3px 3px 12px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
}
.header-search:focus-within { border-color: var(--ink); }
.header-search__input {
  width: 150px;
  border: 0;
  background: none;
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  padding: 5px 0;
}
.header-search__input:focus { outline: none; }
.header-search__input::placeholder { color: var(--muted); }
.header-search__input::-webkit-search-cancel-button { appearance: none; }
.header-search__btn {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--ink-2);
  cursor: pointer;
}
.header-search__btn:hover { background: var(--surface-2); color: var(--ink); }
.header-search__btn svg { width: 16px; height: 16px; }

.icon-btn {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink-2);
  cursor: pointer;
}
.icon-btn:hover { border-color: var(--ink); color: var(--ink); }
.icon-btn svg { width: 17px; height: 17px; }

.nav-toggle { display: none; }

/* 7. Thumbnails & topics --------------------------------------------------- */
.thumb {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: var(--r-sm) var(--r-sm) 0 0;
  background:
    radial-gradient(120% 120% at 88% 8%, color-mix(in srgb, var(--topic, #2f5bd7) 62%, #ffffff) 0%, transparent 58%),
    linear-gradient(150deg, color-mix(in srgb, var(--topic, #2f5bd7) 82%, #101319) 0%, color-mix(in srgb, var(--topic, #2f5bd7) 34%, #0f1218) 100%);
}

/* Two soft light pockets, repositioned per card so a row of placeholders
   never reads as three copies of the same block. */
.thumb::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(40% 58% at var(--bx, 82%) var(--by, 14%), rgba(255, 255, 255, .3), transparent 72%),
    radial-gradient(48% 64% at var(--cx, 12%) var(--cy, 98%), rgba(0, 0, 0, .32), transparent 70%);
  transition: transform .6s ease;
}

.grid .card:nth-child(3n+2) .thumb { --bx: 16%; --by: 76%; --cx: 88%; --cy: 8%; }
.grid .card:nth-child(3n) .thumb { --bx: 54%; --by: 30%; --cx: 30%; --cy: 104%; }
.hero__side .card--row:nth-child(2) .thumb { --bx: 70%; --by: 70%; }
.hero__side .card--row:nth-child(3) .thumb { --bx: 24%; --by: 26%; }
.hero__side .card--row:nth-child(4) .thumb { --bx: 60%; --by: 44%; }

a.card:hover .thumb::before { transform: scale(1.07); }

.thumb::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    repeating-linear-gradient(0deg, rgba(255, 255, 255, .07) 0 1px, transparent 1px 34px),
    repeating-linear-gradient(90deg, rgba(255, 255, 255, .07) 0 1px, transparent 1px 34px);
  mask-image: linear-gradient(to bottom, rgba(0, 0, 0, .9), transparent 85%);
}

.thumb__tag {
  position: absolute;
  left: 14px;
  bottom: 13px;
  z-index: 1;
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(12, 14, 19, .55);
  color: #fff;
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: .09em;
  text-transform: uppercase;
  backdrop-filter: blur(6px);
}

.thumb--sm { aspect-ratio: 4 / 3; width: 104px; flex: none; border-radius: var(--r-sm); }
.thumb--hero { aspect-ratio: 21 / 9; border-radius: var(--r); }
.thumb--hero .thumb__tag { left: 18px; bottom: 16px; }

/* A row that carries its own picture. The photo fills the tile and the category tag stays on top; the
   gradient and the grid below it exist to make an empty tile look designed, so they are switched off
   where there is a picture — otherwise they paint over it. */
.thumb--photo { background: var(--paper-3, #e9e7e2); }
.thumb--photo::before,
.thumb--photo::after { display: none; }

.thumb__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform .5s ease;
}

a.card:hover .thumb__img,
.for-you__link:hover .thumb__img { transform: scale(1.04); }

/* 8. Cards ----------------------------------------------------------------- */
.card {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface);
  box-shadow: var(--shadow-1);
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}

a.card:hover {
  transform: translateY(-3px);
  border-color: var(--line-2);
  box-shadow: var(--shadow-2);
}

.card__body { display: flex; flex-direction: column; gap: 10px; padding: 18px 20px 20px; }

/* One title type for every list on the front page: the cards, the rail's "Most read" list and the closing
   reading rows all set their titles with these four values.
   `.card__title` is an h3 and would inherit the serif face and the 600 weight from the base heading rule,
   but it declares them anyway so the rules can be compared line for line. */
.card__title {
  font-family: var(--font-serif);
  font-size: 21px;
  font-weight: 600;
  line-height: 1.2;
}
a.card:hover .card__title { color: var(--accent); }

.card__title--xl { font-size: clamp(30px, 3.5vw, 45px); line-height: 1.06; letter-spacing: -.025em; }
.card__title--sm { font-size: 17.5px; font-family: var(--font-sans); font-weight: 600; line-height: 1.3; letter-spacing: -.01em; }

.card__summary { font-size: 15.5px; line-height: 1.55; color: var(--muted); }
.card__summary--lg { font-size: 18px; line-height: 1.55; color: var(--ink-2); }

.card__flag {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--accent);
}
.card__flag::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
}

.card--flat { border: 0; background: transparent; box-shadow: none; }
.card--flat:hover { transform: none; box-shadow: none; }

.card--row { flex-direction: row; }
.card--row .thumb { flex: none; width: 128px; aspect-ratio: 1 / 1; border-radius: var(--r) 0 0 var(--r); }
.card--row .card__body { padding: 16px 18px; gap: 8px; }
.card--row .card__title { font-size: 18px; }

/* 9. Hero ------------------------------------------------------------------ */
.hero {
  display: grid;
  grid-template-columns: minmax(0, 1.62fr) minmax(0, 1fr);
  gap: 40px;
  padding-block: 6px 6px;
}

.hero__side { display: flex; flex-direction: column; gap: 16px; }
.hero__lead { display: flex; }
.hero__lead > .card { flex: 1; }

/* 11. Panels ---------------------------------------------------------------- */

/* 12. Section heads -------------------------------------------------------- */
.section__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  margin-bottom: 26px;
}

.section__title { font-size: clamp(25px, 2.4vw, 32px); margin-top: 10px; }
.section__sub { margin-top: 8px; max-width: 62ch; font-size: 15.5px; color: var(--muted); }

.link-more {
  flex: none;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink-2);
  border-bottom: 1px solid var(--line-2);
  padding-bottom: 2px;
  white-space: nowrap;
}
.link-more:hover { color: var(--accent); border-color: var(--accent); }

.radar { list-style: none; display: grid; gap: 0; border-top: 1px solid var(--line); }

.radar__item {
  display: grid;
  grid-template-columns: 132px minmax(0, 1fr) auto;
  gap: 22px;
  align-items: baseline;
  padding-block: 18px;
  border-bottom: 1px solid var(--line);
}
.radar__item:hover { background: var(--surface); }
.radar__src {
  font-family: var(--font-mono);
  font-size: 11.5px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
}
.radar__text { font-size: 16px; line-height: 1.5; color: var(--ink-2); }
.radar__text strong { color: var(--ink); font-weight: 600; }
.radar__time { font-size: 13.5px; color: var(--muted); white-space: nowrap; }

/* Tables inside an article: a plain bordered table, no badges and no links. */
.prose table {
  width: 100%;
  border-collapse: collapse;
  margin-block: 18px;
  font-size: 15.5px;
}
.prose table caption { text-align: left; padding-bottom: 10px; font-size: 14px; line-height: 1.5; color: var(--muted); }
.prose th, .prose td { padding: 12px 14px; border-bottom: 1px solid var(--line); text-align: left; vertical-align: top; }
.prose thead th {
  font-family: var(--font-sans);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--muted);
}
/* A comparison table sits in its own scroller, so a wide grid never pushes the article sideways on a
   phone. The first column is the row label and stays on one line. */
.datatable { overflow-x: auto; margin-block: 18px; }
.datatable table { margin-block: 0; min-width: 520px; }
.datatable th:first-child, .datatable td:first-child { white-space: nowrap; }
.datatable tbody tr:nth-child(even) { background: var(--surface-2); }

/* 13. Front-page helpers --------------------------------------------------- */
/* One front page ships: the lead hero, the headline list and the feed with its sticky rail. These are
   the few helpers it does not share with the entry page. */

/* Layout 6 — the busy front page: the lead hero, then a two-column feed with a sticky rail, and ad slots
   in the rail and between the feed rows. */
.rank-list { list-style: none; counter-reset: rank; display: grid; gap: 12px; }
.rank-list li {
  counter-increment: rank;
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr);
  gap: 8px;
  align-items: baseline;
}
.rank-list li::before {
  content: counter(rank);
  font-family: var(--font-mono);
  font-size: 15px;
  color: var(--accent);
}
.rank-list a { font-family: var(--font-serif); font-size: 21px; font-weight: 600; line-height: 1.2; color: var(--ink); }
.rank-list a:hover { color: var(--accent); }
.rank-list__meta { grid-column: 2; font-family: var(--font-mono); font-size: 11.5px; color: var(--muted); }

/* The closing "Stories for you" list: one entry per row, thumbnail on the left, headline and standfirst
   on the right. No rules between the rows — the thumbnail already separates them — and a tight 4px gap
   with 10px of padding, so the rows read as one block rather than four cards. */
.for-you__list { list-style: none; display: grid; gap: 4px; }
.for-you__link {
  display: grid;
  grid-template-columns: 216px minmax(0, 1fr);
  gap: 22px;
  align-items: center;
  padding-block: 10px;
}
.for-you__link .thumb { aspect-ratio: 16 / 10; border-radius: var(--r-sm); }
.for-you__body { display: grid; gap: 7px; align-content: start; min-width: 0; }
.for-you__title { font-family: var(--font-serif); font-size: 21px; font-weight: 600; line-height: 1.2; color: var(--ink); }
.for-you__link:hover .for-you__title { color: var(--accent); }
.for-you__summary { font-size: 15px; line-height: 1.55; color: var(--muted); max-width: 76ch; }
.for-you__meta { font-family: var(--font-mono); font-size: 11.5px; letter-spacing: .04em; color: var(--muted); }

.with-rail {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 36px;
  align-items: start;
  padding-block: 20px;
}
.feed { display: grid; gap: 6px; }
.rail { display: grid; gap: 20px; }
.rail__sticky { position: sticky; top: 16px; display: grid; gap: 20px; }
.rail__block {
  display: grid;
  gap: 10px;
  padding: 18px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface);
}

/* The sticky leaderboard under the header, and the two square units side by side. */
.ad-slot--sticky { position: sticky; top: 8px; z-index: 20; }
.ad-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
.ad-row .ad-slot { margin: 0; }

/* 14. Quotes --------------------------------------------------------------- */
.quote {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin: 0;
  padding: 24px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface);
}

.quote blockquote { margin: 0; }
.quote blockquote p {
  font-family: var(--font-serif);
  font-size: 19px;
  line-height: 1.42;
  color: var(--ink);
}

.quote__src {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: var(--muted);
}
.quote__src b { color: var(--ink-2); font-weight: 600; }

.quote__take {
  margin-top: auto;
  padding-top: 14px;
  border-top: 1px dashed var(--line-2);
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--ink-2);
}
.quote__take b { color: var(--accent); font-weight: 700; letter-spacing: .02em; }

/* 15. Newsletter ----------------------------------------------------------- */
/* The heading and one line on the left, the address and the button on the right, on one line wherever
   the screen allows it. No card and no list — the block asks for one thing. */
.newsletter {
  position: relative;
  overflow: hidden;
  background: var(--dark);
  color: var(--on-dark);
  padding-block: 46px;
}

.newsletter::before {
  content: "";
  position: absolute;
  inset: -60% -10% auto auto;
  width: 620px;
  height: 620px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(76, 154, 255, .22), transparent 62%);
  pointer-events: none;
}

.newsletter__inner {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 520px);
  gap: 32px;
  align-items: center;
  justify-content: space-between;
}

.newsletter__pitch { min-width: 0; display: grid; gap: 8px; }

.newsletter__title {
  font-size: clamp(22px, 2.2vw, 30px);
  color: #fff;
  margin: 0;
  letter-spacing: -.01em;
}
.newsletter__text { font-size: 16px; line-height: 1.5; color: var(--on-dark-muted); margin: 0; max-width: 70ch; }

.newsletter__pane { min-width: 0; display: grid; gap: 10px; }

.newsletter__form { min-width: 0; }

/* The trap field: off the page for a reader, still in the form for anything that fills every input it finds.
   display:none and visibility:hidden are skipped by the scripts this is for; moving the box out of the
   viewport is not. tabindex="-1" keeps it out of the keyboard order, so the readers who never see it never
   land on it either. */
.nl-trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* The field and its button on one line: the whole block is one action. */
.newsletter__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
}

input[type="email"], input[type="text"] {
  width: 100%;
  padding: 14px 16px;
  border: 1px solid var(--dark-line);
  border-radius: var(--r-sm);
  background: rgba(8, 10, 14, .6);
  color: #fff;
  font-family: inherit;
  font-size: 15.5px;
}
input[type="email"]::placeholder { color: #6d7686; }
input[type="email"]:focus-visible { outline-offset: 1px; }
input[aria-invalid="true"] { border-color: #ff9b9b; }

/* The contact form on the About page. The block above styles the newsletter field for the dark band; this is
   the same control on the light page, with a textarea, so the two never inherit each other's colours. */
.contact {
  display: grid;
  gap: 8px;
  max-width: 640px;
  margin-top: 14px;
}
.contact__title { margin-top: 46px; font-size: 25px; }
.contact__lede { margin: 6px 0 0; color: var(--ink-2); }
.contact__label {
  margin-top: 8px;
  font-size: 12.5px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
}
.contact input[type="text"], .contact textarea {
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--ink);
  font-family: inherit;
  font-size: 15.5px;
}
.contact textarea { min-height: 150px; resize: vertical; }
.contact input[type="text"]:focus-visible, .contact textarea:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.contact .btn { justify-self: start; margin-top: 10px; }

/* Both messages appear only after a submit, so the block itself stays two words wide. */
.form-error {
  margin-top: 10px;
  padding: 10px 12px;
  border: 1px solid rgba(255, 155, 155, .35);
  border-radius: var(--r-sm);
  background: rgba(255, 107, 107, .12);
  color: #ffc2c2;
  font-size: 13.5px;
  line-height: 1.45;
}
.form-success {
  padding: 13px 15px;
  border: 1px solid rgba(78, 207, 164, .35);
  border-radius: var(--r-sm);
  background: rgba(78, 207, 164, .12);
  color: #7ee0bb;
  font-size: 14.5px;
  line-height: 1.5;
}

/* 16. Article page --------------------------------------------------------- */
.progress {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 60;
  height: 3px;
  width: 0;
  background: var(--accent);
  transition: width .1s linear;
}

.crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--muted);
}
.crumbs a:hover { color: var(--accent); }
.crumbs__sep { color: var(--line-2); }

.article__head { padding-block: 34px 26px; }
.article__head .eyebrow { margin-top: 18px; }
.article__title {
  margin-block: 14px 16px;
  font-size: clamp(32px, 4.6vw, 54px);
  line-height: 1.04;
  letter-spacing: -.028em;
}
.article__summary { font-size: 21px; line-height: 1.55; color: var(--ink-2); }

/* The byline row is now just the reader's actions — copy the link, subscribe. The avatar and the
   "By the … desk" line were removed with the date, which moved to the foot of the article. */
.byline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid var(--line);
  font-size: 14px;
  color: var(--muted);
}
.byline__actions { margin-inline-start: auto; display: flex; gap: 8px; }

/* The date closes the article, under the sources. */
.article__foot {
  margin-top: 28px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: .04em;
  color: var(--muted);
}

.article__hero { margin-bottom: 12px; }
.article__hero figcaption {
  margin-top: 10px;
  font-size: 13px;
  color: var(--muted);
}

/* The article: contents on the left, the text in the middle, and the ad rail on the right. The text is
   about two thirds of the reading width and the rail about a third, which is the shape the ad layouts
   are priced for; the contents column is what keeps the measure itself at a readable length. The 50px
   column gap is deliberate: it is the distance the ad networks ask for between a unit and the links next
   to it, so the rail unit is never a mis-click away from the shortlist beside it. */
.article__layout {
  display: grid;
  grid-template-columns: 180px minmax(0, 1fr) 300px;
  gap: 50px;
  align-items: start;
  padding-block: 40px 24px;
}

/* The measure itself. On a narrow screen the rail is gone, so the text column would otherwise stretch to
   the full width of the wrap; capping it keeps the line length readable at every viewport. */
.article__main { max-width: 720px; }

/* The rail: the shortlist of buyer guides first, then the half-page, which follows the reader down the
   page. The unit is last on purpose — a sticky box with content below it gets covered by whatever
   scrolls past it. Sticking the container instead would clip it, because the rail is taller than the
   viewport.

   The *frame* is what sticks: the slot inside it is absolutely positioned (see `.ad-frame > .ad-slot`),
   so `position: sticky` on the slot itself would never move. The rule itself lives beside the frame
   heights, further down. */
.article__rail { display: grid; gap: 20px; align-content: start; }
.ad-slot--halfpage {
  min-height: 600px;
  margin: 0;
}
.rail-links {
  padding: 16px 18px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface);
}
.rail-links__title {
  font-family: var(--font-sans);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
}
.rail-links__list {
  list-style: none;
  display: grid;
  gap: 12px;
  margin-top: 12px;
  counter-reset: rail;
}
.rail-links__list li { display: grid; gap: 3px; padding-left: 22px; position: relative; }
.rail-links__list li::before {
  counter-increment: rail;
  content: counter(rail);
  position: absolute;
  left: 0;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--accent);
}
.rail-links__list a { font-size: 15px; line-height: 1.3; color: var(--ink); font-weight: 500; }
.rail-links__list a:hover { color: var(--accent); }
.rail-links__meta { font-family: var(--font-mono); font-size: 11px; color: var(--muted); letter-spacing: .03em; }

.toc { position: sticky; top: 20px; }
.toc__title {
  font-family: var(--font-sans);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 12px;
}
.toc ol { list-style: none; display: grid; gap: 2px; counter-reset: toc; }
.toc a {
  display: block;
  padding: 7px 12px;
  border-left: 2px solid var(--line);
  font-size: 14px;
  line-height: 1.35;
  color: var(--muted);
}
.toc a:hover { color: var(--ink); border-color: var(--line-2); }
.toc a.is-active { color: var(--ink); font-weight: 600; border-color: var(--accent); background: var(--surface); }

.article__main { min-width: 0; display: grid; gap: 34px; }

.tldr {
  padding: 28px 30px;
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--r);
  background: var(--surface);
  box-shadow: var(--shadow-1);
}
.tldr__title {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 14px;
}
.tldr ul { list-style: none; display: grid; gap: 13px; }
.tldr li {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  gap: 10px;
  font-size: 17px;
  line-height: 1.58;
  color: var(--ink-2);
}
.tldr li::before {
  content: "→";
  color: var(--accent);
  font-size: 14px;
  line-height: 1.7;
}
.tldr li b { color: var(--ink); font-weight: 600; }

/* The entry's own shortlist, written by hand in the admin. It closes the reading, just above the source
   list, and is a light card for the same reason the rest of the article is. */
.related-reading {
  margin-top: 26px;
  padding: 18px 22px 16px;
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--r);
  background: var(--surface);
}
.related-reading__title {
  font-family: var(--font-sans);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--accent);
}
.related-reading__list { list-style: none; display: grid; gap: 10px; margin-top: 12px; }
.related-reading__list li { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 4px 14px; align-items: baseline; }
.related-reading__list a { font-size: 16.5px; line-height: 1.3; color: var(--ink); font-weight: 500; }
.related-reading__list a:hover { color: var(--accent); }
.related-reading__meta { font-family: var(--font-mono); font-size: 11px; color: var(--muted); letter-spacing: .03em; white-space: nowrap; }

.prose { font-size: 19px; line-height: 1.78; color: var(--text-body); display: grid; gap: 26px; }
.prose > p { margin: 0; max-width: 68ch; text-wrap: pretty; }
.prose h2 {
  margin-top: 6px;
  font-size: clamp(26px, 2.6vw, 32px);
  line-height: 1.18;
  color: var(--ink);
  scroll-margin-top: 24px;
}
.prose h3 { margin-top: 10px; font-size: 22px; line-height: 1.25; color: var(--ink); }
.prose strong { color: var(--ink); font-weight: 600; }
.prose a {
  color: var(--ink);
  border-bottom: 1px solid var(--line-2);
}
.prose a:hover { color: var(--accent); border-color: var(--accent); }
.prose ul, .prose ol { display: grid; gap: 10px; padding-left: 22px; }
.prose li::marker { color: var(--accent); }
.prose code {
  padding: 2px 6px;
  border-radius: var(--r-xs);
  background: var(--surface-2);
  font-family: var(--font-mono);
  font-size: 14px;
  color: var(--ink);
}
/* A code block is dark even on the light page. It is the one container a developer reads as code, it
   keeps the article's reading surface light while the snippet stays legible, and GitHub's own dark
   palette is what the eye already expects. */
.prose pre {
  margin: 0;
  padding: 16px 18px;
  border-radius: var(--r-sm);
  background: #0d1117;
  color: #e6edf3;
  font-family: var(--font-mono);
  font-size: 14px;
  line-height: 1.6;
  overflow-x: auto;
}
.prose pre code {
  padding: 0;
  border-radius: 0;
  background: none;
  color: inherit;
  font-size: inherit;
}
.prose pre .code-caption {
  display: block;
  margin-bottom: 10px;
  color: #8b949e;
  font-size: 12px;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.lead-para::first-letter {
  float: left;
  margin: 6px 10px 0 0;
  font-family: var(--font-serif);
  font-size: 62px;
  line-height: .78;
  font-weight: 600;
  color: var(--accent);
}

.callout {
  display: grid;
  gap: 8px;
  padding: 20px 22px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface-2);
  font-size: 16.5px;
  line-height: 1.55;
  color: var(--ink-2);
}
.callout__label {
  font-family: var(--font-sans);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--ink);
}
.callout--warn { border-color: color-mix(in srgb, var(--accent) 38%, var(--line)); background: var(--accent-soft); }
.callout--warn .callout__label { color: var(--accent-strong); }

.toolpick {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 20px;
  align-items: center;
  padding: 22px 24px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface);
  box-shadow: var(--shadow-1);
}
.toolpick__name { font-family: var(--font-serif); font-size: 22px; font-weight: 600; }
.toolpick__text { margin-top: 6px; font-size: 15.5px; color: var(--muted); line-height: 1.5; }

.pull {
  margin: 6px 0;
  padding-left: 22px;
  border-left: 3px solid var(--accent);
  font-family: var(--font-serif);
  font-size: 24px;
  line-height: 1.35;
  color: var(--ink);
}

.inline-cta {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 22px;
  align-items: center;
  padding: 24px 26px;
  border-radius: var(--r);
  background: linear-gradient(120deg, var(--dark), var(--dark-2));
  color: var(--on-dark);
}
.inline-cta__title { font-family: var(--font-serif); font-size: 23px; color: #fff; }
.inline-cta__text { margin-top: 6px; font-size: 14.5px; color: var(--on-dark-muted); }

.sources { list-style: none; display: grid; gap: 9px; }.sources li {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr);
  gap: 8px;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--muted);
}
/* The number in the gutter matches the source's place in the list the story was compiled from. */
.sources__n {
  font-family: var(--font-mono);
  font-size: 11.5px;
  line-height: 1.75;
  color: var(--accent);
}
.sources a { color: var(--ink-2); border-bottom: 1px solid var(--line-2); }
.sources a:hover { color: var(--accent); border-color: var(--accent); }

/* The source list is a quiet appendix: small type, closed by default, opened with a click. */
.article-sources {
  margin-top: 26px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}
.article-sources__summary {
  display: flex;
  align-items: baseline;
  gap: 8px;
  cursor: pointer;
  list-style: none;
  font-family: var(--font-sans);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
}
.article-sources__summary::-webkit-details-marker { display: none; }
.article-sources__summary::before { content: "+"; font-family: var(--font-mono); color: var(--accent); }
.article-sources[open] .article-sources__summary::before { content: "–"; }
.article-sources__summary:hover { color: var(--ink-2); }
.article-sources__count { font-family: var(--font-mono); font-size: 10.5px; letter-spacing: 0; color: var(--muted); }
.article-sources .sources { margin-top: 10px; gap: 6px; }
.article-sources .sources li {
  grid-template-columns: 16px minmax(0, 1fr);
  gap: 6px;
  font-size: 13px;
  line-height: 1.5;
}
.article-sources .sources__n { font-size: 10.5px; line-height: 1.6; }

.authorbox {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  gap: 20px;
  align-items: start;
  padding: 24px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface);
}
.authorbox__avatar {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: linear-gradient(140deg, var(--accent), #5d2110);
}
.authorbox__name { font-family: var(--font-serif); font-size: 20px; font-weight: 600; }
.authorbox__role { font-size: 13.5px; color: var(--muted); margin-top: 2px; }
.authorbox__bio { margin-top: 10px; font-size: 15px; line-height: 1.55; color: var(--ink-2); }

.heading-block { display: grid; gap: 10px; }

/* Search page: one field, and two ways out of the page when the query found nothing. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.search-form { display: flex; gap: 10px; max-width: 620px; margin-top: 22px; }
.search-form__input {
  flex: 1;
  min-width: 0;
  padding: 13px 18px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
}
.search-form__input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.search-count { margin-top: 22px; }
.chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 18px; }
.chip {
  padding: 7px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink-2);
  font-size: 14px;
}
.chip:hover { border-color: var(--ink); color: var(--ink); }

.verified {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 600;
  color: var(--good);
}
.verified::before { content: "✓"; font-size: 11px; }

/* Ad slots. The slot is the space the unit goes in and nothing more: no border, no background, no label band —
   the owner wants the ad itself in the page, not a box around it. Height is still reserved (CLS is a ranking
   factor), and the label is still in the markup but screen-reader only (`.sr-only`), so a reader who cannot see
   the unit still hears what the block is; a sighted reader sees the creative, which carries its own attribution.
   The rule that must not come back: never fake the label in CSS (`:empty::before`) — a label that disappears the
   moment a unit loads is the disguise the label exists to prevent. */
.ad-slot {
  display: grid;
  /* One full-width column. Without it the slot's single column is sized to the unit's max-content width, which
     is zero before a unit fills, and AdSense answers the push with "No slot size for availableWidth=0". */
  grid-template-columns: minmax(0, 1fr);
  place-items: center;
  /* A creative is not always as wide as the band — the 970x250 billboard in a wider column, a 728x90 in a
     970px leaderboard — and one pinned to the left edge reads as a mistake under a centred headline. */
  text-align: center;
  margin: 0;
  padding: 0;
  min-height: 280px;
  overflow: hidden;
}
/* No margins around a unit: the owner asked for the space out, so every slot sits flush and the blocks
   around it (the hero's 6px, the feed's gap, the rail's gap) do the separating. The reserved min-height
   is what stays — a unit that changes the height of the page when it loads is a layout shift. */
.ad-slot--leaderboard { min-height: 120px; }
.ad-slot--inline { min-height: 250px; }
.ad-slot--square { min-height: 280px; }
/* The billboard above an article's headline: 970x250 on a desktop, a 320x100 strip on a phone. */
.ad-slot--billboard { min-height: 250px; }
.ad-slot .adsbygoogle { width: 100%; text-align: center; }
/* AdSense draws the creative in an iframe of its own width and leaves it in the line box; `margin-inline: auto`
   is what actually puts it in the middle when it is narrower than the `ins`. */
.ad-slot .adsbygoogle iframe { display: block; margin-inline: auto; }
.article__main > .ad-slot { margin-inline: 0; }

/* The reserved frame, and the reason it exists: when a unit comes back unfilled the AdSense loader collapses
   its container with an inline `height:auto !important; min-height:0 !important`, and everything below the
   slot jumps — a CLS of 0.33 on the front page. The frame holds the height the design reserved, so the script
   can do what it likes to the slot without moving a line.

   The frame's height is fixed and the slot is absolutely positioned inside it, which is what makes the
   reservation survive the loader: an unfilled unit puts an inline `height: auto !important` on the ins (and
   sometimes on its ancestors) and reserves a placeholder height of its own; in flow that placeholder moves
   everything below it, which measured as CLS 0.33. Absolute, the slot is out of flow and the frame keeps the
   height the design reserved.

   A creative can still be taller than the reservation, and an ad drawn over the content below is a policy
   violation — so the `fit` script in the ad-unit partial grows this frame when a *filled* unit is taller. It
   is the rare case (a leaderboard asks for a horizontal unit); the normal one never moves. */
.ad-frame { position: relative; }
.ad-frame > .ad-slot { position: absolute; inset: 0; margin: 0; }
.ad-frame--leaderboard { height: 120px; }
.ad-frame--inline { height: 250px; }
.ad-frame--square { height: 280px; }
.ad-frame--halfpage { height: 600px; }
/* The article rail's half-page follows the reader. The sticky is on the frame: the slot inside it is
   absolutely positioned, so sticking the slot would do nothing. */
.article__rail > .ad-frame--halfpage { position: sticky; top: 20px; }
.ad-frame--billboard { height: 250px; }
@media (max-width: 780px) {
  .ad-frame--billboard { height: 100px; }
}

/* 17. Footer --------------------------------------------------------------- */
.site-footer {
  margin-top: 8px;
  padding-block: 52px 40px;
  border-top: 1px solid var(--line);
  background: var(--canvas);
}

.footer__top {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) repeat(3, minmax(0, 1fr));
  gap: 40px;
  padding-bottom: 36px;
  border-bottom: 1px solid var(--line);
}

.footer__tagline { margin-top: 14px; max-width: 34ch; font-size: 15px; line-height: 1.55; color: var(--muted); }

.footer__col h3 {
  font-family: var(--font-sans);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 14px;
}
.footer__col ul { list-style: none; display: grid; gap: 9px; }
.footer__col a { font-size: 15px; color: var(--ink-2); }
.footer__col a:hover { color: var(--accent); }

.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding-top: 24px;
  font-size: 13.5px;
  color: var(--muted);
}
.footer__bottom nav { display: flex; flex-wrap: wrap; gap: 18px; }
.footer__bottom a:hover { color: var(--accent); }

/* 18. Utilities, motion, responsive, print --------------------------------- */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.skip {
  position: absolute;
  left: 16px;
  top: -60px;
  z-index: 100;
  padding: 10px 16px;
  border-radius: 0 0 var(--r-sm) var(--r-sm);
  background: var(--ink);
  color: var(--canvas);
  font-size: 14px;
  font-weight: 600;
  transition: top .15s ease;
}
.skip:focus { top: 0; }

.stack-sm { display: grid; gap: 10px; }
.mt-0 { margin-top: 0; }
.text-center { text-align: center; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
  a.card:hover, .btn:hover { transform: none; }
}

@media (max-width: 1080px) {
  .nav { display: none; }
  .nav-toggle { display: grid; }
  .nav.is-open {
    display: flex;
    position: absolute;
    left: 16px;
    right: 16px;
    top: calc(var(--header-h) + 6px);
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    padding: 12px;
    border: 1px solid var(--line);
    border-radius: var(--r);
    background: var(--surface);
    box-shadow: var(--shadow-2);
  }
  .nav.is-open .nav__link { padding: 12px 14px; border-radius: var(--r-sm); }
}

/* Below this width the rail goes away rather than squeezing the text: the in-body unit carries the
   article, and the reader keeps a readable measure. */
@media (max-width: 1240px) {
  .article__layout { grid-template-columns: 208px minmax(0, 1fr); gap: 48px; }
  .article__rail { display: none; }
}

@media (max-width: 1000px) {
  .hero { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  .newsletter__inner { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .footer__top { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .article__layout { grid-template-columns: minmax(0, 1fr); gap: 28px; }
  .toc { position: static; padding-bottom: 8px; border-bottom: 1px solid var(--line); }
  .toc ol { grid-auto-flow: column; grid-auto-columns: minmax(180px, 1fr); overflow-x: auto; padding-bottom: 6px; }
  .toc a { border-left: 0; border-top: 2px solid var(--line); }
  .toc a.is-active { border-top-color: var(--accent); }
  /* The rail moves below the feed and stops following the reader. */
  .with-rail { grid-template-columns: minmax(0, 1fr); gap: 28px; }
  .rail__sticky { position: static; }
  /* On a phone the rail's reading list is not shown at all: the feed above already carries the newest
     entries, and a "Most read" block under it only repeats them. The rail's ad units stay. */
  .rail__block { display: none; }
  /* Below the feed the rail's two squares used to stack, which put the last two units of the page one
     after the other with nothing between them. One is enough down here. The frames are what the partials
     render, so the selector has to name the frame — an `.ad-slot` can never be a child of the rail. */
  .rail__sticky > .ad-frame:last-child { display: none; }
  /* The sticky unit stops sticking under the header. */
  .ad-slot--sticky { position: static; }
}

@media (max-width: 780px) {
  body { font-size: 16.5px; }
  .wrap { padding-inline: 18px; }
  .grid--3 { grid-template-columns: minmax(0, 1fr); }
  .grid--4 { grid-template-columns: minmax(0, 1fr); }
  .grid--2 { grid-template-columns: minmax(0, 1fr); }
  .for-you__link { grid-template-columns: minmax(0, 1fr); gap: 14px; }
  .for-you__link .thumb { aspect-ratio: 16 / 9; }
  .ad-row { grid-template-columns: minmax(0, 1fr); }
  /* The billboard becomes a mobile strip, so it does not eat the screen the article is being read on. */
  .ad-slot--billboard { min-height: 100px; }
  .header-search { padding-left: 4px; }
  .header-search__input { display: none; }
  .section { padding-block: 42px; }
  .newsletter { padding-block: 46px; }
  .newsletter__row { grid-template-columns: minmax(0, 1fr); }
  .radar__item { grid-template-columns: minmax(0, 1fr); gap: 6px; }
  .section__head { flex-direction: column; align-items: flex-start; gap: 12px; }
  .card--row .thumb { width: 104px; }
  .toolpick, .inline-cta { grid-template-columns: minmax(0, 1fr); }
  .article__summary { font-size: 19px; }
  .prose { font-size: 18px; line-height: 1.72; gap: 24px; }
  .tldr li { font-size: 16.5px; }
  .tldr, .callout, .authorbox, .quote { padding: 20px; }
  .byline__actions { margin-inline-start: 0; width: 100%; }
  .byline { gap: 10px 14px; }
  .byline > .meta__sep { display: none; }
  .footer__top { grid-template-columns: minmax(0, 1fr); gap: 28px; }
  .lead-para::first-letter { font-size: 50px; }
}

@media (max-width: 620px) {
  .site-header__inner { gap: 12px; }
  .brand { font-size: 21px; }
  .header__actions { gap: 8px; }
  .icon-btn { width: 36px; height: 36px; }
  .inline-cta .btn { white-space: nowrap; }
}

@media print {
  .site-header, .ticker, .newsletter, .progress, .inline-cta, .toc, .footer__top { display: none !important; }
  body { background: #fff; font-size: 12pt; }
  .article__title { font-size: 24pt; }
}

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

/* The follow row in the legal line: the two configured accounts plus the feed and the address, which
   always exist. An icon without a target is never rendered — the template asks the configuration. */
.footer__social {
  display: flex;
  align-items: center;
  gap: 8px;
}

.footer__social-link {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 999px;
  border: 1px solid var(--line-2);
  color: var(--ink-2);
}

.footer__social-link:hover {
  border-color: var(--accent);
  color: var(--accent);
}
