/* generic — blog styles.
 *
 * Loaded AFTER page.css, which it extends rather than replaces: cards are
 * `.trio__cell`, frames are `.media`, buttons are `.btn`, labels are `.label`.
 * Only what the blog genuinely adds lives here — the byline row, the article
 * measure, and markdown body typography.
 *
 * ZERO colour literals. Every colour arrives through a var() named by
 * tokens.css, and every de-emphasis is --opacity-* on the section's own
 * bright, never a new hue. Corners are cut (var(--clip-chamfer)), never
 * rounded.
 *
 * "named by tokens.css", not "from": the pages actually link tokens.mono.css,
 * which is a documented drop-in with the same token names. Nothing here binds
 * to either file -- swap the <link> and this stylesheet follows.
 */

/* --- Clearing the fixed nav ------------------------------------------------
   .nav is `position: fixed` in page.css, so whatever opens <main> starts
   UNDERNEATH it. The landing page pays for that in .hero, which uses
   --space-4xl of top padding where a plain .section uses --space-3xl; the blog
   has no hero, so its first section opened behind the bar and the eyebrow row
   ("01 — Journal") was half-hidden. Charged to the FIRST SECTION, whatever it
   is, rather than to .blog-index and .post by name, so a page added later
   inherits the fix instead of rediscovering the bug. */
main > .section:first-child { padding-top: var(--space-4xl); }

/* --- Index ---------------------------------------------------------------- */

.blog-index .section__title { margin-bottom: var(--space-xl); }

/* The filter is the existing button vocabulary; only the row is new. */
.cat-filter {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs);
  margin-bottom: var(--space-xl);
}

.post-card { justify-content: flex-start; }

.post-card__link {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  text-decoration: none;
  color: inherit;
}

/* The only thing that moves on hover: the caption de-emphasises to the
   secondary step, which is the same mechanism .muted uses. */
.post-card__link:hover .card__text h3 { opacity: var(--opacity-secondary); }
.post-card__link .card__text h3 { transition: opacity var(--dur-short) var(--ease-out); }

.post-card__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs);
  margin: 0;
}

.post-card__meta a { text-decoration: none; }
.post-card__meta a:hover { opacity: var(--opacity-secondary); }

/* --- Byline --------------------------------------------------------------- */

.byline {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  list-style: none;
  margin: 0;
  padding: 0;
}

.byline__author {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
}

.byline__avatar {
  width: var(--space-lg);
  height: var(--space-lg);
  object-fit: cover;
  clip-path: var(--clip-chamfer);
  border-radius: var(--radius-card);
}

.post__byline .byline__avatar {
  width: var(--space-xl);
  height: var(--space-xl);
}

/* --- Post ----------------------------------------------------------------- */

.post__title { margin-bottom: var(--space-sm); }

.post__subtitle {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  line-height: 1.05;              /* rig's leading at this rung */
  letter-spacing: var(--tracking-heading);
  max-width: 46ch;
  margin: 0 0 var(--space-lg);
}

.post__byline { margin-bottom: var(--space-xl); }

.post__hero { margin-bottom: var(--space-2xl); }

/* The measure caps well below --content-max: 1280px of running prose is
   unreadable, and design.md's rule is that the measure stops widening. */
.post__body {
  max-width: 68ch;
  font-size: var(--text-md);
  line-height: var(--leading-body);
}

.post__body > * + * { margin-top: var(--space-md); }

.post__body h2,
.post__body h3 {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  letter-spacing: var(--tracking-heading);
  margin-top: var(--space-2xl);
}

/* Sub-heading rung: the display face at 2rem / 700, leading 0.95. There is
   no middle register below it — h3 sits at the same rung, smaller. */
.post__body h2 {
  font-size: var(--text-xl);
  line-height: 0.95;
}

.post__body h3 {
  font-size: var(--text-lg);
  line-height: 1.05;
}

.post__body ul,
.post__body ol {
  padding-left: var(--space-md);
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}

.post__body li::marker { opacity: var(--opacity-tertiary); }

.post__body a {
  text-decoration: underline;
  text-underline-offset: 0.2em;
  text-decoration-thickness: var(--rule-hair);
}

.post__body a:hover { opacity: var(--opacity-secondary); }

.post__body strong { font-weight: var(--weight-display); }

/* Blockquote: a hairline spine in the section's own bright, display face.
   No tint, no panel — the rule carries it. */
.post__body blockquote {
  border-left: var(--rule-fine) solid var(--color-rule);
  padding-left: var(--space-md);
  margin-left: 0;
  margin-right: 0;
  font-family: var(--font-display);
  font-size: var(--text-lg);
  line-height: 1.05;
  letter-spacing: var(--tracking-heading);
}

.post__body blockquote p { margin: 0; }

/* Code is a content panel, so it is chamfered and floats inside a hairline
   frame. --ground-black is an existing token (the neutral ground); this
   mints nothing. */
.post__body code {
  font-family: var(--font-outlier);
  font-size: 0.85em;
}

.post__body :not(pre) > code {
  padding: 0.1em 0.35em;
  background: var(--color-rule);
  color: var(--color-paper);
}

.post__body pre {
  background: var(--ground-black);
  color: var(--color-ink);
  border: var(--rule-hair) solid var(--color-rule);
  padding: var(--space-md);
  clip-path: var(--clip-chamfer);
  overflow-x: auto;
  font-size: var(--text-sm);
  line-height: var(--leading-body);
}

.post__body pre code {
  background: none;
  color: inherit;
  padding: 0;
  font-size: inherit;
}

/* A bare markdown image gets the panel treatment without needing the
   .media wrapper markup: chamfer, hairline frame, seen whole. */
.post__body img {
  display: block;
  max-width: 100%;
  height: auto;
  clip-path: var(--clip-chamfer);
  border: var(--rule-hair) solid var(--color-rule);
}

.post__body hr {
  border: 0;
  border-top: var(--rule-hair) solid var(--color-rule);
  opacity: var(--opacity-tertiary);
  margin-block: var(--space-2xl);
}

.post__body table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}

.post__body th,
.post__body td {
  border: var(--rule-hair) solid var(--color-rule);
  padding: var(--space-2xs) var(--space-xs);
  text-align: left;
}

.post__body th {
  font-family: var(--font-outlier);
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  font-weight: 400;
}

/* --- Video ---------------------------------------------------------------- */

/* A video the reader is meant to watch is seen whole; the 130% crop is for
   stills that should read as a detail of something larger. design.md names
   this exact escape hatch. */
.video {
  --media-overscan: 100%;
  margin: 0;
}

.video[data-ratio='16:9'] .media__slot { aspect-ratio: 16 / 9; }

.video .media__slot > iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

.video figcaption { margin-top: var(--space-2xs); }

/* --- Footer blocks -------------------------------------------------------- */

.post__foot .trio,
.post__share .share {
  margin-top: var(--space-lg);
}

.share {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs);
}

.newsletter__note {
  max-width: 46ch;
  margin: var(--space-sm) 0 var(--space-lg);
}

.newsletter {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  max-width: 34rem;
}

.newsletter__row {
  display: flex;
  gap: var(--space-2xs);
}

.newsletter__input {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--font-outlier);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-label);
  padding: var(--space-2xs) var(--space-xs);
  color: var(--color-ink);
  background: var(--color-paper);
  border: var(--rule-hair) solid var(--color-rule);
  border-radius: var(--radius-input);
}

.newsletter__input::placeholder {
  color: inherit;
  opacity: var(--opacity-tertiary);
}

@media (max-width: 599px) {
  .newsletter__row { flex-direction: column; }
  .newsletter__row .btn { text-align: center; }
}

/* --- Nav brand lockup ----------------------------------------------------
   Mark plus wordmark on one baseline. Layout only, no colour: the mark is
   `fill: currentColor` and inherits whatever --color-ink the nav already
   resolves, exactly as the bare text did before it.                        */
.nav__brand { display: inline-flex; align-items: center; gap: 0.5em; }
.nav__mark  { width: 1.15em; height: 1.15em; flex: none; display: block; }
