/* ---------------------------------------------------------------------------
   Width override.

   The handoff sets --st-page: 1120px with a 24px gutter, giving 1072px of
   content, which reads too wide. Narrowed here rather than in tokens.css so
   that file stays a verbatim copy of the export. --st-measure moves with it
   so the article column keeps roughly the same proportion of the page
   (86%) and the reading line does not end up nearly full width.
   --------------------------------------------------------------------------- */
:root {
  --st-page: 1040px;    /* content width 1040 - 48 = 992px (was 1072px) */
  --st-measure: 900px;  /* was 960px */
}

/* ---------------------------------------------------------------------------
   Additions to the Claude Design handoff.

   The handoff covers the article page, home page, related row and footer.
   These are the pieces it does not: listing pages, pagination, empty states
   and the 404. Everything reuses the handoff's own components and tokens —
   listing headers are literally .home-header, and listing grids are
   .post-grid — so there is very little here by design.

   Keep blog.css / home.css / tokens.css untouched so a re-export is a copy.
   --------------------------------------------------------------------------- */

.skip-link {
  position: absolute;
  left: 24px;
  top: -4rem;
  z-index: 100;
  padding: 8px 16px;
  background: var(--st-white);
  color: var(--st-text);
  border: 1px solid var(--st-border-strong);
  border-radius: var(--st-r-sm);
  font-size: 14px;
  transition: top 120ms ease;
}
.skip-link:focus { top: 16px; }

:focus-visible { outline: 2px solid var(--st-blue); outline-offset: 3px; }

/* --- Listing pages -------------------------------------------------------- */
/* The listing grid is the handoff's own post grid, with the section spacing
   the .latest block would otherwise provide. */
.listing { padding-top: 48px; }

/* --- Topic index ---------------------------------------------------------- */
.topic-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 20px;
}
.topic-card {
  display: block;
  padding: 24px;
  background: var(--st-white);
  border: 1px solid var(--st-border);
  border-radius: var(--st-r-sm);
  color: var(--st-text);
  transition: border-color 150ms ease;
}
.topic-card:hover { border-color: var(--st-blue); }
.topic-card__title { margin-top: 10px; font-size: 18px; font-weight: 500; letter-spacing: -.01em; }
.topic-card__text { margin: 8px 0 0; font-size: 15px; line-height: 1.55; color: var(--st-text-2); }

/* --- Pagination ----------------------------------------------------------- */
.pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: 48px;
  padding-top: 24px;
  border-top: 1px solid var(--st-border);
  font-family: var(--st-mono);
  font-size: 12px;
  color: var(--st-text-3);
}
.pagination__link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border: 1px solid var(--st-border-strong);
  border-radius: var(--st-r-sm);
  background: var(--st-white);
  color: var(--st-text);
  font-weight: 500;
  transition: border-color 150ms ease;
}
.pagination__link:hover { border-color: var(--st-blue); }

/* --- Empty state and 404 -------------------------------------------------- */
.empty-state {
  padding: 64px 24px;
  text-align: center;
  color: var(--st-text-2);
  border: 1px dashed var(--st-border-strong);
  border-radius: var(--st-r-sm);
  background: var(--st-white);
}
.notice { padding-top: 96px; }
.notice .home-dek { max-width: 48ch; }

/* --- Author header -------------------------------------------------------- */
.author-header { display: flex; align-items: center; gap: 20px; }
.author-links { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 20px; }

/* --- Real images in schematic frames -------------------------------------- */
/* .cover, .post-card__media and .featured__media are built around the CSS
   schematic, so nothing in blog.css sizes a photograph. Fill and crop. */
.cover--image > img,
.post-card__media > img,
.featured__media > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* --- Photographic cover overlay ------------------------------------------- */
/* Every other cover on the site is a drawn schematic on a grid. A bare
   photograph between two of them reads as a foreign object, so it gets the
   same treatment: grid, scanlines and the mono corner labels. All of it is
   markup and CSS rather than a baked-in image, so the labels stay selectable
   and the texture stays crisp at any width.
   Sized in cqw like the schematics, so the overlay tracks the frame. */
.cover--image { background: var(--st-navy); }

.cover__scrim,
.cover__mesh,
.cover__marks {
  position: absolute;
  pointer-events: none;
}

/* Darkens the two edges the labels sit on and leaves the middle — where the
   faces are — close to untouched. */
.cover__scrim {
  inset: 0;
  background: linear-gradient(
    to bottom,
    rgba(12, 27, 69, 0.66) 0%,
    rgba(12, 27, 69, 0.14) 24%,
    rgba(12, 27, 69, 0) 46%,
    rgba(12, 27, 69, 0.26) 76%,
    rgba(12, 27, 69, 0.7) 100%
  );
}

/* Grid on the same 5cqw pitch as .cover, plus fine scanlines. */
.cover__mesh {
  inset: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.08) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.08) 1px, transparent 1px),
    repeating-linear-gradient(
      to bottom,
      rgba(12, 27, 69, 0.14) 0 1px,
      rgba(12, 27, 69, 0) 1px 3px
    );
  background-size: 5cqw 5cqw, 5cqw 5cqw, 100% 100%;
  background-position: -0.5px -0.5px, -0.5px -0.5px, 0 0;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.14);
}

/* The corner labels are dark text for the light schematic covers; over a
   photograph they need the opposite, and a shadow so they survive a bright
   patch of sky. */
.cover--image .cover__corner {
  color: rgba(255, 255, 255, 0.88);
  text-shadow: 0 1px 3px rgba(12, 27, 69, 0.75);
}

/* Crop marks at the four corners — eight hairlines in one element, each
   corner an L. Positioned from its own corner so they hold at any width. */
.cover__marks {
  inset: 0;
  --arm: linear-gradient(rgba(255, 255, 255, 0.72), rgba(255, 255, 255, 0.72));
  background-image: var(--arm), var(--arm), var(--arm), var(--arm),
    var(--arm), var(--arm), var(--arm), var(--arm);
  background-repeat: no-repeat;
  background-size: 2.6cqw 1px, 1px 2.6cqw, 2.6cqw 1px, 1px 2.6cqw,
    2.6cqw 1px, 1px 2.6cqw, 2.6cqw 1px, 1px 2.6cqw;
  /* Inset further than the corner labels, which sit above the frame the marks
     describe rather than inside it. */
  background-position:
    left 4.2cqw top 4.2cqw, left 4.2cqw top 4.2cqw,
    right 4.2cqw top 4.2cqw, right 4.2cqw top 4.2cqw,
    left 4.2cqw bottom 4.2cqw, left 4.2cqw bottom 4.2cqw,
    right 4.2cqw bottom 4.2cqw, right 4.2cqw bottom 4.2cqw;
}

/* Tag chips, bottom right. These are the post's own tags rather than a fixed
   list, so the row cannot go stale against the article the way the baked-in
   version did. The last one takes the orange accent. */
.cover__chips {
  position: absolute;
  /* Aligned to the crop-mark frame rather than the image edge. */
  right: 4.6cqw;
  bottom: 4.6cqw;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 0.7cqw;
  margin: 0;
  padding: 0;
  list-style: none;
}

.cover__chip {
  padding: 0.55cqw 1.1cqw;
  border: 1px solid rgba(12, 27, 69, 0.14);
  border-radius: var(--st-r-xs);
  background: rgba(255, 255, 255, 0.94);
  font-family: var(--st-mono);
  font-size: 1.05cqw;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--st-navy);
  white-space: nowrap;
}

.cover__chip--key {
  border-color: var(--st-orange);
  color: var(--st-orange-dark);
}

/* Featured card schematic.
   home.css stretches the cover to `inset: 0` with `aspect-ratio: auto`, which
   suits a photograph (object-fit fills it) but not the schematic: its nodes
   are positioned in cqw against the width, so in a taller box they sit at the
   top with dead space beneath. Restore the 21:9 ratio the coordinates assume
   and centre it. Image covers keep the fill behaviour. */
.featured__media .cover:not(.cover--image) {
  top: 50%;
  bottom: auto;
  transform: translateY(-50%);
  aspect-ratio: 21 / 9;
}

/* Pull quotes.
   The handoff marks these with a 2px blue rule, which reads as emphasis more
   than as a quotation. Boxed instead, using the same surface the design gives
   .toc and .strip — hairline border, small radius, tinted ground — with a
   large quotation mark so it is unmistakably a quote. Blue, not orange: the
   design reserves orange for the internal/Sidetrade IQ side and the
   agent-harness cell. */
.article .pullquote {
  position: relative;
  border: 1px solid var(--st-border);
  border-radius: var(--st-r-sm);
  background: var(--st-gray-1);
  padding: 28px 28px 28px clamp(62px, 7vw, 82px);

  /* The design's "technical" voice is the mono stack. Monospace sets wider,
     so drop from the handoff's 24px and relax the negative tracking. */
  font-family: var(--st-mono);
  font-size: 18px;
  line-height: 1.6;
  letter-spacing: 0;
  color: var(--st-text);
}
.article .pullquote::before {
  content: "\201C";
  position: absolute;
  left: clamp(22px, 2.4vw, 28px);
  top: 0.62em;
  /* The mark stays in the display face — the mono glyph is a straight tick
     rather than a true quotation mark. */
  font-family: var(--st-font);
  font-size: clamp(54px, 7.5vw, 84px);
  font-weight: 700;
  line-height: 0;
  color: var(--st-blue);
  pointer-events: none;
}

/* Prose directly under a section heading.
   The handoff nests it inside the section, so `.section .prose
   { padding-top: 20px; gap: 20px }` applies. Our renderer emits blocks as
   siblings, so it was falling back to the standalone `.prose` values (48px /
   24px) and left too much air under every heading. Match the design. */
.article .section + .prose { padding-top: 20px; gap: 20px; }

/* Contents entries. blog.css lays each out as `display: flex` with the
   default stretch alignment, so the 12px mono number and the 14px label sit
   on different baselines. Align them on the baseline instead. */
.toc a { align-items: baseline; }

/* Title accent. The flat revision dropped the orange headline accent; this
   brings it back on the leading clause only. `title` carries that clause and
   `titleAccent` the remainder, so no string parsing is involved.

   A span rather than <em>: the accent is colour, not emphasis, and relying on
   overriding the user agent's italic default meant a stale stylesheet could
   render the headline italic. Nothing to override here. */
.post-title__lead { color: var(--st-orange); font-style: normal; }

/* Figure spacing.
   blog.css declares `figure { margin: 36px auto 0 }` and `.measure
   { margin: 0 auto }`. Every editorial figure carries both, and the class
   wins on specificity — so figures sat flush against the paragraph above.
   Restore the intended 36px at a specificity that wins. */
.article figure.measure { margin-top: 36px; }

/* Images inside article figures. blog.css only sets `img { display: block }`,
   so an uploaded diagram renders at its intrinsic width — a 1800px export
   overflows the page. Constrain to the measure and give it the same hairline
   border the design puts on every other surface. */
.article figure img {
  width: 100%;
  height: auto;
  border: 1px solid var(--st-border);
  border-radius: var(--st-r-sm);
}

/* Diagrams read better a little narrower than the prose measure. Shrink the
   whole figure rather than just the image, so the caption stays aligned with
   it. :has() keeps this off the card grids and strips, which stay full width. */
.article figure.measure:has(img) { max-width: 800px; }

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

/* .page-end gives the last section air before the navy footer. The related
   row already carries 80px of its own, so suppress it there — as the design's
   article page does, which has no .page-end at all.

   General sibling, not adjacent: the article page emits a JSON-LD <script>
   after the related row, and although it is display:none it still counts as
   an element sibling and broke the adjacent selector. */
.related ~ .page-end { display: none; }

/* --- Small screens ---------------------------------------------------------
   The handoff is desktop-only — two media queries in the entire export — and
   its nav needs 480px of run inside a 375px viewport. That overhang is what
   makes every page on the site scroll sideways, not the article content:
   .container and .measure are already fluid, so once the nav fits, nothing
   else does. */
@media (max-width: 640px) {
  :root { --st-gutter: 16px; }

  /* The section label and its divider are the first things to go. The logo
     already says whose site this is and the page says which part of it, so
     the label is the one piece of the bar carrying no destination. */
  .nav__divider,
  .nav__section { display: none; }

  .nav__inner { gap: 12px; }
  .nav__logo { height: 20px; }
  .nav__links { gap: 18px; font-size: 13px; }

  /* The three destinations all survive; only the spacing gives way. */
  .nav__links a { white-space: nowrap; }

  /* And they survive whatever the device does to the rest of the bar. A flex
     item will not shrink below its content, so on a narrow screen — or with a
     font that renders wider than it does here — the brand would otherwise push
     the links past the right edge and out of sight. Pin the links and let the
     logo be the thing that gives way, so the menu cannot go missing. */
  .nav__brand { min-width: 0; }
  .nav__links { flex: 0 0 auto; }

  /* Scale the wordmark down rather than crop it: object-fit keeps the aspect
     while max-width lets it give back the last few pixels on a narrow phone. */
  .nav__logo { max-width: 100%; object-fit: contain; object-position: left center; }
}

/* A long unbroken string — a pasted URL sitting in body copy — is the other
   thing that pushes a page sideways, and it arrives with content rather than
   with layout, so it needs a standing guard rather than a one-off fix. */
body { overflow-wrap: break-word; }
