/* ============================================================================
   07-prose.css — the long-form article body (block: prose · roles D1, H5)

   The last unbuilt block. Supporting pages are mostly text, so this carries
   more of the reading experience than any other block in the system.

   Spacing is done with an owl selector (`> * + *`) rather than margins on each
   element. That is what lets the generator drop ANY existing block into the
   article flow — callout, card-row, image-break, dtable, inlinecta — and have
   it spaced correctly without the block knowing it is inside an article. Adding
   a new block later needs no change here.

   Loaded only by article-type pages. The homepage never pays for it.
   ============================================================================ */

.prose {
  /* Own the measure locally so a block that opts out (a full-width figure,
     a table) can do so by overriding one property, not by fighting margins. */
  --prose-measure: var(--measure);
  font-size: var(--type-body);
  line-height: var(--leading-body);
  letter-spacing: var(--track-body);
  color: var(--label);
}

/* ---- rhythm ------------------------------------------------------------- */
.prose > * + * { margin-block-start: var(--space-m); }

/* Headings bind to the text BELOW them, so the space above is larger than the
   space below. Without this a heading floats between two paragraphs and the
   reader cannot tell which one it introduces. */
.prose > :is(h2, h3, h4) { margin-block-start: var(--space-xl); }
/* Tight only before running text. A block that follows a heading (table, FAQ,
   callout, carousel) needs real air or the heading collides with its frame. */
.prose > :is(h2, h3, h4) + :is(p, ul, ol) { margin-block-start: var(--space-xs); }
.prose > :is(h2, h3, h4) + :not(p, ul, ol) { margin-block-start: var(--space-m); }
.prose > :first-child { margin-block-start: 0; }

/* Anchor links from the anchornav must not land under the frosted navbar. */
.prose > :is(h2, h3, h4)[id] { scroll-margin-block-start: var(--space-3xl); }

.prose > :is(h2, h3, h4) {
  color: var(--label);
  text-wrap: balance;              /* stops a lone orphan word on line 2 */
  max-inline-size: var(--prose-measure);
}
.prose > h2 { font-size: var(--type-title-2); }
.prose > h3 { font-size: var(--type-title-3); }
.prose > h4 { font-size: var(--type-headline); }

.prose > p, .prose li { max-inline-size: var(--prose-measure); }

/* Opening paragraph carries the summary weight the hero deliberately does not.
   Matched on position rather than a class so the generator never has to mark
   it — one less field in the content contract that can be forgotten. */
.prose > p:first-child {
  font-size: var(--type-callout);
  line-height: var(--leading-snug);
  color: var(--label-secondary);
}

/* ---- contextual links (H5) ----------------------------------------------
   These are the internal-link surface the whole supporting-page structure
   depends on, so they are underlined, not colour-only: colour alone fails
   WCAG 1.4.1 and, more practically, is invisible when skim-reading. */
.prose a:not([class]) {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, var(--accent) 40%, transparent);
  text-underline-offset: 3px;
  transition: text-decoration-color var(--dur-fast) var(--ease);
}
.prose a:not([class]):hover { text-decoration-color: var(--accent); }

/* ---- lists ---------------------------------------------------------------
   Markers sit in the gutter so the text edge stays flush with paragraphs
   above and below — a ragged left edge is the classic giveaway of default
   browser list styling. */
.prose :is(ul, ol) {
  padding-inline-start: 0;
  list-style-position: outside;
  margin-inline-start: 1.15em;
}
.prose li + li { margin-block-start: var(--space-2xs); }
.prose li::marker { color: var(--label-tertiary); }
.prose ol > li::marker { font-variant-numeric: tabular-nums; font-weight: var(--weight-medium); }
.prose :is(ul, ol) :is(ul, ol) { margin-block-start: var(--space-2xs); }

/* ---- pull quote ----------------------------------------------------------
   A rule, not a card: a bordered box here reads as a UI component and breaks
   the reading flow, which is the opposite of what a pull quote is for. */
/* No left bar here either — same banned pattern. A short rule above the quote
   marks it instead, matching the verdict block's language. */
.prose blockquote {
  margin-inline: 0;
  padding-block-start: var(--space-s);
  font-size: var(--type-title-3);
  line-height: var(--leading-snug);
  font-weight: var(--weight-medium);
  color: var(--label);
  max-inline-size: var(--prose-measure);
  position: relative;
}
.prose blockquote::before {
  content: "";
  position: absolute; inset-block-start: 0; inset-inline-start: 0;
  inline-size: 2.5rem; block-size: 3px;
  border-radius: 2px;
  background: var(--accent);
}
.prose blockquote p { font-size: inherit; line-height: inherit; max-inline-size: none; }
.prose blockquote cite {
  display: block;
  margin-block-start: var(--space-xs);
  font-size: var(--type-footnote);
  font-style: normal;
  font-weight: var(--weight-regular);
  color: var(--label-secondary);
}

/* ---- figures -------------------------------------------------------------
   Images break the measure on purpose: text wants 68ch, pictures want room.
   Square or portrait only — never a wide 16:9 letterbox on a phone. */
.prose figure { margin: 0; }
/* Images are cropped to a ratio, never dropped in at natural size: t7.jpg is
   portrait and rendered ~1.4 screens tall, which reads as a wall, not a figure.
   Ratio is a variable so the generator can go portrait for a tall subject. */
.prose figure img {
  inline-size: 100%;
  aspect-ratio: var(--figure-ratio, 4 / 3);
  object-fit: cover;
  object-position: center;
  max-block-size: 62svh;
  border-radius: var(--radius-m);
  display: block;
}
.prose figcaption {
  margin-block-start: var(--space-xs);
  font-size: var(--type-footnote);
  line-height: var(--leading-snug);
  color: var(--label-secondary);
  max-inline-size: var(--prose-measure);
}

/* ---- rule ---------------------------------------------------------------- */
.prose hr {
  border: 0;
  block-size: 1px;
  background: var(--separator);
  margin-block: var(--space-xl);
}

/* ---- tables in flowing text ---------------------------------------------
   A table cannot reflow, so it is the single most likely thing to force a
   horizontal page scroll on a 320px screen. It scrolls inside its own box
   instead; the page never does. */
.prose .table-wrap { max-inline-size: none; }

/* ---- de-emphasis --------------------------------------------------------- */
.prose small,
.prose .prose__note {
  display: block;
  font-size: var(--type-footnote);
  color: var(--label-secondary);
  max-inline-size: var(--prose-measure);
}

/* Blocks dropped into the article flow are full-width by design — the owl
   selector above already spaces them, so they need nothing else. */
.prose > :is(figure, .callout, .imgbreak, .dtable, .table-wrap, .inlinecta,
              .card-row, .steps, .faq, .carousel, .photogrid, .pair, .ctaband) {
  max-inline-size: none;
}
