/* ==========================================================================
   Servant Publishing — site stylesheet
   Hand-authored. Reproduces the palette, type scale and spacing of the
   previous Blocksy build without the framework weight.
   Edit here only; every page links this file.
   ========================================================================== */

/* --- Fonts (self-hosted: no third-party request, faster LCP) ------------ */
@font-face { font-family: 'Manrope'; font-style: normal; font-weight: 400;
  src: url('/fonts/manrope-400.woff2') format('woff2'); font-display: swap; }
@font-face { font-family: 'Manrope'; font-style: normal; font-weight: 600;
  src: url('/fonts/manrope-600.woff2') format('woff2'); font-display: swap; }
@font-face { font-family: 'Manrope'; font-style: normal; font-weight: 700;
  src: url('/fonts/manrope-700.woff2') format('woff2'); font-display: swap; }
@font-face { font-family: 'Manrope'; font-style: normal; font-weight: 800;
  src: url('/fonts/manrope-800.woff2') format('woff2'); font-display: swap; }

/* --- Design tokens ------------------------------------------------------ */
:root {
  --green:        #39A751;
  --green-dark:   #2f9946;
  /* Filled buttons only. White on the brand green #39A751 is 3.08:1, under the
     4.5:1 AA needs for 14-16px text. These are 5.30:1 and 5.89:1. The brand
     green is untouched everywhere else -- green on black is 6.82:1 already. */
  --green-btn:    #2C7A3E;
  --green-btn-hi: #2A7239;
  --text:         #d2d7dc;
  --text-dim:     rgba(255, 255, 255, 0.55);
  --heading:      #ffffff;
  --tint:         #1e2b1a;
  --surface:      #0e0e0e;
  --border:       #161d15;
  --bg:           #000000;

  --font:         'Manrope', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --content:      1290px;
  --narrow:       750px;
  --section:      100px;
  --col-gap:      50px;

  --radius:       14px;
  --radius-sm:    8px;
}

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

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

body {
  margin: 0;
  font-family: var(--font);
  font-size: 16px;
  font-weight: 400;
  line-height: 1.65;
  color: var(--text);
  /* The footer texture used to live here as a bottom-anchored body background
     at `contain` -- 1217px tall, which is 80% of a short page like /contact/.
     It collided with the section backdrops (see .site-footer::after). */
  background-color: var(--bg);
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; height: auto; display: block; }

a { color: var(--green); text-decoration: none; }
a:hover { color: var(--green); }

/* --- Typography --------------------------------------------------------- */
h1, h2, h3, h4, h5, h6 {
  color: var(--heading);
  font-weight: 800;
  margin: 0 0 0.5em;
}

h1 { font-size: clamp(2.15rem, 1.35rem + 2.6vw, 3.375rem); line-height: 1; margin-bottom: 50px; }
.h1-second { display: block; margin-top: 0.55em; }
h2 { font-size: clamp(1.6rem, 1.2rem + 1.4vw, 2.1875rem);  line-height: 1.5; margin-bottom: 20px; max-width: 500px; }
h3 { font-size: 1.125rem; line-height: 1.5; }
h4 { font-size: 1rem;     line-height: 1.5; }

p { margin: 0 0 1.15em; }
p:last-child { margin-bottom: 0; }

ul, ol { margin: 0 0 1.15em; padding-left: 1.25em; }
li { margin-bottom: 0.4em; }

strong { color: var(--heading); font-weight: 700; }

hr {
  border: 0;
  border-top: 1px solid var(--border);
  margin: 2.5rem auto;
  max-width: 80px;
}

/* --- Layout ------------------------------------------------------------- */
/* Live sizes containers as min(max-width, 90vw) with no inner padding, so the
   content box is the full 1290px rather than 1290 minus gutters. The 90vw is
   what provides the edge spacing on narrower viewports. */
.container {
  width: min(var(--content), 90vw);
  margin-inline: auto;
}

.container--narrow { width: min(var(--narrow), 90vw); }

.section { padding-block: var(--section); margin-bottom: var(--section); }
.section--tight { padding-block: calc(var(--section) * 0.6); }

.skip-link {
  position: absolute; left: -9999px;
  background: var(--green); color: #fff;
  padding: 0.75rem 1.25rem; border-radius: var(--radius-sm); z-index: 100;
}
.skip-link:focus { left: 1rem; top: 1rem; }

/* --- Focus visibility --------------------------------------------------- */
/* WCAG 2.4.7 and 2.4.11. The form fields previously set outline:none and
   signalled focus with a 1px border tint, which is not a visible indicator.
   :focus-visible so a mouse click does not paint a ring, only keyboard entry. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
[tabindex]:focus-visible {
  outline: 3px solid var(--green);
  outline-offset: 2px;
}

/* --- Header ------------------------------------------------------------- */
.site-header { padding-block: 1.5rem; position: relative; z-index: 20; }

.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
}

.brand { display: flex; align-items: center; }
.brand img { width: 399px; max-width: 60vw; height: auto; }

.nav { display: flex; align-items: center; gap: 30px; }

/* 20px, up from 13px. 20 is the ceiling, not a preference: the nav collapses
   to the toggle below 1000px, and at exactly 1000px the brand plus the nav row
   needs 900px of a 900px container. 24px needs 901px and is already cramped;
   30px needs 969px and pushes the page into horizontal scroll. Measured, not
   estimated — raise this only if the brand mark or the link set shrinks. */
.nav a:not(.btn) {
  color: var(--heading);
  font-size: 16px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.nav a:not(.btn):hover { color: var(--green); }

/* The header CTA sat at the global .btn 14px, which read undersized once the
   nav links went to 20px. 16px balances the row. Measured headroom: up to
   20px still fits at 1000px, the narrowest width the desktop nav is shown. */
.nav .btn { font-size: 16px; }

/* 24px minimum pointer target; the 20px type clears this on its own now. */
.nav a:not(.btn) { display: inline-flex; align-items: center; min-height: 24px; }

.nav a[aria-current="page"] {
  background: var(--surface);
  border-radius: var(--radius-sm);
  padding: 0.5rem 0.85rem;
}

/* --- Buttons ------------------------------------------------------------ */
/* Geometry measured off live (Blocksy), not chosen. Live renders four distinct
   treatments and the rebuild had collapsed them into one:
     solid small   10px 20px / 14px 600 / min-h 40 / no border  -> 43px  (.btn--primary)
     solid large   15px 30px / 16px 600 / min-h 40 / no border  -> 56px  (.btn--lg)
     outline       5px 20px  / 14px 600 / min-h 42 / 2px border -> 42px  (.btn--outline)
     text          0 padding / 16px 500 / no border             -> 26px  (.btn--text)
   Heights fall out of the inherited 1.65 line-height; do not set line-height here. */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.7em;
  font-size: 14px;
  font-weight: 600;
  padding: 10px 20px;
  min-height: 40px;
  border-radius: 7px;
  border: 0 solid transparent;
  transition: background-color 0.18s ease, border-color 0.18s ease, color 0.18s ease;
}

/* Live's hero call to action is the only oversized button on the site. */
.btn--lg { font-size: 16px; padding: 15px 30px; }

.btn--primary { background: var(--green-btn); color: #fff; }
.btn--primary:hover { background: var(--green-btn-hi); color: #fff; }

.btn--outline { border-width: 2px; border-color: var(--green); color: var(--green); padding: 5px 20px; min-height: 42px; }
.btn--outline:hover { background: var(--green); color: #fff; }

.btn--text {
  color: var(--heading);
  padding: 0;
  min-height: 0;
  font-size: 16px;
  font-weight: 500;
}
.btn--text:hover { color: var(--green); }

.btn-row { display: flex; flex-wrap: wrap; align-items: center; gap: 1.5rem; margin-top: 2rem; }

.arrow { transition: transform 0.18s ease; }
.btn:hover .arrow { transform: translateX(3px); }

/* --- Cards -------------------------------------------------------------- */
.card {
  position: relative;
  /* Establishes a stacking context so a z-index:-1 child paints over this
     card's own background rather than dropping behind it entirely. */
  isolation: isolate;
  background: #0c0c0c;
  background-image: linear-gradient(rgba(10, 43, 18, 0.42) 0%, rgb(12, 12, 12) 64%);
  border: 0;
  border-radius: 12px;
  padding: 40px;
  /* Green hairline along the top edge plus a 1px ring — lifts the card off the page. */
  box-shadow: 0 -1px 0 0 rgba(82, 255, 125, 0.16), 0 0 0 1px rgba(255, 255, 255, 0.12);
}

/* The angle has to be a registered property or it will not interpolate. */
@property --border-animation-angle {
  syntax: '<angle>';
  initial-value: 0deg;
  inherits: false;
}

@keyframes borderRotate { to { --border-animation-angle: 1turn; } }

/* A single green arc chasing the border, masked down to a 1px ring. */
.card::after {
  content: '';
  position: absolute;
  inset: -1px;
  border-radius: 12px;
  padding: 1px;
  background: conic-gradient(from var(--border-animation-angle),
    rgba(0, 0, 0, 0) 88%,
    rgba(82, 254, 125, 0.45),
    rgba(82, 254, 125, 0.45) 100%,
    rgba(0, 0, 0, 0));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  animation: borderRotate 7s linear infinite;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .card::after { animation: none; }
}

.card :is(h2, h3) { margin-bottom: 0.6rem; max-width: none; }
.page--contact .card h2 { font-size: 1.125rem; line-height: 1.5; }
.card p:last-child { margin-bottom: 0; }

.card--plain { background-image: none; }

.grid { display: grid; gap: 1.5rem; }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }

.split {
  display: grid;
  grid-template-columns: 1.14fr 1fr;
  gap: var(--col-gap);
  align-items: center;
}

.eyebrow {
  display: inline-block;
  color: var(--green);
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  margin-bottom: 0.85rem;
}

.lead { font-size: 1.0625rem; }

.icon-badge {
  width: 52px; height: 52px;
  display: grid; place-items: center;
  background: var(--green);
  border-radius: 50%;
  margin-bottom: 1.15rem;
}
.icon-badge svg { width: 24px; height: 24px; stroke: #fff; fill: none; stroke-width: 2; }

/* --- Prose (policy + long-form pages) ----------------------------------- */
.prose h2 { margin-top: 2.5rem; }
.prose h3 { margin-top: 1.75rem; color: var(--heading); }
.prose > *:first-child { margin-top: 0; }
.prose .updated { color: var(--text-dim); font-size: 0.9375rem; }
.prose ul { list-style: disc; }

.definition-list { margin: 0 0 1.15em; }
.definition-list dt { color: var(--heading); font-weight: 700; margin-top: 1rem; }
.definition-list dd { margin: 0.25rem 0 0; }

/* --- Contact ------------------------------------------------------------ */
.contact-list a { display: inline-block; min-height: 24px; padding-block: 2px; }
.contact-list { list-style: none; margin: 0; padding: 0; }
.contact-list li { display: flex; gap: 1.15rem; align-items: flex-start; margin-bottom: 1.85rem; }
.contact-list li:last-child { margin-bottom: 0; }
.contact-list .label { color: var(--heading); font-weight: 700; display: block; }

.field { margin-bottom: 1.15rem; }
.field label { display: block; color: var(--heading); font-weight: 600; margin-bottom: 0.45rem; font-size: 0.9375rem; }

.field input, .field textarea {
  width: 100%;
  min-height: 45px;
  padding: 0.7rem 0.9rem;
  font-family: inherit;
  font-size: 1rem;
  color: var(--heading);
  background: rgba(0, 0, 0, 0.3);
  border: 2px solid var(--border);
  border-radius: 10px;
}
.field textarea { min-height: 150px; resize: vertical; }
.field input:focus, .field textarea:focus { border-color: var(--green); }

.form-status { margin-top: 1rem; font-weight: 600; }
.form-status[data-state="error"] { color: #ff6b6b; }
.form-status[data-state="ok"] { color: var(--green); }

/* --- Projects list ------------------------------------------------------ */
.project { margin-bottom: 1.5rem; }
.project:last-child { margin-bottom: 0; }
.project :is(h2, h3) { font-size: 1.375rem; }

/* --- Footer ------------------------------------------------------------- */
.site-footer {
  border-top: 1px solid var(--border);
  padding-block: 3.5rem;
  margin-top: var(--section);
  text-align: center;
}

.footer-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1rem 2rem;
  margin-bottom: 2rem;
}

.footer-links a { color: var(--text); font-size: 18px; }
.footer-links a:hover { color: var(--green); }

.footer-legal { color: var(--text-dim); font-size: 16px; margin: 0; }

/* --- Responsive --------------------------------------------------------- */
@media (max-width: 900px) {
  :root { --section: 64px; --col-gap: 32px; }
  .split { grid-template-columns: 1fr; }
  .grid--3 { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 640px) {
  .grid--2, .grid--3 { grid-template-columns: 1fr; }
  .site-header .container { flex-wrap: wrap; gap: 1rem; }
  .nav { gap: 18px; width: 100%; flex-wrap: wrap; }
  .brand img { width: 220px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition: none !important; }
}

/* --- In-page images ----------------------------------------------------- */
/* Live renders every image square — the 12px radius is on cards, not images. */
.card img { border-radius: 0; margin-bottom: 1.25rem; }
.card img:last-child { margin-bottom: 0; margin-top: 1.25rem; }

.figure-right {
  float: right;
  width: 260px;
  margin: 0.35rem 0 1.5rem 2rem;
  border-radius: 0;
}

.prose::after { content: ""; display: table; clear: both; }

@media (max-width: 640px) {
  .figure-right { float: none; width: 100%; margin: 0 0 1.5rem; }
}

/* --- Bare portrait with a card riding over its lower edge --------------- */
/* Matches the live hero: the photo carries no card treatment of its own, and
   the card's translucent top lets the jacket read through the rounded corners. */
.card-stack { display: flex; flex-direction: column; }
.card-stack > img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 0;
  margin: 0;
}
/* Live markup is figure{margin-bottom:0} + card — flush, no overlap. */
.card-stack > .card { margin-top: 0; }

/* --- Hero card cluster --------------------------------------------------- */
/* Live splits this side into two sub-columns: two stacked cards on the left,
   the portrait with its card beneath on the right. */
.split--top { align-items: start; }

.hero-cards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
  align-items: start;
}

.hero-cards__col {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

/* Artwork sits above the card's gradient but below its text, as on the live
   build (a negative z-index child paints over the parent background only). */
.card--figure { min-height: 480px; }

/* Shared artwork layer. A z-index:-1 child paints over the card's own
   background but under its text, which is how the live build layers these. */
.card--figure::before,
.card--art-youtube::before,
.card--art-publishing::before,
.card--art-niche::before,
.card--art-independent::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: 12px;
  background-repeat: no-repeat;
}

.card--figure::before {
  background-image: url('/images/home-hero-image-2.webp');
  background-size: contain;
  background-position: 50% 100%;
}

.card--art-youtube::before {
  background-image: url('/images/home-about-section-image-1-1.webp');
  background-size: cover;
  background-position: 50% 100%;
}

.card--art-publishing::before {
  background-image: url('/images/home-about-section-image-2.png');
  background-size: contain;
  background-position: 50% 0;
}

.card--art-niche::before {
  background-image: url('/images/home-about-section-image-5.webp');
  background-size: contain;
  background-position: 50% 100%;
}

.card--art-independent::before {
  background-image: url('/images/home-about-section-image-4-1.webp');
  background-size: cover;
  background-position: 0% 0;
}

@media (max-width: 900px) {
  .hero-cards { grid-template-columns: 1fr; }
  .card--figure { min-height: 360px; }
}

/* --- Hero card typography ----------------------------------------------- */
/* Live styles each hero card individually rather than on one scale. */
.hero-cards .card { text-align: center; }
.hero-cards .card :is(h2, h3) {
  font-size: 42px;
  font-weight: 900;
  line-height: 1;
  margin-bottom: 10px;
  color: var(--heading);
}
.hero-cards .card p {
  font-size: 20px;
  font-weight: 600;
  line-height: 33px;
  color: var(--heading);
  margin: 0;
}

.card-stack .card :is(h2, h3) { font-size: 36px; font-weight: 700; }
.card-stack .card p  { font-weight: 700; }

/* Scoped to .hero-cards so it outranks the generic hero card heading rule. */
.hero-cards .card--compact {
  padding: 25px 40px;
  text-align: left;
}
.hero-cards .card--compact :is(h2, h3) {
  font-size: 20px;
  font-weight: 700;
  line-height: 33px;
  margin-bottom: 0;
}

.lead { font-size: 20px; line-height: 33px; margin-bottom: 30px; }

/* Superseded by the measured per-element scale at the end of this file.
   The rule that lived here (.hero-cards .card h3 -> 32px at 900px) had the
   same specificity as .hero-cards .card--compact h3 but came later, so it
   silently GREW "Quality over Quantity" from 20px to 32px on tablet and
   phone. Live takes that heading down to 16px. */

/* --- Full-bleed section backdrops --------------------------------------- */
/* Live carries these as row-level background images, separate from the
   body backdrop. Without them the page reads as flat black. */
.section--hero {
  background-image: url('/images/bg-test-12-scaled-1.jpg');
  background-repeat: no-repeat;
  background-position: 50% 100%;
  background-size: cover;
}

/* The projects section used to carry bg-test-section-2-2-scaled-1.jpg here,
   anchored top at `contain`. Removed 2026-08-23: the body already paints
   footer-background.jpg anchored to the BOTTOM of the page, and the two
   overlapped by ~817px. Both are diagonal stripe textures at different
   scales, so the overlap read as doubled stripes above the footer.
   Live has the identical overlap (~860px) -- this is a deliberate departure
   from live, not a regression. Do not "restore" it to match live without
   also solving the overlap. */

/* --- Projects section grid ---------------------------------------------- */
/* Live leads with a wide feature card beside a narrow one (849/411), then a
   row of three equal cards. Gap is 30px, not the 24px used elsewhere. */
.section--projects .grid { gap: 30px; }
.section--projects .grid--2 { grid-template-columns: 849fr 411fr; }

/* --- Feature block ------------------------------------------------------ */
/* Live renders this artwork at 393px inside a 437px column, not full bleed. */
.card--plain img {
  /* min() keeps the fixed live width from overflowing narrow viewports. */
  max-width: min(393px, 100%);
  margin-inline: auto;
}
.card--plain h3 { font-size: 22px; }

@media (max-width: 900px) {
  .section--projects .grid--2 { grid-template-columns: 1fr; }
}

/* --- Header nav / footer metrics ---------------------------------------- */
/* Live: 12px uppercase 700, no tracking; only the current page reads white.
   The size is deliberately NOT set here any more. This rule used to carry
   font-size:12px, and because it has the same specificity as the nav rule
   near the top of the file but comes later, it silently won -- editing the
   size up there did nothing. Size lives in one place now; keep it that way. */
.nav a:not(.btn) {
  color: var(--text);
  letter-spacing: normal;
}
.nav a[aria-current="page"] { color: var(--heading); }

.site-footer {
  padding-top: 50px;
  padding-bottom: 0;
}

/* --- Project cards ------------------------------------------------------ */
/* Tighter padding than hero cards, and fixed min-heights per row. */
.section--projects .card { padding: 30px; }
.section--projects .grid--2 > .card { min-height: 450px; }
.section--projects .grid--3 > .card { min-height: 350px; }

@media (max-width: 900px) {
  .section--projects .grid--2 > .card,
  .section--projects .grid--3 > .card { min-height: 0; }
}

/* Live footer is two banded rows: links 118px tall, copyright 98px, on top of
   the footer's own 50px lead-in. */
.footer-links { padding-block: 50px; }
.footer-legal { padding-block: 40px; margin: 0; }

/* --- Per-page h1 scale -------------------------------------------------- */
/* Live sets policy titles at 30px, which is SMALLER than its own section
   headings (35px, or 40px on /privacy-policy/) — the page title ends up looking
   subordinate to its sections. We deliberately depart from live here and run the
   title at 50px, matching the founder page, so the hierarchy reads correctly.
   Section headings stay at live's sizes. */
/* --- Wide editorial pages (about, founder) ------------------------------ */
/* Live runs these at full container width with 20px body copy, not in the
   750px prose column used by the policy pages. */
.page--wide p,
.page--wide li { font-size: 20px; line-height: 33px; }
.page--wide h2 { font-size: 36px; }
/* Per-image widths taken from the live build. */
.figure-right--615 { width: 615px; }
.figure-right--366 { width: 366px; }
.figure-right--300 { width: 300px; }
.figure-right--266 { width: 266px; }

@media (max-width: 900px) {
  .figure-right--615,
  .figure-right--366,
  .figure-right--300,
  .figure-right--266 { width: 100%; float: none; margin: 0 0 1.5rem; }
}

/* --- Projects page cards ------------------------------------------------ */
/* Live insets these images to 473px inside a 630px card rather than letting
   them fill it, and runs card copy at 18px. */
/* Live centres the card artwork. `img { display: block }` means a text-align
   on the card does nothing, so these sat flush left. Same cause as the two
   founder images. */
.project img { max-width: min(473px, 100%); margin-inline: auto; }
.project p { font-size: 18px; }

/* --- Narrow-viewport overflow guards ------------------------------------ */
/* Grid items default to min-width:auto, so a fixed-width child (the 300px
   Turnstile iframe) forces its track wider than the container. */
.split > *,
.grid > *,
.hero-cards > * { min-width: 0; }

.cf-turnstile { max-width: 100%; }

@media (max-width: 640px) {
  /* 90vw at 375px is ~338px; 16px side padding leaves ~306px of content,
     which is just enough for the 300px Turnstile widget. */
  .card { padding: 24px 16px; }
  .hero-cards .card--compact { padding: 20px 16px; }
}

/* --- Prose interiors: match live, per page ------------------------------ */
/* Live's page templates are not consistent with one another, so these are
   scoped per page rather than shared. Measured against live 2026-08-21.
   NOTE: .page--legal and .page--wide BOTH carry .prose. Anything put on
   .prose alone therefore lands on the policy pages AND about/founder --
   which is how an earlier pass pushed /about/ headings to 40px when live
   runs 35px. Scope to the page class unless it genuinely applies to all. */

/* Policy pages. Live marks numbered sections up as h1 and sub-sections as h2,
   putting sixteen h1 elements on /privacy-policy/ alone. We keep one h1 and
   step down through h2/h3 -- matching live's SIZES, not its markup. */
/* Live is NOT uniform here, and an earlier pass normalised it to one scale.
   Measured 2026-08-22 across all six live policy pages:
     /privacy-policy/  marks numbered sections as h1 (40px) with h2 sub-sections (35px)
     every other page  marks sections as h2 (35px), with no sub-sections at all
   So 40px is the exception, not the rule. Sections are 35px by default; the
   numbered privacy page opts up via .page--legal-numbered. */
.page--legal h2 { font-size: 2.1875rem; line-height: 1.5; max-width: none; }  /* live 35/53 */
.page--legal h3 { font-size: 1.875rem;  line-height: 1.5; }                   /* live 30 */

.page--legal-numbered h2 { font-size: 2.5rem;    }  /* live 40/60 — numbered sections */
.page--legal-numbered h3 { font-size: 2.1875rem; }  /* live 35/53 — sub-sections */

/* Live spaces policy headings as 1.5em top — so the gap scales WITH the heading
   (52.5px at 35px, 60px at 40px). `.prose h2` used a flat 2.5rem/40px, which ran
   ~20px tight on every section and compounded down the page: /privacy-policy/
   finished 824px short of live over 19 sections. */
.page--legal h2,
.page--legal h3 { margin-top: 1.5em; margin-bottom: 20.5px; }   /* live 52.5 / 20.5 */
.page--legal-numbered h2 { margin-bottom: 22px; }               /* live 60 / 22 */

/* Live's 30px title carries no margin of its own. At our 50px it needs a little,
   or the "Last updated" line underneath reads as though it is crashing into it. */
.page--legal h1 { line-height: 1.2; margin-bottom: 0.35em; }
/* Body copy matches /about/ and /founder/ at 20px/33. At the existing 750px
   column that is 75 characters per line -- the same measure /about/ runs and
   right in the comfortable 45-75 band. It was 16px, which gave 93 characters:
   consistent with nothing and a long measure to read. Deliberately NOT widened
   to the 1290px container: at 20px that would be ~129 characters a line. */
.page--legal p,
.page--legal li { font-size: 20px; line-height: 33px; }
.page--legal p  { margin-bottom: 1.5em; }                                     /* live 24 @16 */
.page--legal ul,
.page--legal ol { padding-left: 2.5em; margin-bottom: 1.5em; }                /* live 40 / 24 */
.page--legal li { margin-bottom: 0; }                                         /* live 0 */

/* The 404 borrows the policy pages' prose column but not their heading scale.
   Policy pages run h1 30 / h2 40 on purpose, mirroring live's markup quirk
   (live marks numbered sections as h1). There is no live 404 to mirror, and
   that scale renders as an inverted hierarchy once the page has subheadings. */
.page--404 h1 { margin-bottom: 30px; }   /* size inherited from .page--legal */
.page--404 h2 { font-size: 1.75rem; margin-top: 40px; }

/* Wide editorial pages. Live runs both titles at line-height 1.3 with a 20px
   gap below, and separates paragraphs with <br><br> -- one blank line, so the
   paragraph gap is the 33px line-height rather than a margin. */
.page--wide h1 { line-height: 1.3; margin-bottom: 20px; }   /* live 60/78 and 50/65 */
.page--wide p  { margin-bottom: 1.65em; }                   /* live 33 @20 */

/* Live's two wide pages disagree with each other; match each as it is. */
.page--about   h2 { font-size: 2.1875rem; line-height: 1.5; margin-bottom: 20px; } /* 35/53 */
.page--founder h2 { font-size: 2.25rem;   line-height: 1;   margin-bottom: 40px; } /* 36/36 */

/* Link underlining lives in ONE place: the site-wide rule near the end of this
   file (main p a / main li a). A .prose-scoped rule used to sit here setting
   text-decoration:none -- while its own comment said colour-only links fail
   WCAG 1.4.1 -- and it outranked the site-wide rule on specificity, so ten of
   the thirteen pages shipped undecorated links. Do not reintroduce it. */
/* (removed: see the site-wide underline rule near the end of this file) */

/* --- Wide pages: live's responsive scale -------------------------------- */
/* Live (Blocksy/GreenShift) breaks at 999.98px and 689.98px and centres all
   text from the tablet breakpoint down. Values read from live's own inline
   CSS on 2026-08-21, per element, not inferred:
       about   title 60 / 45 / 30      sections 35 / 30 / 25   body 20 / 18 / 16
       founder title 50 / 45 / 30      sections 36 / 45 / 30   body 20 / 20 / 20
   Founder's sections genuinely grow at tablet (36 -> 45) before dropping to
   30; that is live's own inconsistency, reproduced rather than smoothed. */

@media (max-width: 999.98px) {
  .page--wide h1,
  .page--wide h2,
  .page--wide h3,
  .page--wide p     { text-align: center; }
  .page--wide h2    { max-width: 100%; }
  .page--about h2   { font-size: 1.875rem; }   /* 30 */
  .page--about p    { font-size: 1.125rem; }   /* 18 */
  .page--founder h2 { font-size: 2.8125rem; }  /* 45 */
}

@media (max-width: 689.98px) {
  .page--about h2   { font-size: 1.5625rem; }  /* 25 */
  .page--about p    { font-size: 1rem; }       /* 16 */
  .page--founder h2 { font-size: 1.875rem; }   /* 30 */
}

/* --- Mobile navigation -------------------------------------------------- */
/* Live collapses its nav behind a button below the tablet breakpoint. Ours ran
   as one row to 640px, which overflowed the viewport between ~690 and 900px,
   then stacked into a 219px-tall header on phones. Collapsing at live's
   999.98px fixes both.
   The nav is hidden only when nav.js has confirmed it can be reopened
   (.has-nav-toggle on <html>), so with JS off the links stay reachable. */
.nav-toggle { display: none; }

@media (max-width: 999.98px) {
  .site-header .container { flex-wrap: wrap; gap: 1rem; }

  .nav-toggle {
    display: inline-flex;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    width: 44px;                 /* 44px keeps the tap target accessible */
    height: 44px;
    padding: 0 8px;
    background: none;
    border: 0;
    cursor: pointer;
  }
  .nav-toggle__bar {
    display: block;
    height: 2px;
    background: var(--heading);
    border-radius: 2px;
  }
  .nav-toggle[aria-expanded="true"] .nav-toggle__bar { background: var(--green); }

  .has-nav-toggle .nav { display: none; }
  .has-nav-toggle .nav.nav--open { display: flex; }

  .nav {
    width: 100%;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    padding-top: 0.5rem;
  }
  .nav a:not(.btn) { padding: 10px 0; }
  .nav .btn { margin-top: 0.5rem; }
}

/* Live underlines prose links only while they are NOT hovered -- its rule is
   literally `:not(:hover) { text-decoration: underline }` -- and swaps the
   colour to white via --theme-link-hover-color. Our a:hover already goes to
   var(--heading) (#ffffff); this drops the underline to finish the match. */
/* (removed: prose links are underlined at rest now) */

/* --- Home and projects: live's responsive scale ------------------------- */
/* Live's title on both pages steps 54 / 45 / 30 and it centres headings and
   running text from the tablet breakpoint down; section headings step 30 / 25.
   NOT replicated: live tunes individual card and stat elements to a dozen
   separate sizes (15/16/18/20/22/36/42px) through the page builder. Those are
   per-element builder values rather than a scale, and are listed as remaining
   deltas rather than guessed at. */
@media (max-width: 999.98px) {
  /* Home runs left-aligned at every width; /projects/ stays centred. */
  .page--projects h1, .page--projects h2, .page--projects p { text-align: center; }
  .page--home h2, .page--projects h2 { font-size: 1.875rem; }   /* 30 */

  /* Live keeps the project cards' body copy left-aligned at every width,
     even while centring the headings around it. */
  .page--projects .project p { text-align: left; }
}

@media (max-width: 689.98px) {
  .page--home h2, .page--projects h2 { font-size: 1.5625rem; }  /* 25 */
}

/* --- 320px viewports ---------------------------------------------------- */
/* iPhone SE and small Androids report ~305px of usable width. Two things
   broke there and nowhere else. */

/* Policy prose cites full URLs. An unbreakable 311px link pushed the page
   19px wide; allow breaks inside links only, not in ordinary prose. */
.prose a { overflow-wrap: anywhere; }

@media (max-width: 359.98px) {
  /* Turnstile renders a fixed 300px widget and offers nothing narrower short
     of its compact variant, which changes the shape entirely. `zoom` scales
     the layout box so the page stops overflowing; `transform` would scale the
     paint only and leave the 300px box behind. */
  .cf-turnstile { zoom: 0.8; }
}

/* A 40px heading containing one long word ("recommendation") measured 338px in
   a 288px column at 320px wide. break-word only splits a word that cannot fit
   on its own line, so headings are untouched at every width where they do. */
.prose h1,
.prose h2,
.prose h3 { overflow-wrap: break-word; }

/* --- Homepage: live's per-element sizes --------------------------------- */
/* Live styles every homepage element individually through its page builder
   rather than on a scale. Each value below was read from live's own inline
   CSS and matched to our element by its text, on 2026-08-21. Format is
   desktop / <=999.98px / <=689.98px. Where live declares no override the
   base value simply carries, which is why several rows repeat.
   Live's breakpoints, not ours -- do not "tidy" these to 900/640. */

/* Hero lead. The projects-section lead is deliberately NOT included: live
   holds that one at 20px all the way down. */
.split--top .lead { font-size: 20px; }                        /* 20/18/16 */

/* Hero cards */
.hero-cards .card--figure :is(h2, h3) { font-size: 42px; }             /* 42/35/35 */
.hero-cards .card--figure p  { font-size: 20px; }             /* 20/16/16 */
.hero-cards .card--compact :is(h2, h3) { font-size: 20px; }            /* 20/16/16 */
.card-stack .card :is(h2, h3) { font-size: 36px; }                     /* 36/16/22 */
.card-stack .card p  { font-size: 20px; }                     /* 20/16/16 */

/* "What We Build" cards. Scoped away from .section--projects, which shares
   .grid--3 but runs its body copy a size larger. */
.section:not(.section--projects) .grid--3 .card :is(h2, h3) { font-size: 18px; }   /* 18/16/16 */
.section:not(.section--projects) .grid--3 .card p  { font-size: 15px; line-height: 25px; }  /* 15 flat */

/* Full-width card under "What We Build" */
.card--plain h3 { font-size: 22px; }                          /* 22/18/18 */
.card--plain p  { font-size: 15px; line-height: 25px; }       /* 15 flat */

/* Platforms and Projects cards: headings step down, body copy holds at 16. */
.section--projects .card :is(h2, h3) { font-size: 18px; }              /* 18/16/16 */

@media (max-width: 999.98px) {
  .split--top .lead { font-size: 18px; }
  .hero-cards .card--figure :is(h2, h3) { font-size: 35px; }
  .hero-cards .card--figure p  { font-size: 16px; }
  .hero-cards .card--compact :is(h2, h3) { font-size: 16px; }
  .card-stack .card :is(h2, h3) { font-size: 16px; }
  .card-stack .card p  { font-size: 16px; }
  .section:not(.section--projects) .grid--3 .card :is(h2, h3) { font-size: 16px; }
  .card--plain h3 { font-size: 18px; }
  .section--projects .card :is(h2, h3) { font-size: 16px; }
}

@media (max-width: 689.98px) {
  .split--top .lead { font-size: 16px; }
  /* Live really does step this one 36 -> 16 -> 22, growing again on phones.
     Reproduced rather than smoothed. */
  .card-stack .card :is(h2, h3) { font-size: 22px; }
}

/* --- Wide pages: live's 1215 content column ----------------------------- */
/* The outer container already matches live exactly at 1290. Inside it, live
   runs its headings and main text column at 1215 -- the row is split into
   columns and the content column takes 1290 minus a 75px gap. Measured on
   live 2026-08-21: about title 1215, about intro text 1215, founder h1 1215,
   founder "Todd Temaat" h2 1215.
   Left-aligned inside the container, not centred: live's blocks start at the
   container's left edge, so no auto margins here. */
.page--wide h1,
/* 750px, matching /editorial-standards/ and the seven policy pages, which all
   run a uniform 750 column. At 20px that is 75 characters a line. These two
   pages previously mixed 750 and 1220 within the same page, and the 1220
   paragraphs ran 121 characters -- the longest measure on the site. */
.page--wide h2,
.page--wide h3,
.page--wide p { max-width: 750px; margin-inline: auto; }
/* Button rows and list blocks belong to the same column, or they hang off
   its left edge while the copy beside them stays put. */
.page--wide .btn-row,
.page--wide ul,
.page--wide ol { max-width: 750px; margin-inline: auto; }

@media (max-width: 999.98px) {
  /* Centred from tablet down, so the cap must centre with the text. */
  .page--wide h1,
  .page--wide h2,
  .page--wide h3,
  .page--wide p { max-width: 100%; }
}

/* --- Live's column structures ------------------------------------------- */
/* Measured from live 2026-08-21. These are layout, not decoration: without
   them the sections stack where live runs them side by side. */

/* Section header: heading left, lead beside it.
   Live: 405 + 835 with a 50px gap, on both / and /projects/. */
.section-head {
  display: grid;
  grid-template-columns: 405fr 835fr;
  gap: 50px;
  align-items: start;
}
.section-head > h2 { margin-bottom: 0; }
.section-head > .lead { margin-bottom: 0; }

/* "What We Build": live is ONE row of two columns, 823 + 437 with a 30px gap,
   bottom-aligned, with the three cards nested inside the left column at 254
   each. Ours previously ran the cards full width and dropped the wide card
   underneath. */
.feature-row {
  display: grid;
  grid-template-columns: 823fr 437fr;
  gap: 30px;
  align-items: end;
}
.feature-row .grid--3 { grid-template-columns: repeat(3, 1fr); gap: 30px; }

@media (max-width: 999.98px) {
  /* Live collapses these to a single column below the tablet breakpoint. */
  .section-head,
  .feature-row { grid-template-columns: 1fr; gap: 24px; }
  .section-head { text-align: center; }
}

/* --- Projects page: live's own values ----------------------------------- */
/* The homepage really does run 849/411 here, but /projects/ runs two equal
   630 columns. The shared .section--projects rule was applying the homepage's
   split to both. */
.page--projects .section--projects .grid--2 { grid-template-columns: repeat(2, 1fr); }

/* Live: project card headings 22/33/700 centred; ours were 18/27/800 left. */
.page--projects .project :is(h2, h3) {
  font-size: 22px;
  line-height: 33px;
  font-weight: 700;
  text-align: center;
  max-width: 405px;
  margin-left: auto;
  margin-right: auto;
}
.page--projects .project .btn-row { justify-content: center; }

/* Live runs the internal-systems card headings at 700, not 800. */
.page--projects .grid--3 .card :is(h2, h3) { font-weight: 700; }

/* Live constrains the projects title to a 659px column, so it wraps there. */
.page--projects .section--hero h1 { max-width: 659px; }

/* --- About page: live's block structure --------------------------------- */
/* Live lays /about/ out as four blocks inside the 1290 container, measured
   2026-08-21:
     1. a 1215 column: title, intro copy, then a centred 599x120 logo
     2. a two-column row, vertically centred: 630 image | 605 copy (gap 55)
     3. a centred 366x229 figure
     4. a centred 749 column for "What We Build Now"
   Ours previously ran one full-width column with both images floated right. */
.about-intro { max-width: 750px; margin-inline: auto; }
/* Requested 2026-08-23: logo at half its previous 599px, and two-thirds less
   space between it and "The Early Years" (221px -> 74px). */
.about-logo { display: block; margin: 17px auto 0; width: 300px; max-width: 100%; height: auto; }

.about-split {
  display: grid;
  grid-template-columns: 630fr 605fr;
  gap: 55px;
  align-items: center;
  margin-top: 74px;
}
.about-split__media img { width: 615px; max-width: 100%; height: auto; }
.about-split__body > h2:first-child { margin-top: 0; }

.about-figure {
  display: block;
  margin: 60px auto;
  width: 366px;
  max-width: 100%;
  height: auto;
}

.about-narrow { width: 750px; max-width: 100%; margin-inline: auto; }
.about-narrow > h2:first-child { margin-top: 0; }

@media (max-width: 999.98px) {
  /* Live collapses to a single centred column below the tablet breakpoint. */
  .about-split { grid-template-columns: 1fr; gap: 24px; margin-top: 32px; }
  .about-narrow { width: 100%; }
  .about-figure { margin: 32px auto; }
}

/* --- Founder page: live's block structure ------------------------------- */
/* Live measured 2026-08-21: a 1215 column holding the heading pair, then a
   608 | 608 row (copy left, portrait right), a centred 232x145 figure, and a
   402 | 832 row (image left, copy right) vertically centred.
   Our founder copy is longer than live's -- deliberately rewritten and
   fact-checked -- so the extra sections continue in the 1215 column. The
   column structures themselves match live. */
/* The portrait rows occupy exactly the same 750px space as every paragraph on
   the page, and split THAT space into two columns internally -- picture in with
   the copy, not beside the column, above it or below it. The outer edges never
   move, so the page holds one width from top to bottom. */
.founder-split,
.founder-row {
  display: grid;
  gap: 30px;
  align-items: center;
  max-width: 750px;
  margin-inline: auto;
}
.founder-split { grid-template-columns: 1fr 220px; }   /* copy left, portrait right */
.founder-row   { grid-template-columns: 220px 1fr; }   /* portrait left, copy right */
.founder-split__body  { grid-column: 1; }
.founder-split__media { grid-column: 2; }
.founder-row__media   { grid-column: 1; }
.founder-row__body    { grid-column: 2; }
/* The copy is already 750 from .page--wide; auto margins would re-centre it
   inside its own grid cell and knock it off the shared left edge. */
.founder-split__body > *,
.founder-row__body > * { margin-inline: 0; max-width: none; }
.founder-split__media { text-align: center; }
/* Live renders this 300x300 (measured 2026-08-22 at 1920 and 1600, directly and
   in an iframe). The source file is a 400x400 square and byte-identical to ours,
   so crop rather than squash. An earlier note here claimed live used 300x400 —
   it does not, and that made our headshot 100px too tall. */
.founder-split__media img {
  width: 100%;
  max-width: 240px;
  height: 300px;
  object-fit: cover;
  object-position: center top;
  margin-inline: auto;
}

.founder-figure {
  display: block;
  margin: 40px auto;
  width: 232px;
  max-width: 100%;
  height: auto;
}


.founder-row__media { text-align: center; }
.founder-row__media img { width: 100%; max-width: 240px; max-width: 100%; height: auto; margin-inline: auto; }

@media (max-width: 999.98px) {
  .founder-split,
  .founder-row { grid-template-columns: 1fr; gap: 24px; margin-top: 24px; }
  .founder-figure { margin: 28px auto; }
}

/* --- Narrow-width collapses for the new column structures ---------------- */
/* These grids are declared later in the file and at higher specificity than
   the original collapse rules, so they were overriding them and holding
   multi-column layouts on phones. Collapse them explicitly at live's
   breakpoint. */
@media (max-width: 999.98px) {
  .page--projects .section--projects .grid--2 { grid-template-columns: 1fr; }
  .feature-row .grid--3 { grid-template-columns: 1fr; }
  .section--projects .grid--2 { grid-template-columns: 1fr; }
}

/* --- Card icons --------------------------------------------------------- */
/* Live's three "What We Build" cards each open with a 60px green disc holding
   a 20px white glyph, inset 25px from the card edge. Paths copied from live's
   own markup rather than substituted with lookalikes. */
.card-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 60px;
  height: 60px;
  border-radius: 50%;
  background: var(--green);
  margin-bottom: 20px;
}
.card-icon svg { width: 20px; height: 20px; fill: #fff; display: block; }

/* Live varies card padding by card type; derived from its measured content
   insets: 254-wide feature cards 25, 630-wide project cards 20. (The 410-wide
   grid cards at 30 and the 437 wide card at 40 already match.) */
.feature-row .grid--3 .card { padding: 25px; }
.page--projects .project { padding: 20px; }

/* --- Vertical rhythm: live's hero and section spacing -------------------- */
/* IMPORTANT: live is currently served to us with a logged-in WordPress admin
   bar, which pushes everything down 32px. The values below are live's
   LOGGED-OUT positions, i.e. measured minus 32. Do not re-derive them from a
   raw screenshot without subtracting the bar.
   Live's h1 sits at a different height on every page, so hero padding is
   per-page. Our header is 128px tall, so padding-top = target - 128. */
.page--home    .section--hero { padding-top: 112px; }  /* h1 at 240 */
.page--about   .section--hero { padding-top: 112px; }  /* h1 at 240 */
.page--founder .section--hero { padding-top: 22px; }   /* h1 at 150 */
.page--projects .section--hero { padding-top: 212px; } /* h1 at 340 */

/* Live's homepage hero closes at 60, and its "What We Build" row carries
   margin 60 top / 100 bottom rather than a full 100/100 section pad. */
.page--home .section--hero { padding-bottom: 60px; }
.page--home .section--hero + .section { padding-top: 60px; padding-bottom: 100px; }

@media (max-width: 999.98px) {
  /* Collapse the bespoke hero padding on narrow screens. */
  .page--home .section--hero,
  .page--about .section--hero,
  .page--founder .section--hero,
  .page--projects .section--hero { padding-top: 48px; padding-bottom: 48px; }
  .page--home .section--hero + .section { padding-top: 48px; padding-bottom: 48px; }
}

/* Live bottom-aligns BOTH columns of this row (align-items:flex-end), so the
   shorter left column sits 50px down. An earlier pass concluded otherwise --
   that reading came from measuring live while its lazy-loaded card image had
   not yet loaded, which left the right column artificially short. Always force
   live's images to load before measuring its vertical rhythm. */
.feature-row { align-items: end; }

/* Live's hero cards: "Quality over Quantity" 281x83 at 20px padding,
   "User First" 281x162 at 25px. Ours ran 116 and 192 on 25/40 and 40. */
.hero-cards .card--compact { padding: 20px; }
.card-stack .card { padding: 25px; }

/* --- Homepage hero column: live's internal spacing ----------------------- */
/* Live's left hero column is 626 tall; ours was 513, which pushed nothing
   down on its own but left the two sites out of step further down the page.
   Measured against live (logged-out coordinates):
     h1 break before "Not to Distract."  50px  (ours 0.55em = 30)
     "Founded by ..." line               20/33 (ours 16/26)
     button row bottom margin            70px */
.h1-second { margin-top: 50px; }
.split--top p:not(.lead) { font-size: 20px; line-height: 33px; }
.split--top .btn-row { margin-bottom: 70px; }

/* `.section` carries margin-bottom: var(--section) on top of its padding, so
   each homepage gap ran 100px wider than live's. Live spaces these with
   padding alone: hero closes at 60 and the next row opens at 60; the row after
   that opens at 100. Keep the final section's margin so the footer still
   clears. */
.page--home .section--hero,
.page--home .section--hero + .section { margin-bottom: 0; }

/* Live's section-head: the heading wraps to two lines (105 tall) and the lead
   is 795 wide, starting 20px below the heading's top. Our self-hosted Manrope
   renders "Platforms and Projects" at 394px where live's renders past 405, so
   live wraps and we did not; capping the heading reproduces live's two-line
   break rather than leaving a visible one-line-vs-two difference. */
.section-head > h2 { max-width: 390px; }
.section-head > .lead { max-width: 795px; margin-top: 20px; }

/* Live's section-head row is 139 tall -- its lead carries a 20px bottom margin
   -- and the card grid below it opens at 50, not 40. */
.section-head > .lead { margin-bottom: 20px; }
.section--projects .grid--2 { margin-top: 50px; }

/* Live opens the project cards 196px below the h1 baseline; ours ran 250. */
.page--projects .section--hero { padding-bottom: 46px; }

/* Live sizes this one image smaller than the other project images: 413x232
   against the shared 473. It is the only project image live insets further. */
.project img[src*="finance-abridged2"] { max-width: min(413px, 100%); }

/* --- Footer: separator removed, transition softened --------------------- */
/* Requested 2026-08-23: drop the light green rule above the footer, and ease
   the join between the last body section and the footer. The fade is a
   pointer-events:none overlay sitting above the footer, so it never
   intercepts clicks on the last section's links. */
.site-footer {
  border-top: 0;
  position: relative;
}
/* .site-footer::before used to paint a 140px transparent-to-black gradient
   ending exactly at the footer top edge. Because the texture band below it is
   unaffected, the gradient reaching full black there produced a hard seam --
   the second of the two horizontal lines above the footer. The band now masks
   itself in (see ::after), so this layer is unnecessary and was harmful. */


/* --- Links: green always, underlined only on hover ---------------------- */
/* Requested 2026-08-23. This deliberately departs from live, which underlines
   prose links at rest and drops the underline on hover. Nav, footer and button
   links keep their own treatments. */
/* :not(.btn) matters. Without it these rules outrank .btn--primary and paint
   green text on a green button -- invisible. Buttons keep their own colours. */
/* WCAG 1.4.1: green on the body grey is ~2.2:1, under the 3:1 that would let
   colour carry the link distinction unaided. Scoped to running text inside
   <main>, so header/footer nav and .btn calls-to-action stay undecorated.
   Not .prose alone -- the home hero sits outside it and has an inline link. */
main p a:not(.btn),
main li a:not(.btn) {
  color: var(--green);
  text-decoration: underline;
  /* A hairline, set away from the baseline. The browser default rule is thick
     enough at 16-20px that an underlined link reads as bolder than the text
     around it, which is not the intent -- 1.4.1 only needs a non-colour cue. */
  text-decoration-thickness: 1px;
  text-decoration-skip-ink: auto;
  text-underline-offset: 0.2em;
}
main p a:not(.btn):hover,
main li a:not(.btn):hover { color: var(--green); text-decoration: underline; }

/* Button labels stay white in every state, on any background. */
.btn--primary,
.btn--primary:hover,
.btn--outline:hover { color: #fff; }

/* --- About: single column, left aligned --------------------------------- */
/* Requested 2026-08-23: logo up 25% (300 -> 375), the two-column split
   dropped, and "The Early Years" centred. */
.about-logo { width: 375px; }
.about-split { display: block; }
.about-split__media { display: none; }
.about-split__body { text-align: left; }
/* No max-width override here: the h2 must sit in the same 750 column as the
   copy under it, or it hangs 270px left of everything else on the page. */

/* --- Project card artwork: darkened so copy can sit on top -------------- */
/* Requested 2026-08-23. Earlier attempts moved the copy off the artwork
   (bands, then a two-column split). Simpler and better looking: keep the
   artwork full-bleed and lay a flat dark filter over it, then put the words on
   top. The filter is a gradient layered ABOVE the image in the same ::before,
   so it needs no extra element and cannot fall out of sync with the artwork.
   Strength is per-card: the photo is busy and bright, the graphics are not. */
.card--art-youtube::before {
  background-image:
    linear-gradient(rgba(0, 0, 0, 0.62), rgba(0, 0, 0, 0.62)),
    url('/images/home-about-section-image-1-1.webp');
}
.card--art-niche::before {
  background-image:
    linear-gradient(rgba(0, 0, 0, 0.45), rgba(0, 0, 0, 0.45)),
    url('/images/home-about-section-image-5.webp');
}
.card--art-independent::before {
  background-image:
    linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)),
    url('/images/home-about-section-image-4-1.webp');
}

/* --- AI Publishing card: graphic on top, copy beneath ------------------- */
/* Kept from the earlier pass at Todd's request -- this one reads better as a
   band than as a darkened backdrop, so it gets no filter. The section prefix
   is needed because `.section--projects .card { padding: 30px }` outranks a
   bare .card--art-* selector. */
.section--projects .card--art-publishing { padding-top: 210px; }
.card--art-publishing::before {
  inset: 0 0 auto 0;
  height: 190px;
  background-size: contain;
  background-position: 50% 0;
}

@media (max-width: 999.98px) {
  .section--projects .card--art-publishing { padding-top: 165px; }
  .card--art-publishing::before { height: 150px; }
}

/* --- "Built for Clarity and Structure": artwork flush to the card top ---- */
/* Requested 2026-08-23: the green ball should meet the top edge of the card
   rather than floating below the card's padding. The image breaks out of that
   padding with negative margins, so the values must track the card padding at
   each breakpoint (40px desktop, 24px/16px under 640). overflow:hidden lets
   the card's 12px radius clip the artwork's top corners. */
.card--plain { overflow: hidden; }
.card--plain img {
  max-width: none;
  width: calc(100% + 80px);
  margin: -40px -40px 24px;
  border-radius: 12px 12px 0 0;
}

@media (max-width: 640px) {
  .card--plain img {
    width: calc(100% + 32px);
    margin: -24px -16px 18px;
  }
}


/* --- Footer texture ------------------------------------------------------ */
/* footer-background.jpg moved off `body` and onto a band at the foot of the
   page. As a body background at `contain` it painted 1217px tall, so on
   /about/, /contact/ and /founder/ -- where our single .section--hero holds the
   whole page, unlike live which splits it into rows -- it overlapped the hero
   backdrop by ~807px. Two diagonal stripe textures crossing read as doubled
   stripes. A fixed 400px band clears every hero on every page.
   `cover` keeps the stripe angle; scaling the height instead would skew it. */
.site-footer::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 400px;
  z-index: -1;
  pointer-events: none;
  background: url('/images/footer-background.jpg') 50% 100% / cover no-repeat;
  /* Without this the band began on a hard horizontal edge 82px above the
     footer -- the first of the two lines. Fading it in over the top half
     keeps the stripe angle and removes the seam. */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 55%);
  mask-image: linear-gradient(to bottom, transparent 0%, #000 55%);
}
