/* ==========================================================================
   Klugwerk marketing site — main stylesheet
   Design tokens live in :root. Brand source of truth: the "Red Hexagon"
   identity (assets/images/logo/klugwerk-badge.svg) — red #D0021B on white,
   wordmark set in Vault Alarm (SimpleBits).
   ========================================================================== */

/* --- Fonts ----------------------------------------------------------------
   Vault Alarm (display/headings) — commercially licensed from SimpleBits.
   Single weight; "Sharp" is a stylistic variant registered as its own family.
   IBM Plex Sans (body) — OFL licensed, mirrored from packwerk_website.
--------------------------------------------------------------------------- */
@font-face {
  font-family: "Vault Alarm";
  src: url("/assets/fonts/vault-alarm/VaultAlarm-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Vault Alarm Sharp";
  src: url("/assets/fonts/vault-alarm/VaultAlarm-Sharp.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Sans";
  src: url("/assets/fonts/ibm-plex-sans/IBMPlexSans-Regular-Latin1.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Sans";
  src: url("/assets/fonts/ibm-plex-sans/IBMPlexSans-Italic-Latin1.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Sans";
  src: url("/assets/fonts/ibm-plex-sans/IBMPlexSans-Medium-Latin1.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Sans";
  src: url("/assets/fonts/ibm-plex-sans/IBMPlexSans-SemiBold-Latin1.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Sans";
  src: url("/assets/fonts/ibm-plex-sans/IBMPlexSans-Bold-Latin1.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* --- Design tokens -------------------------------------------------------- */
:root {
  /* Color — from the Red Hexagon identity */
  --kw-color-red-base: #D0021B;
  --kw-color-red-hover: #A80000;
  /* Warmed a step from #FAF9F7 at KWM-32 so the white section bands read
     against the body ground */
  --kw-color-surface-base: #F7F4EF;
  --kw-color-surface-raised: #FFFFFF;
  --kw-color-ink-base: #1E1B1A;
  /* Full-bleed dark ground — the nav strip (KWM-32) */
  --kw-color-ink-deep: #171210;
  --kw-color-ink-muted: #6B6462;

  /* Semantic aliases */
  --kw-color-text: var(--kw-color-ink-base);
  --kw-color-text-muted: var(--kw-color-ink-muted);
  /* Hairline rules and borders — ink at low alpha */
  --kw-color-border-hairline: rgba(30, 27, 26, 0.1);
  /* Washes — barely-there fills derived from the brand inks (table striping,
     inline code, blockquote ground) */
  --kw-color-surface-wash: color-mix(in srgb, var(--kw-color-ink-base) 4%, transparent);
  /* A deeper step of the same wash, where two fills must read as different
     (table header vs striped rows) */
  --kw-color-surface-wash-deep: color-mix(in srgb, var(--kw-color-ink-base) 12%, transparent);
  --kw-color-accent-wash: color-mix(in srgb, var(--kw-color-red-base) 10%, transparent);
  --kw-color-accent-base: var(--kw-color-red-base);
  --kw-color-accent-hover: var(--kw-color-red-hover);
  --kw-color-link: var(--kw-color-accent-base);
  --kw-color-link-hover: var(--kw-color-accent-hover);

  /* Typography */
  --kw-font-display: "Vault Alarm", system-ui, -apple-system, "Segoe UI", sans-serif;
  --kw-font-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  /* System mono stack for code in posts — no self-hosted mono face yet */
  --kw-font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  --kw-tracking-tight: -0.02em;
  --kw-tracking-open: 0.02em;

  /* Shape & depth */
  --kw-radius-sm: 4px;
  --kw-radius-md: 8px;
  /* The badge hexagon silhouette (geometry only — color comes from the
     element's background via mask). Points top/bottom, 1323:832 aspect,
     traced from the logo SVG's OUTER outline — an earlier trace used the
     inner polygon (1251:760), whose ratio is measurably squatter than the
     logo reads because the border stroke adds more height than width
     around the points (corrected at KWM-32 QA). Keep every horizontally-
     oriented decorative hexagon at this ratio: height = width x 0.6289
     (e.g. 1rem wide x 0.6289rem tall). */
  --kw-hex-silhouette: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1323 832'%3E%3Cpolygon points='661.5,0 1323,226 1323,606 661.5,832 0,606 0,226'/%3E%3C/svg%3E");
  --kw-radius-lg: 16px;
  --kw-radius-full: 9999px;
  --kw-shadow-md: 0 4px 12px rgba(30, 27, 26, 0.08);

  /* Layout */
  --kw-content-max: 72rem;
  /* Prose reading measure — long-form paragraphs cap at this width sitewide */
  --kw-measure-prose: 44rem;

  /* Spacing scale — the only values padding/margin/gap rules should use.
     Snap new spacing to the nearest step; don't add one-off values.
     (Consolidated from ~11 ad-hoc values, KWM-18.) */
  --kw-space-xs: 0.75rem;
  --kw-space-sm: 1rem;
  --kw-space-md: 1.5rem;
  --kw-space-lg: 2rem;
  --kw-space-xl: 3rem;
  --kw-space-2xl: 4rem;
  --kw-space-3xl: 6rem;
}

/* --- Reset ----------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

* {
  margin: 0;
  padding: 0;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  font-family: var(--kw-font-sans);
  color: var(--kw-color-text);
  background: var(--kw-color-surface-base);
  line-height: 1.6;
}

img,
svg {
  display: block;
  max-width: 100%;
}

/* --- Base elements ----------------------------------------------------------
   Headline hierarchy: Vault Alarm (the all-caps display face) carries the h1
   brand moment AND h2 section openers — an h1-only split was tried first, but
   the Plex h2s read too generic without the brand tie (reversed with Jason at
   the Proof Pages audit, 2026-07-09). h2 sets smaller with open tracking so
   the caps face doesn't overwhelm. h3 and below set in the body sans at
   semibold.
--------------------------------------------------------------------------- */
h1 {
  font-family: var(--kw-font-display);
  /* Vault Alarm ships a single weight — avoid synthesized bold */
  font-weight: 400;
  letter-spacing: var(--kw-tracking-tight);
  line-height: 1.15;
}

h2 {
  font-family: var(--kw-font-display);
  /* Single weight here too — avoid synthesized bold */
  font-weight: 400;
  letter-spacing: var(--kw-tracking-open);
  line-height: 1.25;
  /* Section-opener size and margin, sitewide — below the h1 moment; the
     all-caps face carries at smaller sizes. (Margin promoted here at the
     KWM-20 consolidation; every section opener uses the same rhythm.) */
  font-size: clamp(1.5rem, 3vw, 1.875rem);
  margin-bottom: var(--kw-space-md);
}

h3,
h4 {
  font-family: var(--kw-font-sans);
  font-weight: 600;
  line-height: 1.25;
}

/* Interior page h1s — short labels ("Work", "About"): a quieter opener than
   the homepage hero moment, but still clearly above the h2 section openers.
   Interior pages set <h1 class="page-title"> (KWM-19/KWM-20). */
.page-title {
  font-size: clamp(1.75rem, 3.5vw, 2.25rem);
}

/* Prose defaults — the sitewide reading measure and stacked-paragraph rhythm
   (consolidated at KWM-20 from per-section rule blocks). Components with
   mixed-element flows (contact sections, footer, post body) add their own
   `> * + *` spacing on top; a narrower component measure (hero) overrides. */
p {
  max-width: var(--kw-measure-prose);
}

p + p {
  margin-top: var(--kw-space-sm);
}

address {
  font-style: normal;
}

a {
  color: var(--kw-color-link);
}

a:hover {
  color: var(--kw-color-link-hover);
}

/* --- Focus states ---------------------------------------------------------
   One sitewide ring instead of browser defaults: Chrome's blue hugs the
   red .hero__cta pill with too little contrast to read as focus (KWM-31).
   The ink ring works on the light grounds; the dark nav strip and the red
   footer carry white companion rings beside their own rules (KWM-32). */
:focus-visible {
  outline: 2px solid var(--kw-color-ink-base);
  outline-offset: 2px;
}

/* --- Layout ------------------------------------------------------------------
   .container is the shared page-width wrapper, applied as a second class on
   the existing semantic elements (<section class="offer container">) — no
   wrapper divs. It owns width, centering, and horizontal padding; components
   keep their own vertical padding via padding-block — never the padding
   shorthand, which would clobber .container's padding-inline.
   Exception: .post deliberately stays out — it uses the narrower prose reading
   measure, --kw-measure-prose (see Post below).
--------------------------------------------------------------------------- */
.container {
  max-width: var(--kw-content-max);
  margin-inline: auto;
  padding-inline: var(--kw-space-md);
}

/* .section is the standard content-section block rhythm, applied alongside
   .container (<section class="offer container section">). Consolidated at
   KWM-20 from identical per-page rules; the hero, page headers, and footer
   deliberately keep their own vertical rhythm. (Stepped down from 2xl at
   KWM-20 QA — the 8rem section gaps read as disjointed.) */
.section {
  padding-block: var(--kw-space-xl);
}

/* Full-bleed section bands (KWM-32): sections are themselves .container
   (width-capped), so a plain background can't reach the viewport edges.
   border-image with a one-color gradient + 100vw outset paints the band
   across the full viewport without affecting layout or scrollbars — the
   no-wrapper-divs convention keeps .container on the section itself, so
   this is the cleanest full-bleed mechanism available.
   Each band sets background AND border-image in the same color: the
   background is the real, tooling-visible fill (axe/Lighthouse can't see
   border-image paint, and would compute text contrast against the body
   ground behind the band); the border-image only extends it full-bleed.
   Ground alternation: white bands alternate with the warm paper body so
   adjacent sections read as distinct areas. Interior pages band the odd
   sections (the page header supplies the leading paper); the homepage
   (has-masthead — its hero lives outside <main> on its own white band)
   re-phases to even so paper follows the black nav strip. The contact
   echo opts out: its white card needs a paper ground to read against.
   NOTE: parity is per-page section order — adding, removing, or reordering
   a <section> in <main> re-phases every band after it; recount the
   alternation whenever page structure changes. */
.hero {
  background: var(--kw-color-surface-raised);
  border-image: conic-gradient(var(--kw-color-surface-raised) 0 0) fill 0 / / 0 100vw;
}

body:not(.has-masthead) main > section:nth-of-type(odd):not(.contact-echo) {
  background: var(--kw-color-surface-raised);
  border-image: conic-gradient(var(--kw-color-surface-raised) 0 0) fill 0 / / 0 100vw;
}

.has-masthead main > section:nth-of-type(even):not(.contact-echo) {
  background: var(--kw-color-surface-raised);
  border-image: conic-gradient(var(--kw-color-surface-raised) 0 0) fill 0 / / 0 100vw;
}

/* --- Site nav ----------------------------------------------------------------
   Black strip (KWM-32). On the homepage it renders below the hero masthead
   and pins to the viewport top on scroll (see default.html); interior pages
   carry it at the top as usual. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  /* No border-image full-bleed needed here: unlike the banded sections, the
     header itself isn't a .container (the nav inside it is), so a plain
     background already spans the viewport. */
  background: var(--kw-color-ink-deep);
}

.site-nav {
  /* Stepped down from sm when the brand lockup sized up (KWM-32 QA) — the
     lockup carries the strip's height; tighter padding keeps it from
     feeling tall */
  padding-block: var(--kw-space-xs);
  display: flex;
  align-items: center;
  justify-content: space-between;
}

/* Responsive-brand lockup: the full badge needs ~120px of width before its
   detail (gears, inner wordmark, EST 2026) survives, so the nav carries the
   identity's atom instead — the red badge-silhouette hexagon (the favicon's
   glyph strategy) beside the logotext. The full badge's home is the homepage
   hero masthead. Placeholder pending a real small-context mark (KWM-33). */
.site-nav__brand {
  font-family: var(--kw-font-display);
  font-weight: 400;
  /* Sized up from the links' scale — the lockup leads the strip; both it
     and the links stay vertically centered by .site-nav's align-items.
     Tight line-height so the display face doesn't add empty strip height. */
  font-size: 1.75rem;
  line-height: 1.2;
  text-decoration: none;
  text-transform: uppercase;
  color: var(--kw-color-surface-raised);
  display: inline-flex;
  align-items: center;
  gap: var(--kw-space-xs);
}

/* The pointed top/bottom cost the hexagon visual weight against the caps —
   it oversizes past the type's cap height so the lockup reads of-a-piece
   (KWM-32 QA) */
.site-nav__brand::before {
  content: "";
  flex: none;
  /* Badge-silhouette ratio: width x 0.6289 */
  width: 2.5rem;
  height: 1.5723rem;
  background: var(--kw-color-red-base);
  -webkit-mask: var(--kw-hex-silhouette) center / contain no-repeat;
  mask: var(--kw-hex-silhouette) center / contain no-repeat;
}

/* Dims to a dirtier white — same quieting treatment as the footer's body
   text. Also outranks the global a:hover, whose dark red would all but
   vanish on the strip. */
.site-nav__brand:hover {
  color: color-mix(in srgb, var(--kw-color-surface-raised) 75%, transparent);
}

.site-nav__links {
  display: flex;
  gap: var(--kw-space-md);
  list-style: none;
}

/* Nav links at full presence (KWM-32 — muted 1rem read too quiet on the
   strip): resting white, hover on the darker-red pill, current page resting
   on a brand-red pill that inverts under the pointer. Pill padding is
   glyph-relative (em) like the inline-code chip — the spacing scale starts
   too big for a nav pill — and the negative block margin keeps the strip
   the height the padding would otherwise add to. */
.site-nav__links a {
  text-decoration: none;
  color: var(--kw-color-surface-raised);
  font-size: 1.0625rem;
  font-weight: 500;
  padding: 0.35em 0.75em;
  margin-block: -0.35em;
  border-radius: var(--kw-radius-sm);
}

.site-nav__links a:hover {
  background: var(--kw-color-red-hover);
}

/* Declared after :hover at equal specificity on purpose: the current page's
   resting pill beats the plain hover rule, and its own :hover inverts it. */
.site-nav__links a[aria-current="page"] {
  background: var(--kw-color-red-base);
}

.site-nav__links a[aria-current="page"]:hover {
  color: var(--kw-color-red-base);
  background: var(--kw-color-surface-raised);
}

/* The sitewide ink ring is invisible on the black strip */
.site-header :focus-visible {
  outline-color: var(--kw-color-surface-raised);
}

/* --- Hero ---------------------------------------------------------------------- */
.hero {
  padding-block: var(--kw-space-3xl) var(--kw-space-2xl);
  text-align: center;
}

.hero__badge {
  width: min(20rem, 70vw);
  /* Keep the 1324×832 intrinsic ratio when the width attribute is overridden */
  height: auto;
  margin: 0 auto var(--kw-space-lg);
}

.hero h1 {
  /* Slogan-length: the verb-led promise; the category claim opens the lede */
  font-size: clamp(2rem, 4.5vw, 3rem);
  max-width: 46rem;
  margin: 0 auto var(--kw-space-sm);
}

.hero p {
  font-size: 1.25rem;
  color: var(--kw-color-text-muted);
  max-width: 40rem;
  margin: 0 auto;
}

.hero__cta {
  display: inline-block;
  margin-top: var(--kw-space-lg);
  padding: var(--kw-space-xs) var(--kw-space-lg);
  background: var(--kw-color-accent-base);
  color: var(--kw-color-surface-raised);
  font-weight: 600;
  text-decoration: none;
  border-radius: var(--kw-radius-full);
}

.hero__cta:hover {
  background: var(--kw-color-accent-hover);
  color: var(--kw-color-surface-raised);
}

/* --- Homepage sections: offer, proof, contact -----------------------------------
   Block rhythm and prose measure come from .section and the base rules. */
.offer__blocks {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: var(--kw-space-md);
  margin-top: var(--kw-space-lg);
}

.offer__block {
  background: var(--kw-color-surface-raised);
  border-radius: var(--kw-radius-lg);
  box-shadow: var(--kw-shadow-md);
  padding: var(--kw-space-lg);
}

.offer__block h3 {
  font-size: 1.125rem;
  margin-bottom: var(--kw-space-xs);
  /* Brand-red card headings (KWM-32) — matches .vignette h3 */
  color: var(--kw-color-accent-base);
}

/* Closing link-out sentence after the offer cards — inline text link, spaced
   off the card grid (the proof section's link-out rides the base p + p rule) */
.offer__link-out {
  margin-top: var(--kw-space-lg);
}

/* The homepage contact section is the sitewide echo card carrying the full
   facts as labeled rows (KWM-32) — markup in index.html; the echo include
   on interior pages stays lighter and points here. */
#contact {
  /* Clear the sticky header on #contact jumps — the header is ~4rem tall,
     and the section's own top padding keeps the heading in the clear */
  scroll-margin-top: var(--kw-space-2xl);
}

/* Labeled fact rows: small-caps muted labels over full-size values, so the
   card reads as a reference card rather than loose prose */
.contact-card > div + div {
  margin-top: var(--kw-space-sm);
}

.contact-card dt {
  font-size: 0.8125rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--kw-tracking-open);
  color: var(--kw-color-text-muted);
}

.contact-card dd a {
  font-size: 1.25rem;
  font-weight: 500;
}

.contact-card__note {
  font-size: 0.9375rem;
  color: var(--kw-color-text-muted);
}

/* --- Interior pages: shared patterns ------------------------------------------
   Work ships these first (KWM-19); About and the 404 page reuse .page-header
   (KWM-20, KWM-30). The h1 is the short-label .page-title from the base styles;
   an intro paragraph beside it is optional — Work and Posts use one, About
   and 404 open straight into body copy. */
.page-header {
  /* Bottom padding keeps the header text off the first section's band edge
     (was zero when every ground matched — KWM-32) */
  padding-block: var(--kw-space-2xl) var(--kw-space-xl);
}

.page-header .page-title {
  margin-bottom: var(--kw-space-sm);
}

/* Closing contact echo — an echo of the Home contact section, not a duplicate,
   presented as a card-like callout (same surface language as .offer__block).
   Prose and contact-fact lines alternate inside it; space them as one flow. */
.contact-echo__card {
  max-width: var(--kw-measure-prose);
  background: var(--kw-color-surface-raised);
  border-radius: var(--kw-radius-lg);
  box-shadow: var(--kw-shadow-md);
  padding: var(--kw-space-lg);
}

.contact-echo__card > * + * {
  margin-top: var(--kw-space-sm);
}

/* --- Work page ------------------------------------------------------------------
   Vignettes are flowing prose (no field labels — the no-case-study-machinery
   constraint) at the base reading measure. */
.vignette + .vignette {
  margin-top: var(--kw-space-xl);
}

.vignette h3 {
  font-size: 1.125rem;
  /* Brand-red headings (KWM-32) — matches .offer__block h3 */
  color: var(--kw-color-accent-base);
}

.vignette__years {
  color: var(--kw-color-text-muted);
  font-size: 0.9375rem;
  margin-bottom: var(--kw-space-xs);
}

/* --- About page ---------------------------------------------------------------
   The headshot floats right inside the bio's prose column, so the text keeps
   the same left edge and reading measure as every other section and wraps
   around the photo. min() keeps a readable text column at narrow widths
   without CSS media queries (none exist sitewide; the img's sizes attribute
   is the only breakpoint-shaped thing on the site). */
.about-intro__bio {
  max-width: var(--kw-measure-prose);
  /* Contain the float if the photo ever outruns the text */
  display: flow-root;
}

.about-intro__photo {
  float: right;
  width: min(16rem, 45%);
  /* Keep the 800×800 intrinsic ratio when the width attribute is overridden */
  height: auto;
  margin-left: var(--kw-space-md);
  margin-bottom: var(--kw-space-sm);
  border-radius: var(--kw-radius-lg);
}

/* --- Long-form content elements ---------------------------------------------
   Blockquotes, inline code, code blocks, tables, and the thought-break rule.
   Built for post bodies (KWM-25) and promoted sitewide at KWM-32 so the
   marketing pages share the same vocabulary — pull quotes first. Post-only
   rhythm (heading margins, list indents, flow spacing, image corners) stays
   under .post-body below.
--------------------------------------------------------------------------- */
/* Quote and code blocks each get their own ground (KWM-25 QA): quotes sit on
   the brand-red wash behind the accent bar; code sits on the raised card
   surface with a hairline edge. */
blockquote {
  border-inline-start: 3px solid var(--kw-color-accent-base);
  background: var(--kw-color-accent-wash);
  padding: var(--kw-space-sm);
  border-radius: 0 var(--kw-radius-md) var(--kw-radius-md) 0;
  /* Full-ink text: the wash already sets the quote apart, and muted gray
     fought the red ground (KWM-25 QA) */
}

/* Pull quotes: select lines repeated from the page copy as signposts
   (KWM-32). The blockquote ground does the quoting; the text itself
   differentiates from body copy by going italic at a real size jump, with
   an oversized display-face quotation mark hanging in the wash. Also adds
   the flow spacing posts otherwise get from .post-body's rhythm. */
.pull-quote {
  position: relative;
  /* Deliberately narrower than the prose measure: the quote should read as
     an interruption in the flow, not a full-width block damming it — the
     right-edge inset does quietly what the section-band alternation does
     loudly. The 100% term keeps a visible inset at narrow viewports too. */
  max-width: min(36rem, 100% - var(--kw-space-lg));
  margin-block: var(--kw-space-lg);
  font-size: 1.375rem;
  line-height: 1.45;
  font-style: italic;
  padding: var(--kw-space-md);
  /* Room for the hanging mark */
  padding-inline-start: var(--kw-space-xl);
}

.pull-quote::before {
  content: "\201C";
  position: absolute;
  inset-block-start: var(--kw-space-sm);
  inset-inline-start: var(--kw-space-xs);
  font-family: var(--kw-font-display);
  font-style: normal;
  font-size: 2.5rem;
  line-height: 1;
  color: var(--kw-color-accent-base);
}

code {
  font-family: var(--kw-font-mono);
  font-size: 0.9375em;
  /* The red wash reads more present than the faint ink wash did, and ties
     inline code to the section's other accent grounds (KWM-25 QA) */
  background: var(--kw-color-accent-wash);
  /* Glyph-relative, not layout spacing — the token scale starts too big
     for an inline chip */
  padding: 0.1em 0.3em;
  border-radius: var(--kw-radius-sm);
}

pre {
  background: var(--kw-color-surface-raised);
  border: 1px solid var(--kw-color-border-hairline);
  border-radius: var(--kw-radius-md);
  padding: var(--kw-space-sm);
  /* Long lines scroll inside the block instead of breaking the measure */
  overflow-x: auto;
}

/* Inside a pre the block already provides the ground — undo the inline chip */
pre code {
  background: none;
  padding: 0;
  border-radius: 0;
}

/* Thought-break rule: red-wash line segments flanking a small brand hexagon
   (the badge silhouette) at the center */
hr {
  border: 0;
  height: 0.6289rem;
  margin-block: var(--kw-space-lg);
  background:
    linear-gradient(var(--kw-color-accent-wash), var(--kw-color-accent-wash)) left center / calc(50% - 1.25rem) 2px no-repeat,
    linear-gradient(var(--kw-color-accent-wash), var(--kw-color-accent-wash)) right center / calc(50% - 1.25rem) 2px no-repeat;
}

hr::before {
  content: "";
  display: block;
  width: 1rem;
  height: 100%;
  margin-inline: auto;
  background: var(--kw-color-accent-base);
  -webkit-mask: var(--kw-hex-silhouette) center / contain no-repeat;
  mask: var(--kw-hex-silhouette) center / contain no-repeat;
}

table {
  border-collapse: collapse;
  /* Tabular content needs more air than the base prose rhythm gives it —
     step up from the flow's space-sm on both sides */
  margin-block: var(--kw-space-md);
  /* Frame the table so header, rows, and stripes read as one object
     (KWM-25 QA) */
  border: 1px solid var(--kw-color-border-hairline);
}

th,
td {
  text-align: left;
  padding: var(--kw-space-xs) var(--kw-space-sm);
  border-bottom: 1px solid var(--kw-color-border-hairline);
}

th {
  font-weight: 600;
  /* Heavier rule under the header row than between body rows */
  border-bottom-width: 2px;
  /* Anchor the header to the table — a few steps deeper than the row
     stripes (KWM-25 QA; a red-wash header was tried and pulled back) */
  background: var(--kw-color-surface-wash-deep);
}

/* Subtle striping so rows track across columns */
tbody tr:nth-child(even) {
  background: var(--kw-color-surface-wash);
}

/* --- Posts index ----------------------------------------------------------------
   Title-plus-date rows; the muted date treatment matches .vignette__years. */
.post-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.post-list li + li {
  margin-top: var(--kw-space-sm);
}

.post-list time {
  display: block;
  color: var(--kw-color-text-muted);
  font-size: 0.9375rem;
}

/* --- Post ----------------------------------------------------------------
   Not a .container: long-form prose keeps the deliberately narrower reading
   measure (--kw-measure-prose, the sitewide paragraph cap). The h1 is the
   shared .page-title. */
.post {
  max-width: var(--kw-measure-prose);
  margin-inline: auto;
  padding: var(--kw-space-xl) var(--kw-space-md);
}

.post-header {
  margin-bottom: var(--kw-space-lg);
}

.post-header .page-title {
  margin-bottom: var(--kw-space-xs);
}

.post-header time {
  color: var(--kw-color-text-muted);
}

.post-body {
  /* Long-form reading size — a step above the 1rem UI base (KWM-25 QA);
     em-based rules below ride along */
  font-size: 1.125rem;
  /* Safety net for rare over-wide content (many-column tables): pan here
     instead of breaking the page. Don't move this onto <table> itself as
     display: block — that strips table semantics for assistive tech.
     Code blocks scroll themselves first (see pre below). */
  overflow-x: auto;
}

/* :where() zeroes this rule's specificity so promoted long-form elements
   with their own margins (hr, table, .pull-quote) beat the flow rhythm
   regardless of file order — without it, their top margins silently lost
   to this rule's higher/later position. */
:where(.post-body) > * + * {
  margin-top: var(--kw-space-sm);
}

/* Long-form prose elements Markdown can produce. Only h2 carries sitewide
   heading rhythm, and the global reset zeroes list padding — everything
   below restores what post bodies need. */
.post-body h3,
.post-body h4 {
  margin-top: var(--kw-space-lg);
}

/* Section openers need a fuller break from the prose above them (KWM-25 QA) */
.post-body h2 {
  margin-top: var(--kw-space-xl);
}

/* h3/h4 have no sitewide size; step them between the h2 opener and the
   1.125rem post prose */
.post-body h3 {
  font-size: 1.25rem;
}

.post-body h4 {
  font-size: 1.125rem;
}

.post-body ul,
.post-body ol {
  /* Restore the indent the global reset strips; also indents nested lists */
  padding-inline-start: var(--kw-space-md);
}

/* Quote, code, table, and hr treatments moved to "Long-form content
   elements" above (promoted sitewide, KWM-32). */

/* Rouge token palette — Jekyll's default highlighter already emits these
   spans (posts only, so scoping to .highlight is safe). Duotone within the
   brand: keywords brand red, strings/numbers the darker hover red, comments
   muted italic, defined names semibold. */
.highlight .c,
.highlight .c1,
.highlight .cm,
.highlight .cs {
  color: var(--kw-color-text-muted);
  font-style: italic;
}

.highlight .k,
.highlight .kd,
.highlight .kn,
.highlight .kp,
.highlight .kr,
.highlight .kt {
  color: var(--kw-color-accent-base);
}

.highlight .s,
.highlight .s1,
.highlight .s2,
.highlight .sb,
.highlight .sr,
.highlight .ss,
.highlight .m,
.highlight .mi,
.highlight .mf {
  color: var(--kw-color-accent-hover);
}

.highlight .nf,
.highlight .nc,
.highlight .no {
  font-weight: 600;
}

.post-body img {
  /* Same corner language as the About photo */
  border-radius: var(--kw-radius-lg);
}

/* Newer/older links plus the route back to the index; stacked lines, so a
   missing neighbor at either end leaves no gap. A small centered brand
   hexagon (the badge silhouette) marks the end of the post proper. */
.post-nav {
  margin-top: var(--kw-space-xl);
}

.post-nav::before {
  content: "";
  display: block;
  /* Three badge-silhouette hexagons with a half-hexagon gap between */
  width: 4rem;
  height: 0.6289rem;
  margin: 0 auto var(--kw-space-lg);
  background: var(--kw-color-accent-base);
  -webkit-mask:
    var(--kw-hex-silhouette) left center / 1rem 100% no-repeat,
    var(--kw-hex-silhouette) center / 1rem 100% no-repeat,
    var(--kw-hex-silhouette) right center / 1rem 100% no-repeat;
  mask:
    var(--kw-hex-silhouette) left center / 1rem 100% no-repeat,
    var(--kw-hex-silhouette) center / 1rem 100% no-repeat,
    var(--kw-hex-silhouette) right center / 1rem 100% no-repeat;
}

.post-nav > * + * {
  margin-top: var(--kw-space-xs);
}

/* The post column centers itself at the prose measure; center the closing
   echo card to match (elsewhere it sits at the container's left edge). */
.post + .contact-echo .contact-echo__card {
  margin-inline: auto;
}

/* --- Footer ----------------------------------------------------------------------
   Red strip closing every page — the bottom bookend to the nav (KWM-32). */
.site-footer {
  /* Real background + full-bleed border-image — see the section-bands note */
  background: var(--kw-color-red-base);
  border-image: conic-gradient(var(--kw-color-red-base) 0 0) fill 0 / / 0 100vw;
  padding-block: var(--kw-space-xl);
  /* Near-white keeps the copyright line a half-step quieter than the links
     while clearing AA on the red ground (white ~5.7:1 there; this 92% mix
     ~4.9:1 — both clear the 4.5 bar) */
  color: color-mix(in srgb, var(--kw-color-surface-raised) 92%, transparent);
  font-size: 0.875rem;
}

.site-footer a {
  color: var(--kw-color-surface-raised);
}

.site-footer :focus-visible {
  outline-color: var(--kw-color-surface-raised);
}

/* Stacked, one line per item — copyright, contact, nav echo */
.site-footer > * + * {
  margin-top: var(--kw-space-xs);
}

