/* Article page (S067) — component-level styling for `web/templates/post.html` and its
 * partials, per `web/static/css/app.css`'s own module doc ("component-level styling for
 * individual pages ... belongs to the steps that add those templates"). Reuses the shared
 * `.wrap-main` shell (D-33) and every token in `tokens.css`; introduces no new colour. */

/* The reading measure is `68ch`, and `ch` is the advance of `0` *in the element's own
 * font* — so the column only means 68 characters of reading text if this element carries
 * the reading face, exactly as the mockup declares it
 * (`design/design_handoff_agentblog/mockups/Article.dc.html:59`: one `<article>` with
 * `max-width:68ch;font-family:var(--display);font-size:19px`). Inheriting `body`'s 15px UI
 * sans here resolves the same token ~7% narrower and silently tracks `--size-ui`
 * (S067 review, round 3, minor). `font-family` is `--reading`, not a literal `--display`
 * (S071 review, major): `--reading` is `tokens.css`'s own alias for the reading face
 * `data-reading-face` selects (serif `--display` by default, `sans` when the owner picks
 * it), and this is the one reading-length prose block a per-user font choice must reach.
 * Every descendant that is *not* reading prose re-declares its own face below
 * (`.eyebrow`, `.byline`, `.article-footer`, `.chip`, …); `h1` pins `--display` explicitly
 * rather than inheriting `.article`'s font, so a heading never follows the reading-face
 * toggle. */
.article {
  max-width: var(--measure-reading);
  margin-inline: auto;
  font-family: var(--reading);
  font-size: var(--size-reading);
  /* The mockup puts `hanging-punctuation` on the `<article>` (`Article.dc.html:59`), so the
   * eyebrow, title, dek and byline inherit it too (S210 review round 1, nit). */
  hanging-punctuation: first last;
  /* The mockup's `<article>` carries `padding:56px 20px 80px` in one declaration
   * (`design/design_handoff_agentblog/mockups/Article.dc.html:59`); the shared shell's
   * `.wrap-main` (`app.css`) already contributes `--space-10` (40px) top / `--space-20`
   * (80px) bottom, so only the missing 16px of top padding — `--space-4` — is added here
   * rather than duplicating the shell's own values (S077d). The declaration's middle
   * value (the 20px inline gutter) is deliberately *not* transcribed: the centred
   * column's horizontal padding is the shell's `--space-6` (24px) on every page, which
   * loop invariant 8 ("a page template never re-invents the centred column") makes the
   * point of having a shell at all (S077d review round 2, nit; D-90's exception register). */
  padding-top: var(--space-4);
}

.article-header {
  margin-bottom: var(--space-10);
}

/* `.article-header .eyebrow`, not `.eyebrow`: `app.css`'s `.wrap-main p` is `(0,1,1)` and
 * would otherwise win the `margin` here (S067 review, round 3, minor). Same for `.dek`. */
.article-header .eyebrow {
  margin: 0 0 var(--space-4);
  font-family: var(--mono);
  font-size: var(--size-mono);
  /* `.06em`, not the shared `--tracking-eyebrow` (`.08em`): the mockup tracks this eyebrow
   * tighter than every other one on the site
   * (`design/design_handoff_agentblog/mockups/Article.dc.html:60` vs. the verdict card's
   * `:75` and the citations/tags `h2`'s `:94`/`:103`, both still `.08em`) — S077d. */
  letter-spacing: var(--tracking-eyebrow-article);
  text-transform: uppercase;
  color: var(--text-2);
}

.article h1 {
  margin: 0 0 var(--space-4);
  font-family: var(--display);
  font-size: var(--size-display);
  line-height: var(--leading-display);
  letter-spacing: var(--tracking-display);
  /* `design/design_handoff_agentblog/mockups/Article.dc.html:61` (S077d). */
  text-wrap: pretty;
}

.article-header .dek {
  margin: 0 0 var(--space-5);
  font-family: var(--display);
  font-style: italic;
  /* `design/design_handoff_agentblog/mockups/Article.dc.html:62` — the dek is the one
   * off-token size/leading pair in the handoff's article (loop invariant 7); `text-wrap`
   * is the same line's third declaration (S077d). */
  font-size: 21px;
  line-height: 1.45;
  text-wrap: pretty;
  color: var(--text-2);
}

.byline {
  margin: 0;
  font-family: var(--sans);
  font-size: var(--size-ui-dense);
  color: var(--text-2);
}

.byline time {
  font-family: var(--mono);
  font-size: var(--size-mono);
}

/* `Article.dc.html:64` styles the byline's author link `color:var(--text)`; unstyled it
 * inherits `app.css`'s global `a { color: var(--accent) }` instead. Same substitution
 * `.article-crosspost a`/`.post-nav a` below already make for their own sibling links
 * (S123 review round 1, minor). */
.byline a {
  color: var(--text);
}

/* Agent-attributed byline shapes only (S123, D-90): the mockup's flex-wrap clause layout
 * (`design/design_handoff_agentblog/mockups/Article.dc.html:63-64`, `gap:12px`) — kept off
 * the plain `.byline` rule above so the unchanged human-authored shape (S067) never gets a
 * 12px gap opened between "By" and the author link. `.byline--agent > span` needs no rule
 * of its own: each clause is already an inline `<span>`, and flex lays out inline children
 * as items without further markup. */
.byline--agent {
  display: flex;
  gap: var(--space-3);
  flex-wrap: wrap;
  align-items: center;
}

/* The byline's read count (S144, D-207): `Article.dc.html:65`'s `button`, a dotted-underline
 * mono label that opens `#readers`. */
.byline-reads {
  background: none;
  border: 0;
  padding: 0;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--text-2);
  text-decoration: underline dotted;
  text-underline-offset: 3px;
  cursor: pointer;
}

/* The reader-country popover, `Article.dc.html:68-91`. The UA's `[popover]` rule already
 * supplies the mockup's `position:fixed; inset:0; height:fit-content`; `max-height` keeps
 * Close on screen at 375px, where the list would otherwise push the popover past the top
 * of the viewport. */
.readers {
  margin: auto;
  width: min(640px, 92vw);
  max-height: calc(100vh - 32px);
  overflow: auto;
  padding: 24px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.5;
}

/* `Article.dc.html:24`. A dimmed `--text` layer, not `color-mix()`, which only `tokens.css`
 * may use (`tests/golden_render.rs`); `dash-tokens.css` dims the same way. */
.readers::backdrop {
  background: var(--text);
  opacity: .24;
}

.readers-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin: 0 0 16px;
}

.readers-title {
  margin: 0;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-2);
  font-weight: 400;
}

.readers-close {
  background: none;
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 2px 8px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--text-2);
  cursor: pointer;
}

/* The popover's three `p`s sit inside `.wrap-main`, whose `app.css` body-copy rule
 * `.wrap-main p` (0,1,1) would otherwise give them `--text-2`, a 68ch measure and its own
 * margin and line-height: scoped through `.article-header` (0,2,0) like `.eyebrow` above,
 * and `color`/`max-width` restated, so they render as `Article.dc.html:73-90` draws them. */
.article-header .readers-total {
  margin: 0 0 16px;
  max-width: none;
  font-family: var(--display);
  font-size: 28px;
  line-height: 1.2;
  color: var(--text);
}

.article-header .readers-total span {
  font-family: var(--sans);
  font-size: 14px;
  color: var(--text-2);
}

.readers-map {
  display: block;
  width: 100%;
  height: auto;
}

/* The five-step legend: the map's own opacities (`render::readers_map::render_png`,
 * `0.2 × level`) over `--accent`. */
.article-header .readers-scale {
  display: flex;
  align-items: center;
  gap: 4px;
  margin: 12px 0 16px;
  max-width: none;
  line-height: inherit;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-2);
}

.readers-scale i {
  width: 18px;
  height: 8px;
  border-radius: 1px;
  background: var(--accent);
}

.readers-scale i:nth-child(2) { opacity: .2; }
.readers-scale i:nth-child(3) { opacity: .4; }
.readers-scale i:nth-child(4) { opacity: .6; }
.readers-scale i:nth-child(5) { opacity: .8; }
.readers-scale i:nth-child(6) { opacity: 1; }

.readers-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  column-gap: 24px;
}

.readers-list li {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 6px 0;
  border-bottom: 1px solid var(--line);
  font-size: 14px;
}

.readers-list li span:last-child {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--text-2);
}

.article-header .readers-note {
  margin: 16px 0 0;
  max-width: none;
  line-height: inherit;
  font-size: 13px;
  color: var(--text-2);
}

.article-body {
  font-family: var(--reading);
  font-size: var(--size-reading);
  line-height: var(--leading-reading);
}

/* `color`/`line-height` are re-declared, not inherited from `.article-body`: `app.css`'s
 * `.wrap-main p` is also `(0,1,1)` and its system-page body copy (`--text-2`, 1.55) would
 * otherwise override the reading typography on every paragraph of every article
 * (S067 review, round 3, major). The mockup's article paragraphs carry nothing but
 * `margin:0 0 1.2em` and inherit primary text at 1.65. */
.article-body p {
  margin: 0 0 1.2em;
  color: var(--text);
  line-height: var(--leading-reading);
}

/* 26px/1.25/`-.01em` with a `1.8em 0 .6em` margin, not the shared `h1,h2,h3` ramp in
 * `app.css` (22px `--size-h2`, weight 400, 1.2, no tracking): the mockup's in-body section
 * heading sits off the `--size-h*` scale
 * (`design/design_handoff_agentblog/mockups/Article.dc.html:71`), the same commented
 * literal case as the dek's 21px above — S077d review round 2, minor. `font-family` is
 * left to `app.css`'s `h1,h2,h3`, which already pins `--display` so an in-body heading
 * never follows the reading-face toggle (the reason `.article h1` pins it too). */
.article-body h2 {
  margin: 1.8em 0 0.6em;
  font-weight: 500;
  font-size: 26px;
  line-height: 1.25;
  letter-spacing: -0.01em;
}

/* The article pull quote (`design/design_handoff_agentblog/mockups/Article.dc.html:87`).
 * Reachable on any post: `src/content/markdown.rs` allowlists `blockquote`, and a `>` block
 * that is not a `Claim:` verdict stays a plain blockquote, which without this rule renders
 * as the UA default (40px indent, no rule, roman, primary text) — S077d review round 2,
 * major. `pulldown-cmark` wraps the quote's text in `<p>`, and `.article-body p` above is
 * `(0,1,1)` with `color: var(--text)`, so the paragraph re-inherits the quote's own
 * `--text-2` explicitly; the last one drops its `1.2em` trailing margin so the quote box
 * ends on its text, as the mockup's single text node does. */
.article-body blockquote {
  margin: 1.6em 0;
  padding-left: var(--space-5);
  border-left: 1px solid var(--text);
  font-style: italic;
  color: var(--text-2);
}

.article-body blockquote p {
  color: inherit;
}

.article-body blockquote p:last-child {
  margin-bottom: 0;
}

/* Body images, code blocks and tables fit the reading column from 360px up
 * (`docs/design-brief.md:36`) — S265. The sanitizer (`src/content/markdown.rs`) lets
 * `img` through with no `width`/`height`, and `pre`/`table` with no `style`, so without
 * these a 2560px image, a long code line or a wide table widens the whole page. No mockup
 * draws body code, tables or figures, so every value is an existing token.
 *
 * Every rule here covers `.citation-body` as well: `content::citations` moves each
 * footnote definition's HTML out of the body into the Citations list
 * (`partials/citations.html`), outside `.article-body`, and a footnote can hold the same
 * three shapes (S265 review round 1, major). Block text there keeps the `pre`'s own
 * `--text`, as in the body, rather than the list's `--text-2`.
 *
 * Those block shapes are not the only overflow: a long unbroken word — an autolinked URL,
 * an inline `code` identifier — widens the page just the same, so running text breaks a
 * word that would otherwise overflow its line (S265 review round 1, minor). A `pre` keeps
 * `white-space: pre` and scrolls instead. It is `break-word`, never `anywhere`: this
 * container holds tables, the cells inherit the value, and `anywhere` also lowers every
 * cell's min-content width to about one character, so an auto-layout table would split
 * "Version" or "1.40.0" mid-word rather than scroll within itself (S265 review round 2,
 * major). `docs.css` can use `anywhere` because it sets it on `code` and `a`, not on a
 * container of tables. */
.article-body,
.citation-body {
  overflow-wrap: break-word;
}

/* The image stays inline in its paragraph (no `display: block`): it only shrinks to the
 * column, so an image narrower than the column keeps its natural size. */
.article-body img,
.citation-body img {
  max-width: 100%;
  height: auto;
}

/* A long line scrolls inside the block instead of widening the page. `font-style` is
 * reset because a fenced block inside a `>` quote would otherwise inherit the
 * blockquote's italic (S265 review round 1, nit). */
.article-body pre,
.citation-body pre {
  overflow-x: auto;
  max-width: 100%;
  margin: 1.4em 0;
  padding: var(--space-3) var(--space-4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  font-family: var(--mono);
  font-size: var(--size-mono);
  font-style: normal;
  line-height: 1.6;
  color: var(--text);
}

/* `app.css`'s global `code` rule would otherwise recolour block text to `--text-2`; inline
 * `code` outside a `pre` keeps that rule untouched. */
.article-body pre code,
.citation-body pre code {
  font: inherit;
  color: inherit;
}

/* `display: block` is what lets a table wider than the column scroll within itself; the
 * rows keep their table layout through the anonymous table box, and a table that fits is
 * unchanged in width. */
.article-body table,
.citation-body table {
  display: block;
  max-width: 100%;
  overflow-x: auto;
  border-collapse: collapse;
  margin: 1.4em 0;
  font-family: var(--sans);
  font-size: var(--size-ui-dense);
  line-height: 1.5;
}

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

.article-body th,
.citation-body th {
  font-weight: 500;
  background: var(--surface);
}

.article-body sup.footnote-reference a {
  font-family: var(--mono);
  /* 11px, not the shared `--size-mono` (12px): the mockup sets its citation superscripts
   * one size below the mono scale
   * (`design/design_handoff_agentblog/mockups/Article.dc.html:69-70, :72`) — S077d. */
  font-size: 11px;
  padding-left: 2px;
}

.article-footer {
  margin-top: var(--space-14);
  font-family: var(--sans);
  font-size: var(--size-ui);
}

.citations,
.tag-chips,
.post-nav {
  border-top: 1px solid var(--line);
  padding-top: var(--space-5);
}

.tag-chips,
.post-nav {
  /* 28px, not `--space-8` (32px): both sections follow the same top-rule pattern at
   * `design/design_handoff_agentblog/mockups/Article.dc.html:102` and `:111` — S077d
   * review round 1. */
  margin-top: 28px;
}

/* S120, D-195: not in the design handoff (same register `.dash-webhooks-*` already
 * carries for S119) — a rendered Dev.to syndication link, styled like the nav labels
 * below it (`.post-nav-label`) rather than left at browser-default paragraph size. */
.article-crosspost {
  margin-top: var(--space-5);
  font-family: var(--mono);
  font-size: var(--size-mono);
  color: var(--text-2);
}

.article-crosspost a {
  color: var(--text);
}

.citations h2,
.tag-chips h2 {
  font-family: var(--mono);
  font-size: var(--size-mono);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--text-2);
  font-weight: 400;
}

.citations h2 {
  /* 14px, not the shared `--space-4` (16px): the mockup's citations heading sits closer to
   * its list than the tags heading below it
   * (`design/design_handoff_agentblog/mockups/Article.dc.html:94` vs. `:103`) — S077d. */
  margin: 0 0 14px;
}

.tag-chips h2 {
  /* 12px == `--space-3`, unlike the citations heading above it
   * (`design/design_handoff_agentblog/mockups/Article.dc.html:103`) — S077d. */
  margin: 0 0 var(--space-3);
}

/* `> ol`, `> ol > li`, not descendant selectors: a footnote's own HTML (`.citation-body`)
 * can hold `ul`/`ol`/`li`, and a descendant selector would turn each of its items into this
 * 28px-track grid, squeezing its text and any code block into the number column and
 * dropping a nested `ol`'s numbers (S265 review round 3, major). */
.citations > ol {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  /* 10px, not the shared `--space-3` (12px) or `--space-2` (8px): off the 4px spacing
   * scale by design, transcribed from
   * `design/design_handoff_agentblog/mockups/Article.dc.html:95` (S077d). */
  gap: 10px;
  color: var(--text-2);
  line-height: 1.5;
}

/* `minmax(0, 1fr)`, not `1fr`: a `1fr` track's minimum is `auto`, so a wide image, code
 * block or table in a footnote would widen the track and the page with it (S265 review
 * round 1, major). */
.citations > ol > li {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr);
  gap: var(--space-2);
}

.citation-number {
  font-family: var(--mono);
  font-size: var(--size-mono);
  padding-top: 3px;
}

.citation-body p {
  display: inline;
  margin: 0;
}

.citation-backref {
  font-family: var(--mono);
  font-size: var(--size-mono);
}

.chip-row {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
  align-items: center;
}

.chip {
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  /* `3px 10px`, not `3px var(--space-3)` (3px 12px): the article footer's chip padding is
   * its own off-grid pair, distinct from the tag concept-card's `2px 8px`
   * (`tag.css`'s own `.chip`) — one shared rule cannot serve both
   * (`design/design_handoff_agentblog/mockups/Article.dc.html:105-107` vs. `:127-129`,
   * S077d). */
  padding: 3px 10px;
  font-family: var(--mono);
  font-size: var(--size-helper);
  color: var(--text);
}

.chip-broader {
  color: var(--text-2);
}

/* `(0,1,1)`, for the same `app.css` `.wrap-main p` reason as `.article-header .eyebrow`. */
.tag-chips .tag-legend {
  margin: var(--space-3) 0 0;
  font-size: var(--size-helper);
  color: var(--text-2);
}

.post-nav {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.post-nav a {
  color: var(--text);
}

.post-nav-newer {
  margin-inline-start: auto;
  text-align: right;
}

.post-nav-label {
  display: block;
  font-family: var(--mono);
  font-size: var(--size-mono);
  color: var(--text-2);
}
