/* ==========================================================================
   ARTICLE — the reading experience

   Loaded only on an article page, because nothing here is used anywhere
   else and long-form typography is not worth carrying on every request.

   Editorial first: the page *is* the article, not a card containing one.
   No outer rounded container, no shadowed panel around the text. What
   carries the design is the measure, the rhythm and the hierarchy.
   ========================================================================== */

/* Reading progress — the only chrome a long read earns. */
.read-progress {
  position: fixed; inset-inline: 0; top: 0; height: 3px;
  z-index: calc(var(--z-toast) - 1); pointer-events: none;
}
.read-progress span {
  display: block; height: 100%; width: 0;
  background: linear-gradient(90deg, var(--brand-500), var(--accent-500));
}

/* ── Masthead ────────────────────────────────────────────────────────── */
.article__head { padding-block: clamp(1.25rem, 3vw, 2rem) clamp(2.5rem, 6vw, 5rem); }
.article-opener {
  position: relative;
  overflow: hidden;
  border-bottom: 1px solid var(--line);
  background:
    radial-gradient(circle at 84% 24%, color-mix(in srgb, var(--accent-500) 14%, transparent), transparent 28rem),
    var(--grad-hero);
}
.article-opener > .bg-grid { position: absolute; inset: 0; opacity: .45; pointer-events: none; }
.article-opener > .container { position: relative; z-index: 1; }
.article__category {
  display: inline-flex;
  margin-top: clamp(1.5rem, 3vw, 2.5rem);
  padding: .4rem .7rem;
  border: 1px solid color-mix(in srgb, var(--accent-500) 38%, var(--line));
  border-radius: 999px;
  color: var(--accent-ink);
  background: color-mix(in srgb, var(--accent-500) 8%, var(--surface));
  font-size: .68rem;
  font-weight: 750;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.article__title {
  margin-top: .9rem;
  font-size: clamp(2.1rem, 5vw, 3.6rem);
  line-height: 1;
  letter-spacing: -0.045em;
  /* A headline is the one place balancing earns its cost: two lines with a
     single word stranded on the second reads as a mistake. */
  text-wrap: balance;
  max-width: 16ch;
}
.article__standfirst {
  margin-top: clamp(1rem, 2vw, 1.5rem);
  font-size: clamp(1.05rem, 1.6vw, 1.3rem);
  line-height: 1.55;
  color: var(--text-muted);
  max-width: 54ch;
  text-wrap: pretty;
}

/* Who wrote it, and the facts about the piece, on one rule. */
.byline {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 0.85rem clamp(1rem, 3vw, 2.25rem);
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
  padding-top: clamp(1.25rem, 2.5vw, 1.75rem);
  border-top: 1px solid color-mix(in srgb, var(--text) 16%, transparent);
}
.byline__face { flex-shrink: 0; }
.byline__who { display: grid; margin-inline-end: auto; }
.byline__name { font-weight: 600; color: var(--text); font-size: var(--fs-sm); }
.byline__role { font-size: var(--fs-xs); color: var(--text-dim); }
.byline__facts { display: flex; flex-wrap: wrap; gap: 0.5rem 1.75rem; margin: 0; }
.byline__facts div { display: grid; gap: 0.1rem; }
.byline__facts dt {
  font-size: 0.68rem; letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--text-dim); font-family: var(--font-mono);
}
.byline__facts dd {
  margin: 0; font-size: var(--fs-sm); color: var(--text); font-weight: 500;
  font-variant-numeric: tabular-nums;
}

/* ── Cover ───────────────────────────────────────────────────────────── */
.article__cover { max-width: 1040px; margin-block: clamp(1.25rem, 2.5vw, 2rem) clamp(2.25rem, 4vw, 3.5rem); }
.article__cover img {
  width: 100%; height: auto; display: block;
  aspect-ratio: 16 / 7.5; max-height: 500px; object-fit: cover;
  border: 1px solid var(--line); border-radius: 2px;
  box-shadow: none;
}
.article__cover figcaption {
  max-width: 68ch; margin: 0.85rem auto 0; padding-inline: 1.25rem;
  font-size: var(--fs-xs); color: var(--text-dim); line-height: 1.5;
}
.article__credit { color: var(--text-dim); opacity: 0.75; }
.article__credit::before { content: " \00b7 "; }

/* ── Body grid: contents beside the column where there is room ───────── */
.article__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(2rem, 4vw, 3.5rem);
  align-items: start;
  padding-bottom: clamp(3rem, 7vw, 6rem);
}
.article__body { max-width: 100%; }

@media (min-width: 1100px) {
  .article__grid { grid-template-columns: 232px minmax(0, 1fr); }
  /* The text column stays centred in the page rather than being shoved
     right by the sidebar. The reading is the thing. */
  .article__body { justify-self: center; width: 100%; }

  /* The contents rail is conditional — it only renders for an article with
     enough headings to need one. Without this rule the body became the
     grid's only child and was placed in the 232px rail, rendering the whole
     article as a vertical ribbon about twenty characters wide. Both forms
     are here deliberately: the class is set from the same flag the template
     branches on, and `:has()` covers markup that changes without it. */
  .article__grid--solo,
  .article__grid:not(:has(.contents)) { grid-template-columns: minmax(0, 1fr); }
}

/* ── Contents ────────────────────────────────────────────────────────── */
.contents__box {
  border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 0.95rem 1rem; background: var(--surface);
}
.contents__summary {
  display: flex; align-items: center; justify-content: space-between;
  gap: 0.75rem; cursor: pointer; list-style: none;
  font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase;
  font-family: var(--font-mono); color: var(--text-dim);
}
.contents__summary::-webkit-details-marker { display: none; }
.contents__chev { transition: transform var(--dur-fast) var(--ease-out); }
.contents__box[open] .contents__chev { transform: rotate(180deg); }

.contents__list { margin: 0.85rem 0 0; padding: 0; list-style: none; }
.contents__item a {
  display: flex; gap: 0.6rem; align-items: baseline;
  padding: 0.4rem 0 0.4rem 0.7rem; margin-inline-start: -0.7rem;
  font-size: var(--fs-sm); line-height: 1.4; color: var(--text-muted);
  border-inline-start: 2px solid transparent;
  transition: color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.contents__item a:hover { color: var(--text); }
.contents__item--h3 a { padding-inline-start: 1.85rem; font-size: var(--fs-xs); }
.contents__num {
  font-family: var(--font-mono); font-size: 0.7rem; color: var(--text-dim);
  font-variant-numeric: tabular-nums; flex-shrink: 0;
}
.contents__text { overflow-wrap: break-word; min-width: 0; }

/* The section being read. Set by scroll-spy — the reason this is a
   navigation aid rather than a static index. */
.contents__item a.is-current {
  color: var(--text); font-weight: 550;
  border-inline-start-color: var(--accent-500);
}
.contents__item a.is-current .contents__num { color: var(--accent-ink); }

@media (min-width: 1100px) {
  .contents { position: sticky; top: calc(var(--nav-h) + 1.75rem); }
  .contents__box { padding: 1rem; box-shadow: var(--shadow-sm); }
  /* Always open where there is room: a disclosure widget with space to be
     a list is only a click in the way. */
  .contents__summary { pointer-events: none; }
  .contents__chev { display: none; }
  .contents__list { max-height: calc(100vh - var(--nav-h) - 8rem); overflow-y: auto; }
}

/* ── Prose, tuned for long-form ──────────────────────────────────────── */
.prose--article {
  /* ~68ch lands near 660px here — inside the 600-760px band where the eye
     reliably finds the start of the next line. */
  max-width: 68ch;
  margin-inline: auto;
  font-size: clamp(1.02rem, 1.15vw, 1.12rem);
  line-height: 1.75;
  color: var(--text-muted);
}
.prose--article > * + * { margin-top: 1.4em; }
.prose--article h2 {
  margin-top: 2.4em; margin-bottom: -0.35em;
  font-size: clamp(1.4rem, 2.4vw, 1.9rem); line-height: 1.2;
  letter-spacing: -0.015em; color: var(--text); text-wrap: balance;
  /* Jumping to a section must not park its heading under the sticky nav. */
  scroll-margin-top: calc(var(--nav-h) + 1.5rem);
  padding-top: .3em;
}
.prose--article h3 {
  margin-top: 1.9em; margin-bottom: -0.5em;
  font-size: clamp(1.15rem, 1.7vw, 1.35rem); line-height: 1.3;
  color: var(--text); scroll-margin-top: calc(var(--nav-h) + 1.5rem);
}
/* They carry tabindex="-1" so the fragment moves focus for a screen reader;
   that must not paint a focus ring on a mouse click. */
.prose--article h2:focus, .prose--article h3:focus { outline: none; }
.prose--article p { text-wrap: pretty; }
.prose--article li { margin-top: 0.45em; }
.prose--article strong { color: var(--text); font-weight: 600; }

/* Pull quote: display face, no italic, a rule rather than quote marks. It
   should read as a break in the argument, not an indented paragraph. */
.prose--article blockquote {
  margin-block: 2em; padding: 0 0 0 1.4em;
  border-inline-start: 2px solid var(--accent-500);
  font-family: var(--font-display);
  font-size: clamp(1.2rem, 2vw, 1.5rem);
  line-height: 1.4; color: var(--text); font-style: normal;
  letter-spacing: -0.01em;
}
.prose--article blockquote p { margin: 0; }

.prose--article figure { margin-block: 2em; border-radius: 0; overflow: visible; }
.prose--article figure img { border-radius: var(--r-md); width: 100%; height: auto; }
.prose--article figcaption {
  margin-top: 0.7em; font-size: var(--fs-xs); color: var(--text-dim);
  line-height: 1.5; text-align: start;
}
.prose--article img { width: 100%; height: auto; border-radius: var(--r-md); }
.prose--article hr { margin-block: 2.5em; border: 0; height: 1px; background: var(--line); }

/* A wide table scrolls inside its own box. The page never scrolls sideways. */
.prose__scroll {
  overflow-x: auto; margin-block: 1.8em;
  border: 1px solid var(--line); border-radius: var(--r-md);
}
.prose__scroll table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.prose__scroll th, .prose__scroll td {
  padding: 0.7rem 0.9rem; border-bottom: 1px solid var(--line); text-align: start;
}
.prose__scroll th {
  background: var(--surface); color: var(--text);
  font-weight: 600; white-space: nowrap;
}
.prose__scroll tr:last-child td { border-bottom: 0; }

/* ── Code blocks ─────────────────────────────────────────────────────── */
/* Dark in both themes. A code block is a quotation from a terminal, and
   flipping it to white on the light theme makes it read as prose. */
.code {
  --code-bg: #0b1424;
  --code-bar: #111d33;
  --code-line: rgba(255, 255, 255, 0.09);
  --code-fg: #dfe7f5;
  --code-dim: #7f90ad;

  margin-block: 2em; border-radius: var(--r-md); overflow: hidden;
  border: 1px solid var(--code-line); background: var(--code-bg);
}
.code__bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; padding: 0.5rem 0.85rem;
  background: var(--code-bar); border-bottom: 1px solid var(--code-line);
}
.code__lang {
  font-family: var(--font-mono); font-size: 0.66rem;
  letter-spacing: 0.12em; color: var(--code-dim);
}
.code__copy {
  font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.06em;
  color: var(--code-dim); padding: 0.25rem 0.55rem; border-radius: 6px;
  border: 1px solid transparent; background: none; cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.code__copy:hover { color: var(--code-fg); border-color: var(--code-line); }
.code__copy.is-done { color: #6ee7a8; border-color: #6ee7a8; }
.code__scroll { overflow-x: auto; }
.code__pre {
  margin: 0; padding: 1.1rem 1.15rem; background: none; border: 0;
  font-family: var(--font-mono); font-size: 0.855rem; line-height: 1.65;
  color: var(--code-fg); tab-size: 2;
}
.code__pre code { background: none; padding: 0; color: inherit; font-size: inherit; }

/* Pygments tokens. Hand-set rather than generated: a stock theme brings
   forty rules and a palette that fights the brand. Six hues, all measured
   against #0b1424 at 4.5:1 or better. */
.code__pre .k, .code__pre .kd, .code__pre .kn,
.code__pre .kr, .code__pre .kc, .code__pre .kp { color: #f0a8d8; }
.code__pre .kt { color: #7fd6c0; }
.code__pre .s, .code__pre .s1, .code__pre .s2, .code__pre .sb,
.code__pre .sc, .code__pre .sd, .code__pre .se, .code__pre .sh,
.code__pre .si, .code__pre .sx, .code__pre .sr, .code__pre .ss { color: #9fd77f; }
.code__pre .c, .code__pre .c1, .code__pre .cm, .code__pre .cs,
.code__pre .cp, .code__pre .cpf { color: #6b7d99; font-style: italic; }
.code__pre .m, .code__pre .mi, .code__pre .mf, .code__pre .mh,
.code__pre .mo, .code__pre .il { color: #f2b233; }
.code__pre .nf, .code__pre .fm { color: #7cc4f5; }
.code__pre .nc, .code__pre .nn { color: #7fd6c0; }
.code__pre .nb, .code__pre .bp { color: #7cc4f5; }
.code__pre .nd { color: #f2b233; }
.code__pre .o, .code__pre .ow, .code__pre .p { color: #a8b6cc; }
.code__pre .nt { color: #f0a8d8; }
.code__pre .na { color: #f2b233; }
.code__pre .err { color: #ff8fa0; }

/* ── Tags, footer, author ────────────────────────────────────────────── */
.article__tags {
  display: flex; flex-wrap: wrap; gap: 0.5rem;
  max-width: 68ch; margin: 2.5rem auto 0;
}
.article__foot {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 1rem;
  max-width: 68ch; margin: 2rem auto 0;
  padding-top: 1.5rem; border-top: 1px solid var(--line);
}

.share { position: relative; }
.share__menu {
  position: absolute; inset-inline-end: 0; bottom: calc(100% + 0.5rem);
  min-width: 190px; padding: 0.35rem;
  background: var(--bg-elevated); border: 1px solid var(--line);
  border-radius: var(--r-md); box-shadow: var(--shadow-lg); z-index: 20;
}
.share__item {
  display: flex; align-items: center; gap: 0.65rem; width: 100%;
  padding: 0.55rem 0.7rem; border-radius: var(--r-sm);
  font-size: var(--fs-sm); color: var(--text-muted); text-align: start;
  transition: background var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}
.share__item:hover { background: var(--surface); color: var(--text); }
.share__item svg { width: 16px; height: 16px; flex-shrink: 0; }

.author-card {
  display: flex; gap: clamp(1rem, 2.5vw, 1.5rem); align-items: flex-start;
  max-width: 68ch; margin: 3rem auto 0;
  padding: clamp(1.25rem, 3vw, 1.75rem);
  border: 1px solid color-mix(in srgb, var(--accent-500) 24%, var(--line)); border-radius: 2px;
  background: color-mix(in srgb, var(--accent-500) 5%, var(--surface));
}
.author-card__face { flex-shrink: 0; }
.author-card__text { min-width: 0; }
.author-card__eyebrow {
  font-family: var(--font-mono); font-size: 0.66rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--text-dim);
}
.author-card__name {
  margin: 0.35rem 0 0; font-size: var(--fs-lg);
  font-weight: 600; color: var(--text);
}
.author-card__role { margin: 0.1rem 0 0; font-size: var(--fs-sm); color: var(--accent-ink); }
.author-card__bio {
  margin: 0.65rem 0 0; font-size: var(--fs-sm);
  line-height: 1.6; color: var(--text-muted);
}

/* ── Comment threads ─────────────────────────────────────────────────── */
/* Indentation stops at the third level. Deeper replies keep their place in
   the conversation without squeezing the text into a two-word column. */
.comment__replies {
  margin-top: 1rem;
  padding-inline-start: clamp(0.85rem, 3vw, 1.75rem);
  border-inline-start: 1px solid var(--line);
}
.comment--d3 .comment__replies {
  padding-inline-start: 0; border-inline-start: 0; margin-top: 0.85rem;
}

.article-comments { padding-block: clamp(3.5rem, 7vw, 6rem); border-top: 1px solid var(--line); }
.article-comments > .container { max-width: 860px; }
.article-comments > .container > h2 { font-size: clamp(1.65rem, 3vw, 2.2rem); letter-spacing: -.03em; }
.comment-compose { margin-block: 1.5rem 2.5rem; padding: clamp(1.3rem, 3vw, 2rem); border-color: var(--line); border-radius: 2px; background: var(--bg); box-shadow: none; }
.comment-compose form { display: grid; gap: 1rem; }
.article-comments .comment { gap: 1rem; padding-bottom: 1.35rem; }
.article-comments .comment__body { padding: 1.05rem 1.15rem 1rem; border-radius: 2px; }
.article-comments .comment__head { margin-bottom: .55rem; }
.article-comments .comment__actions { margin-top: .85rem; gap: .4rem 1.1rem; }
.article-comments .comment__replies { margin-top: 1.25rem; }
.article-comments .alert { border-radius: 2px; }
.article-related { border-top: 1px solid var(--line); }

@media (max-width: 720px) {
  .article__head { padding-bottom: 2.5rem; }
  .article__title { font-size: clamp(2rem, 8.5vw, 2.35rem); }
  .article__standfirst { font-size: 1rem; }
  .byline { display: grid; grid-template-columns: auto 1fr; }
  .byline__facts { grid-column: 1 / -1; display: grid; grid-template-columns: repeat(2, 1fr); width: 100%; padding-top: .8rem; border-top: 1px solid var(--line); }
  .article__cover { padding-inline: 1rem; }
  .article__cover img { aspect-ratio: 16 / 7.5; border-radius: 2px; }
  .article__cover figcaption { padding-inline: .2rem; }
  .article__grid { padding-inline: 1rem; }
  .contents__box { border-radius: var(--r-lg); }
  .author-card { align-items: center; }
  .comment-compose { padding: 1.1rem; }
  .article-comments .comment { gap: .7rem; }
  .article-comments .comment__body { padding: .9rem; }
}

@media (prefers-reduced-motion: reduce) {
  .contents__chev { transition: none; }
}
