/* THREE BEATS — theadamthomas.com theme
   Built by ghost-webdev, 2026-09-12, against ops/BRIEF.md revision 8.
   SYLLABUS (the previous direction) is retired; nothing here is inherited
   from that stylesheet except the DO-NOT-REGRESS link rule and the WCAG
   colour corrections, both called out where they occur.

   Table of contents
   1. Tokens (spacing, type, grid) — two breakpoints, switch at 900px
   2. Colour (ops/BRIEF.md §5 — closed palette, do not add colours)
   3. Fonts
   4. Reset + base typography
   5. Grid primitives: .block, the step-out beat system
   6. Links, buttons, forms, focus, selection
   7. Masthead
   8. Footer
   9. Ghost cards: Callout / Signup / Header / Image / Gallery
   10. Post/page body typography (p, h2, h3, blockquote, lists, pre, table)
   11. Article & newsletter rows, month archive
   12. Utility pages, build-guard flag, placeholders
   13. Motion + reduced motion
*/

/* 1. Tokens
/* ---------------------------------------------------------- */
:root {
    /* type — SIX sizes, and no others (ops/BRIEF.md §4 Scale). Values
       below are the Newsreader table, 2026-09-14 — sizes rose across the
       board on the move from Poppins/Roboto Slab, per Adam's Option B
       decision (ops/DECISIONS.md). --t-display carries a THIRD tier no
       other token has: it holds at 2.5rem (40px) from 0 up through
       1023px, and steps to 3.75rem (60px) only at >= 1024px (the
       min-width: 1024px override below) — NOT at the usual 900px switch.
       That extra step exists because Home's h1 measures 753.5px at 60px,
       27px over its 726px budget if it set that large as early as 900px;
       staying at 40px through 1023px keeps every live display heading on
       one line with room to spare (ops/BRIEF.md §4 "Display budgets"). */
    --t-meta: 0.8125rem;
    --t-body: 1.25rem;
    --t-sub: 1.5rem;
    --t-step: 1.875rem;
    --t-head: 2.5rem;
    --t-display: 2.5rem;

    /* Control labels (button labels and Home's Work link): Poppins 700 at
       1.125rem, fixed at every breakpoint — the one size outside the
       six-size scale (ops/BRIEF.md §4 Scale). */
    --t-control: 1.125rem;

    /* spacing — four values, and no others (ops/BRIEF.md §3). --space-1
       rises from 20 to 24px (critique-home-05 pass, ruling 2: paragraph
       spacing) — it is still the same token everywhere else that used it,
       not a new one. --space-turn rises from 80 to 96px (ruling 3) and
       formalises pass 3's ad-hoc exception: the turn from the last beat-2
       element into the landing band, the band's own top padding, form ->
       footer line, and on Home, the essay -> proof-and-bio turn.
       --space-3 separates sections, the light-ground footer, and now also
       (Home only) proof-and-bio -> the catalogue. */
    --space-1: 1.5rem;
    --space-2: 2.5rem;
    --space-3: 10rem;
    --space-turn: 6rem;

    /* The tight offset (ops/BRIEF.md §3): a caption below its photograph,
       and inside a catalogue row, title -> excerpt -> meta line. One of
       the two stated exceptions to the four-value spacing scale — not a
       fifth spacing token, so it lives outside the --space-* naming. */
    --offset-tight: 0.5rem;

    /* grid (ops/BRIEF.md §2). One column, one left edge — the step-out
       axis and its --unit token are retired (2026-09-13 critique-home-02
       re-ruling; ops/DECISIONS.md). --block is the ONE measure now (40rem,
       2026-09-13 critique-home-04 pass, ruling 3): every element —
       headings, lede, body, quotes, photographs, rows, band content — sits
       on it. Pass 3's separate --measure (a narrower 38rem reading column
       inside a wider 44rem --block) is retired; there is one right edge
       again. */
    --block: 40rem;

    /* The apparatus gutter (ops/BRIEF.md §2 Grid; Adam's ruling of
       2026-09-20, "apparatus moves to the side that has the width"): body
       ranges left, apparatus (captions, attributions, meta lines, the
       catalogue label, the Work link, date ranges, row thumbnails, lead-ins)
       ranges RIGHT of the column at >= 1280px only. 40rem column + 2rem gap
       + 14rem gutter = 56rem, landing exactly on the display edge the nav,
       the opening photograph and the close's hairline already declare.
       Only two tiers now: the gutter at >= 1280px, and none below it. The
       old 1024-1279px 8rem LEFT rail is retired outright, not mirrored to
       the right — it collided with display headings at that width and was
       the tier captions wrapped four lines deep in (review 19). Below
       1280px every apparatus item sits on its own line, right-aligned to
       the column's own right edge (built per-selector, not a token). */
    --gutter-width: 14rem;
    /* Baseline offsets for 13px apparatus beside larger type (round 2,
       measured by CDP on Newsreader/Poppins at 1920): the distance from a
       13px line's first baseline to the first baseline of a --t-head
       (40px, lh 1.1) or --t-sub (24px, lh 1.2) line, both top-aligned. */
    --baseline-head: 16px;
    --baseline-sub: 8px;
    --baseline-body: 9px;
    --baseline-quote: 8px;
    --descent-meta: 2px;
    --baseline-lead: 8px;
    --baseline-lead-p: 10px;
    --baseline-control: 13px;
    --baseline-signup: 14px;
    --baseline-label: 10px;
    --baseline-verb: -7px;
    --baseline-verb-step: 0px;
    --baseline-word: 15px;
    --baseline-stamp: 33px;
    --baseline-lede: 11px;
    --baseline-price: -1px;
    --baseline-field: 16px;
    --baseline-prefix: 8px;
    --baseline-offer: 10px;
    --baseline-caption: 0px;
    --gutter-gap: 2rem;

    /* Newsreader sets all site content; Poppins 700 is the brand's voice
       in the chrome only — the logo, both navs, the copyright, the
       catalogue label, the Work link and button labels (Adam's 2026-09-14
       decision, Option B; ops/BRIEF.md §4 Families). Roboto Slab is
       retired outright — its files, @font-face rules and preloads are
       gone (see §3 below). */
    --font-title: 'Poppins', 'Helvetica Neue', Arial, sans-serif;
    --font-body: 'Newsreader', 'Iowan Old Style', 'Palatino Linotype', Georgia, serif;
    --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

    /* Koenig's editor preview expects these two variables to exist so its
       WYSIWYG matches the front end. The pairing is fixed by the brand
       book (ops/BRIEF.md §4 Families, inherited) — there is no font
       picker on this theme, so both point at the same fixed families
       declared above rather than exposing a choice. */
    --gh-font-heading: 'Poppins', 'Helvetica Neue', Arial, sans-serif;
    --gh-font-body: 'Newsreader', 'Iowan Old Style', 'Palatino Linotype', Georgia, serif;

    font-synthesis: none;
    /* opsz follows the computed font-size automatically — 13px text uses
       opsz 13, a 60px heading uses opsz 60. No element sets
       font-variation-settings by hand (ops/BRIEF.md §4 Families). */
    font-optical-sizing: auto;
}

@media (max-width: 899px) {
    :root {
        --t-body: 1.1875rem;
        --t-sub: 1.375rem;
        --t-step: 1.625rem;
        --t-head: 2rem;
        --space-3: 6rem;
        --space-turn: 3rem;
    }
}

/* --t-display's own, later breakpoint (ops/BRIEF.md §4 Scale) — see the
   long comment on its declaration above. This must be a separate,
   later-declared query from the max-width: 899px one above so it wins on
   source order once both conditions are true (both are same-specificity
   :root rules). */
@media (min-width: 1024px) {
    :root {
        --t-display: 3.75rem;
    }
}

/* The 1024-1279px 8rem gutter tier is retired (ops/BRIEF.md §2 Grid,
   Adam's ruling of 2026-09-20): only two tiers exist now, the >= 1280px
   gutter above and no gutter at all below it. Do not reintroduce a
   min-width:1024px/max-width:1279px override here. */

/* 2. Colour — closed palette. Every colour used anywhere below must be one
   of these seven. The brand book's other four marks (the mid orange, the
   dark maroon, the light purple used only in the logo art, and the book's
   WRITTEN purple, which the logo file itself does not actually render)
   must never appear as literal hex values anywhere in this file
   (ops/BRIEF.md "What this is NOT — Palette").

   2026-09-13 critique-home-05 pass, ruling 5: the accent moves to the
   purple the logo file actually renders everywhere ("one purple accent,
   the logo's own" — measured from the file, not the brand book's written
   swatch). The theme's previous hover fill is deleted outright; the
   theme's previous accent moves from "the fill" to "the hover fill", its
   only remaining job. Neither superseded hex appears anywhere in this
   file any more, including in comments — `grep -c` for either against
   this file must return 0 (ops/BRIEF.md §12). */
/* 2026-09-14 close-B pass: the hover fills (the old --c-free-hover,
   --c-commercial-hover) are retired outright, along with every filled
   control — ops/DECISIONS.md, Ruling 1, "Retired colours and roles".
   Five colours remain in the theme's CSS (ops/BRIEF.md §5, §12 item 9). */
:root {
    --c-ground: #f5f7f5;
    --c-ink: #2e2926;
    --c-link-underline: #5e48ca;
    --c-free: #5e48ca;
    --c-commercial: #a8583a;
    --c-placeholder: rgba(46, 41, 38, 0.7);
}

/* 3. Fonts
/* ---------------------------------------------------------- */
@font-face {
    font-family: 'Poppins';
    src: url('../fonts/poppins-700.woff2') format('woff2');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}
/* Newsreader: variable, Latin subset, wght 400-600, opsz 12-60 (narrowed
   from the file's own 12-72 to fit the 180,000-byte combined ceiling —
   ops/BRIEF.md §4 Families; see the build report for the exact bytes).
   Two files, roman and italic — no separate weight files, since the axis
   itself carries 400/500/600. font-weight is a RANGE on each @font-face,
   which is what lets the variable font respond continuously rather than
   snapping to one instance. */
@font-face {
    font-family: 'Newsreader';
    src: url('../fonts/newsreader-roman.woff2') format('woff2');
    font-weight: 400 600;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Newsreader';
    src: url('../fonts/newsreader-italic.woff2') format('woff2');
    font-weight: 400 600;
    font-style: italic;
    font-display: swap;
}
/* Roboto Slab leaves the site — its three @font-face rules, its files and
   its preloads are removed (ops/BRIEF.md §4 Families). No other
   @font-face: JetBrains Mono, EB Garamond and Inter are also removed from
   the build. Code uses the system mono stack, --font-mono, declared in
   §1. */

/* 4. Reset + base typography
/* ---------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
/* overflow-x: clip is retired (2026-09-14 close-B pass, ops/DECISIONS.md
   Ruling 4): it existed only to guard the landing band's full-bleed
   breakout, which is gone with the band. Nothing on the site bleeds past
   the grid any more, so horizontal overflow must be zero without any
   clip guard — verified with scrollWidth === clientWidth at every
   width. */
html { -webkit-text-size-adjust: 100%; font-size: 16px; }
body, h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd, ul, ol, table {
    margin: 0;
}
ul, ol { padding: 0; list-style: none; }
img { max-width: 100%; display: block; }
button, input { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }
table { border-collapse: collapse; width: 100%; }

body {
    font-family: var(--font-body);
    font-weight: 400;
    font-size: var(--t-body);
    line-height: 1.6;
    color: var(--c-ink);
    background: var(--c-ground);
}

/* Generic fallback for any heading not reached by a more specific
   selector below (e.g. a heading inside raw HTML content). All site
   content is Newsreader (ops/BRIEF.md §4 Families) — the chrome's Poppins
   never applies to a content heading, only to nav/copyright/catalogue
   label/buttons/Work link, styled separately, below. */
h1, h2, h3, h4, h5, h6 {
    font-family: var(--font-body);
    font-weight: 500;
    line-height: 1.15;
}
/* h4 and below render as h3 (ops/BRIEF.md §4 Scale) — Koenig only emits
   h2/h3 from its own heading picker, but raw HTML cards can carry h4-h6.
   h3 (and h4-h6): Newsreader 600 at --t-body (ops/BRIEF.md §4 Scale). */
h4, h5, h6 {
    font-family: var(--font-body);
    font-weight: 600;
    font-size: var(--t-body);
    line-height: 1.4;
}

/* Emphasis (ops/BRIEF.md §4 "Emphasis" — Newsreader has a real italic, so
   this is no longer the synthesis-avoidance workaround Roboto Slab
   needed). Never colour, underline, uppercase or small caps. em/i/titles
   of works are set in the italic file AT THE SURROUNDING WEIGHT (no
   font-weight declared here, so it inherits) — except inside an italic
   quote, where em reverts to roman so the emphasis still shows. strong/b
   is 600: 700 is not in the loaded weight range (400-600), so 600 is the
   correct, non-synthesised value, and it stays 600 in a context already
   at 600 (no synthesis either way). */
em, i, cite {
    font-family: var(--font-body);
    font-style: italic;
}
blockquote em, blockquote i, blockquote cite {
    font-style: normal;
}
strong, b {
    font-family: var(--font-body);
    font-weight: 600;
    font-style: normal;
}

/* No uppercase anywhere on this site (ops/BRIEF.md §4 Scale). The meta
   tier is sentence case.

   TWO metadata styles, by role, composed once each and never re-declared
   per component (2026-09-13 critique-home-03 pass, GAP 4 — this retires
   the single Poppins Bold metadata style from critique-home-02: "bold 13px
   reads as an interface label" on a quoted person's attribution).

   INTERFACE: both navs. Poppins Bold, tracked. The copyright moves to
   EDITORIAL, below (2026-09-14 pass-8, Ruling 7: "a non-link should not
   match the nav's link weight"). */
.masthead-nav .nav-link,
.footer-nav-primary,
.footer-nav,
.build-guard-flag {
    font-family: var(--font-title);
    font-weight: 700;
    font-size: var(--t-meta);
    line-height: 1.4;
    letter-spacing: 0.01em;
}
/* EDITORIAL: captions, attributions, dates, framework names, meta lines,
   and now the footer copyright (2026-09-14 pass-8, Ruling 7). Newsreader
   400, no tracking. figcaption previously inherited the body's Roboto
   Slab at the wrong size — critique-home-02 "fixed" it into Poppins Bold,
   which was also wrong; this is the corrected, final home for it. A
   quoted person's name goes to 600 where it's built (the tier-1 unit and
   tier-2 attribution, below), not here. */
.meta,
.article-meta,
.issue-meta,
.home-row-meta,
.article-row-meta,
.newsletter-month-range,
.photo-caption,
.footer-copyright,
figcaption {
    font-family: var(--font-body);
    font-weight: 400;
    font-size: var(--t-meta);
    line-height: 1.4;
}

::selection { background: var(--c-link-underline); color: var(--c-ground); }

/* 5. Grid primitives — the step-out beat system (ops/BRIEF.md §1–2)
/* ---------------------------------------------------------- */
.block {
    width: 100%;
    max-width: var(--block);
    margin-inline: auto;
}
@media (max-width: 899px) {
    .block { padding-inline: 1.25rem; }
}
/* THE GRID IS CENTRED AS ONE UNIT at >= 1280px (Adam's ruling,
   2026-09-21, "Centre the block"; ops/BRIEF.md §2). The 56rem unit —
   40rem column + 2rem gap + 14rem gutter — is what sits in the middle of
   the viewport, not the 40rem column alone, so the page no longer rides
   8rem right of centre. Every .block (masthead, main, footer) shares this
   left edge; everything that reaches the display edge or the gutter is
   measured from the column's left edge, so none of it moves relative to
   the column. 50% is the parent's width, which is the full viewport for
   every .block on the site. */
@media (min-width: 1280px) {
    .block {
        margin-left: calc(50% - (var(--block) + var(--gutter-gap) + var(--gutter-width)) / 2);
        margin-right: auto;
    }
}

main.block { display: block; }

/* Section → section: --space-3 (ops/BRIEF.md §3). Masthead → first beat is
   --space-2 instead (2026-09-12 critique ruling, ops/DECISIONS.md): that
   gap equals the logo's own clear space, because the masthead is chrome,
   not a section. Only the FIRST top-level beat of a template gets its
   value from its position after the masthead; a nested `.section` (a
   post's second+ Ghost-card section) gets --space-3 as its own entry gap.
   The footer's own margin is --space-turn now, not --space-3 (2026-09-14
   close-B pass, ops/BRIEF.md §6 Footer, ops/DECISIONS.md Ruling 2) — it
   sits below the close's control row (or the last beat, on a page with
   no close), on the page's own ground; there is no more band for it to
   join. */
main.block > .beat-opening:first-child {
    margin-top: var(--space-2);
}
main.block > .section {
    margin-top: var(--space-3);
}
.site-footer { margin-top: var(--space-turn); }

/* Beat → beat: --space-2 (ops/BRIEF.md §3). */
.beat + .beat,
.beat-opening + .content,
.content + .beat {
    margin-top: var(--space-2);
}

/* One column, one left edge (ops/BRIEF.md §2; 2026-09-13 critique-home-02
   re-ruling). The step-out axis, its --unit token and every negative
   margin that widened a closing card back out to a second axis are
   retired — see ops/DECISIONS.md, "the step-out is RETIRED". Every beat
   renders at .block's own left edge with no extra indent. The only
   remaining exception is the landing band (§9 below), which breaks out
   to the full viewport width on purpose, as the page's one field. */

/* Inside a beat: heading -> text, paragraph -> paragraph, photo ->
   caption, row -> row: --space-1. This is the default for everything
   inside .content; the section-opening h2 and the beat-3 cards override
   it below with more specific selectors. */
.content > * + * {
    margin-top: var(--space-1);
}
.beat-opening > * + * { margin-top: var(--space-1); }
.beat-close > * + * { margin-top: var(--space-1); }

/* Below 1280px, an article's or issue's meta line is right-aligned, above
   the title (ops/BRIEF.md §7 Article/Issue). ".article-meta"/".issue-meta"
   already get their face, size and weight from the shared EDITORIAL rule
   in §4 — this only adds the alignment. */
.article-meta,
.issue-meta {
    text-align: right;
}
/* An article's or issue's meta line is apparatus (ops/BRIEF.md §7 Article/
   Issue, §2 "level with its title"): at >= 1280px it hangs in the RIGHT
   gutter (Adam's ruling, 2026-09-20), level with the post title, via true
   `position: absolute` against ".beat-opening" (already the meta line's
   and the title's shared parent in post.hbs — no new wrapper needed).
   Absolute, not a negative-margin pull, for the same reason as the
   catalogue row's own meta line: the meta line PRECEDES the title in the
   DOM, so a negative margin on the meta itself has nothing after it to
   measure against, and the title's own height is variable (it wraps).
   Taking the meta out of flow makes the title ".beat-opening"'s first
   in-flow child, so it starts exactly at the top the meta needs to level
   with, regardless of either element's own height.
   `left: calc(40rem + gap)`, not `right: calc(100% + gap)` — ".beat-opening"
   is exactly the 40rem column, so its left edge is the column's own left
   edge; the literal 40rem is correct here the same way it is for every
   other right-gutter selector below (see the handoff's "40rem, not 100%"
   note). */
@media (min-width: 1280px) {
    .article-body > .beat-opening,
    .issue-article > .beat-opening {
        position: relative;
    }
    .article-body > .beat-opening > .article-meta,
    .issue-article > .beat-opening > .issue-meta {
        position: absolute;
        top: 0;
        left: calc(var(--block) + var(--gutter-gap));
        right: auto;
        width: var(--gutter-width);
        text-align: right;
        margin-top: 0;
    }
    .article-body > .beat-opening > .post-title,
    .issue-article > .beat-opening > .post-title {
        margin-top: 0;
    }
}

/* On a PAGE (Home/Work/About) a body h2 opens the next section:
   --space-3 above it regardless of what precedes it, then --space-1 to
   its own beat-1 paragraph, then --space-2 into beat 2
   (ops/BRIEF.md §6 "the authoring convention"). Scoped to .page-article
   only — an Article or Issue has exactly one section (ops/BRIEF.md §7),
   so an h2 inside its body is an ordinary body heading, not a new
   section; its own --space-2/--space-1 rule lives in §10 below and must
   not be overridden by this one. */
.page-article .content > h2 {
    margin-top: var(--space-3);
}
.page-article .content > h2 + p { margin-top: var(--space-1); }
.page-article .content > h2 + p + * { margin-top: var(--space-2); }

/* Beat 2 -> beat 3: the closing card always follows immediately, so this
   is unconditional, regardless of what precedes it. An outward Callout
   keeps the ordinary --space-2 beat gap; the action (Signup/Header) sits
   on the landing band instead, whose own --space-turn top margin is set in
   §9 below (ops/BRIEF.md §1: "outward --space-2; action --space-turn"). */
.content > .kg-callout-card {
    margin-top: var(--space-2);
}

/* A bare <hr> is a retired device (ops/BRIEF.md §11: "hairline rules as
   structure… rules exist only on inputs and tables"). Ghost's own
   onboarding content ships one; hide it rather than let it render as
   structure it no longer has a job doing. */
.content > hr { display: none; }

/* Photographs range left on the column's left edge, never centred
   (ops/BRIEF.md §2). ".scene-photo" (renamed from ".circle-photo"
   2026-09-13 critique-home-03 pass: Adam's decision retired the circle
   for every scene/room photograph — the article feature photo and the
   article-row thumbnail, its only two uses in this theme's own markup —
   so the shared base class is a plain rectangle now, not a circle; only
   faces (the About portrait, a Ghost image card handled separately in §9)
   stay circles). border-radius: 0 is the sitewide default already (§4
   base), so there is nothing to reset here. */
.scene-photo {
    overflow: hidden;
    flex: 0 0 auto;
}
.scene-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    filter: grayscale(100%) contrast(1.05);
}

/* border-radius: 0 on everything except photographs (full circles) — no
   shadows anywhere (ops/BRIEF.md §2, inherited). */
button, input, .btn { border-radius: 0; box-shadow: none; }

/* 6. Links, buttons, forms, focus, selection
/* ---------------------------------------------------------- */

/* DO NOT REGRESS: link text stays #2e2926. Purple lives ONLY on the
   underline, never the text — the accent on the body ink is 2.23:1 and
   fails WCAG G183 (2026-09-13 critique-home-05 pass, ruling 5: the accent
   hex changed, and so did the exact ratio, but the rule it fails is the
   same one it always failed). Do not "fix" this by making link text
   purple. See ops/BRIEF.md §5 "DO NOT REGRESS". */
a.inline-link,
.content a,
.article-row-title a,
.home-row-title a,
.article-row-meta a,
.home-row-meta a,
.newsletter-issue-title,
.index-cross-link a {
    color: var(--c-ink);
    text-decoration: none;
    border-bottom: 1px solid var(--c-link-underline);
    text-underline-offset: 0.15em;
    padding-bottom: 0.1em;
    transition: border-bottom-width var(--motion-duration) ease-out;
}
a.inline-link:hover, a.inline-link:focus-visible,
.content a:hover, .content a:focus-visible,
.newsletter-issue-title:hover, .newsletter-issue-title:focus-visible {
    border-bottom-width: 2px;
}
/* Row titles carry no underline at rest; they gain one on hover/focus
   only (ops/BRIEF.md §10 Motion, rule 2). Shared by Home's and
   /writing/'s catalogue rows (2026-09-13 critique-home-05 pass). */
.article-row-title a,
.home-row-title a {
    border-bottom-color: transparent;
}
.article-row:hover .article-row-title a,
.article-row-title a:focus-visible,
.home-row:hover .home-row-title a,
.home-row-title a:focus-visible,
.article-row-excerpt-link {
    border-bottom-color: transparent;
}
.article-row-title a:hover, .article-row-title a:focus-visible,
.home-row-title a:hover, .home-row-title a:focus-visible {
    border-bottom-color: var(--c-link-underline);
}
.article-row-excerpt-link:hover, .article-row-excerpt-link:focus-visible {
    border-bottom-width: 0;
}
.newsletter-issue-title.is-current {
    color: var(--c-ink);
    border-bottom: none;
    cursor: default;
}
/* No visited-link style anywhere (ops/BRIEF.md §5). */

/* STANDALONE ARROW LINKS (ops/BRIEF.md §5 Colour, "Standalone arrow
   links"; §2 item 12, ops/DECISIONS.md Ruling 5, 2026-09-14 pass-8): the
   catalogue label, Home's Work link, and every utility-page outward link
   (".outward-link a" — Tag/Author/404's "Read these first"/"Start from
   the front page.", an Issue's member-view next-issue link and its
   month-section's outward link). Poppins 700, ink, NO underline at rest —
   the arrow itself is the link cue — and a 2px accent underline on hover
   and focus, same as every other link's hover state. This must come after
   the base "a.inline-link" rule above (same 0,1,1 specificity: ".outward-
   link a" ties "a.inline-link", since the template's outward-link anchors
   also carry the "inline-link" class) to win on source order, not
   a forced-priority declaration, per this file's own convention. Links INSIDE running text
   keep their 1px underline at rest (unchanged, above) — only these
   apparatus-adjacent, self-contained links drop it. */
.page-home .content .catalogue-label a,
.page-home .content > p:has(+ .catalogue):not(.kg-image-card + p) a,
.page-home > .content > p:has(+ .kg-signup-card) a,
.outward-link a {
    font-family: var(--font-title);
    font-weight: 700;
    color: var(--c-ink);
    text-decoration: none;
    border-bottom: none;
    padding-bottom: 0;
    transition: border-bottom-width var(--motion-duration) ease-out;
}
.page-home .content .catalogue-label a:hover,
.page-home .content .catalogue-label a:focus-visible,
.page-home .content > p:has(+ .catalogue):not(.kg-image-card + p) a:hover,
.page-home .content > p:has(+ .catalogue):not(.kg-image-card + p) a:focus-visible,
.page-home > .content > p:has(+ .kg-signup-card) a:hover,
.page-home > .content > p:has(+ .kg-signup-card) a:focus-visible,
.outward-link a:hover,
.outward-link a:focus-visible {
    border-bottom: 2px solid var(--c-link-underline);
}
/* The arrow itself (ops/BRIEF.md §5): generated on the SAME ::after via
   the content "visible / assistive-tech" pair, so there is one source of
   truth for the glyph and it never enters the accessibility tree. Every
   standalone arrow link gets one, including outward links, which had none
   before this pass.

   "\00a0→" (a NON-BREAKING space), not a plain " →" (2026-09-14 gate-6
   pass-9): a plain space renders fine here, since these anchors are
   ordinary inline elements, but the SAME " →" content on ".btn" and
   Ghost's card buttons (below) rendered with no visible gap at all —
   ".btn" is "display: inline-flex", and the CSS Flexbox spec strips
   collapsible whitespace at the start/end of a flex container's own
   generated inline content, silently eating the leading space from
   THAT ::after only. A non-breaking space is not "collapsible
   whitespace" under that rule, so it survives in both contexts — one
   character choice now renders identically everywhere, per the
   brief's own literal spec (a space before the arrow), rather than
   applying the space via a workaround margin that would only need
   fixing again the next time a differently-laid-out arrow link is
   added. */
.page-home .content .catalogue-label a::after,
.page-home .content > p:has(+ .catalogue):not(.kg-image-card + p) a::after,
.page-home > .content > p:has(+ .kg-signup-card) a::after,
.outward-link a::after {
    content: "\00a0→" / "";
}

:focus { outline: none; }
:focus-visible {
    outline: 2px solid var(--c-link-underline);
    outline-offset: 2px;
}

/* THE ACTION CONTROL (ops/BRIEF.md §5 "The action control is text, not a
   button shape"; ops/DECISIONS.md, the Option-B/close-spec entries,
   Ruling 1) — every filled control on the site is retired outright, along
   with the two superseded hover-fill hexes (removed from :root, above;
   `grep -c` for either against this file must return 0, same standard as
   every other retired colour, ops/BRIEF.md §12).
   ".btn"/".btn-free"/".btn-commercial" are the theme's own native-markup
   classes (partials/components/signup-form.hbs's <button>, and post.hbs's
   commercial <a>); ".kg-signup-card-button"/".kg-header-card-button" are
   Ghost's own classes on the equivalent elements inside a card — one
   shared rule covers both sets, since the visual spec is identical
   either way. A Signup card's submit is always a real
   `<button type="submit">`; a Header card's control is always a real
   `<a>` — this file styles whichever Ghost/the template actually
   rendered, never converting one into the other. */
.btn,
.kg-signup-card-button,
.kg-header-card-button {
    display: inline-flex;
    align-items: center;
    background: transparent;
    border: none;
    border-radius: 0;
    box-shadow: none;
    color: var(--c-ink);
    font-family: var(--font-title);
    font-weight: 700;
    font-size: var(--t-control);
    line-height: 1.6;
    cursor: pointer;
    padding: 0.75rem 0;
    min-height: 44px;
    text-decoration-line: underline;
    text-decoration-thickness: 2px;
    text-underline-offset: 0.75rem;
    opacity: 1;
    transition: text-decoration-thickness var(--motion-duration) ease-out;
}
/* The generated arrow (ops/BRIEF.md §5 "a generated trailing ' →' that
   assistive tech skips") — the same visible/assistive-tech split as every
   other arrow link in this file. "\00a0→" (non-breaking space), not a
   plain " →" — see the long comment on ".outward-link a::after" above
   for why: this file's own flex-laid-out controls silently ate a plain
   leading space here (2026-09-14 gate-6 pass-9, "Get it Tuesday→" had no
   gap while "Work with me →" did, on the exact same generated-content
   rule). */
.btn::after,
.kg-signup-card-button::after,
.kg-header-card-button::after {
    content: "\00a0→" / "";
}
/* Free: purple underline. Paid: orange. The reader code is now carried
   entirely by the underline colour, since there is no fill left to carry
   it (ops/BRIEF.md §5 "Exactly one action control per page, identified by
   its underline colour"). */
.btn-free,
.content .kg-signup-card-button {
    text-decoration-color: var(--c-free);
}
.btn-commercial,
.content .kg-header-card-button {
    text-decoration-color: var(--c-commercial);
}
.btn-free:hover, .btn-free:focus-visible,
.content .kg-signup-card-button:hover, .content .kg-signup-card-button:focus-visible,
.btn-commercial:hover, .btn-commercial:focus-visible,
.content .kg-header-card-button:hover, .content .kg-header-card-button:focus-visible {
    text-decoration-thickness: 3px;
}

/* Every email input on the site is a ruled field now, not a filled one —
   there is no more ink ground to read the fill against (ops/BRIEF.md §5
   "The close's input"). */
input[type="email"] {
    background: transparent;
    border: none;
    border-bottom: 1px solid var(--c-ink);
    border-radius: 0;
    height: auto;
    padding: 0.75rem 0;
    color: var(--c-ink);
    font-family: var(--font-body);
    font-weight: 400;
    font-size: var(--t-body);
    line-height: 1.6;
}
input[type="email"]::placeholder {
    color: var(--c-placeholder);
}
input[type="email"]:focus-visible {
    border-bottom: 2px solid var(--c-link-underline);
    outline: 2px solid var(--c-link-underline);
    outline-offset: 4px;
}

/* The native-markup signup form (post.hbs's theme-rendered asks, via
   partials/components/signup-form.hbs) — input and submit on one
   baseline, --space-1 apart, matching the Ghost-card equivalent
   (ops/BRIEF.md §5). Below 900px they stack, submit --space-1 under a
   full-width input.

   flex-wrap: wrap (caught in review with a real screenshot, not just
   computed styles): ".signup-form-error" is a third flex child with
   `flex-basis: 100%`, present in the DOM even when empty (Ghost's own
   markup, not conditionally rendered). With the default `nowrap` this
   file's earlier draft used, that 100%-basis item competed for space on
   the SAME row as the input and button — an invisible but real flex
   item — and squeezed both down far below their own bases, wrapping the
   button's own text onto two lines. `flex-wrap: wrap` lets the error
   paragraph fall to its own new line instead (only visible once Ghost's
   JS adds an ".error" state class), leaving the input and button the
   full row to themselves. */
.signup-form {
    display: flex;
    flex-wrap: wrap;
    /* flex-end, not baseline (2026-09-14 gate-6 pass-9) — the field's
       rule is its own border-bottom, sitting exactly at its box's own
       bottom edge; the submit's rule is a text-underline offset from ITS
       baseline. Two different browser-computed baselines (a form
       control's own heuristic vs. a text button's true text baseline)
       left the two rules at visibly different heights even though both
       elements individually followed the brief's own literal spec
       (0.75rem padding, 0.3em underline offset). Bottom-aligning the two
       boxes removes that baseline-heuristic variable entirely, so only
       the button's own underline-offset (tuned below) needs to close the
       remaining, much smaller, fixed gap. */
    align-items: flex-end;
    gap: var(--space-1);
}
.signup-form input[type="email"] { flex: 1 1 16rem; min-width: 0; }
@media (max-width: 899px) {
    .signup-form {
        flex-direction: column;
        align-items: flex-start;
    }
    .signup-form input[type="email"],
    .signup-form .btn {
        width: 100%;
    }
}
.signup-form-error {
    flex-basis: 100%;
    font-family: var(--font-body);
    font-weight: 400;
    font-size: var(--t-meta);
    color: var(--c-ink);
    text-align: left;
}

.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
}

/* 7. Masthead
/* ---------------------------------------------------------- */
.masthead {
    padding-top: var(--space-2);
}
/* The masthead sits on .block's own left edge, the same edge every beat
   and the band share (2026-09-13 critique-home-02 re-ruling: the inner/
   outer axis is retired). Nav keeps justify-content: space-between, so it
   stays right-aligned to the block's own right edge. */
.masthead-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-1);
}
/* The wordmark now renders at every width (Adam's ruling, 2026-09-20) —
   previously the mark alone (39px) swapped in below 900px, leaving ample
   room; now mark + wordmark (about 220px) plus the nav's own three
   --space-2-separated items (about 195px, unchanged) no longer both fit
   in the 360px column at 400px, measured with a real
   getBoundingClientRect() check: 455px scrollWidth against a 400px
   viewport. No hamburger is ever an option (ops/BRIEF.md §6), and none
   of the type sizes or the nav's own --space-2 item gap are mine to
   shrink — both are specified. Letting the nav wrap onto its own line
   under the logo row is the one purely mechanical fix available: no
   token changes, nothing hidden, still three words with no hamburger,
   and the wordmark still renders at every width as ruled. row-gap keeps
   the "at least --space-2 between the wordmark and the first nav item"
   requirement intact for the stacked case. */
@media (max-width: 899px) {
    .masthead-inner {
        flex-wrap: wrap;
        row-gap: var(--space-2);
    }
}
/* The wordmark is set, not drawn (Adam's ruling, 2026-09-20; ops/BRIEF.md
   §6 Masthead). logo.png no longer renders anywhere — the file stays on
   disk for exports and the brand book, just unreferenced. The two-circle
   mark is unaltered: mark.png, 40px tall (39px wide, 393x400 intrinsic),
   at every width, no filter/recolour/opacity. The wordmark is live text,
   Poppins 700 at --t-sub (24px; 22px below 900), one line, so it can never
   diverge from the page's own type system again. Clear space stays
   measured off the mark's 40px box, unchanged by the swap. */
.masthead-logo {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}
.masthead-mark { width: 39px; height: 40px; flex-shrink: 0; }
.masthead-wordmark {
    /* Newsreader, not Poppins (Adam's ruling, 2026-09-21): 600 at --t-sub
       with -0.005em, exactly the scale's existing 600/24 setting (catalogue
       row titles), so the wordmark introduces no new style. 600 rather than
       the h1's 500 so it holds its weight beside the solid two-circle
       mark at a fifth of the h1's size. */
    font-family: var(--font-body);
    font-weight: 600;
    font-size: var(--t-sub);
    letter-spacing: -0.005em;
    line-height: 1;
    color: var(--c-ink);
    white-space: nowrap;
}
/* --t-sub itself already steps to 1.375rem (22px) below 900px (§1
   Tokens), so no separate override is needed here. */
.masthead-nav .nav-list {
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
}
/* Family/weight/size come from the composed metadata style in §4 —
   .masthead-nav .nav-link is a member of that selector group. This rule
   only carries the layout-specific override (no underline at rest). */
.masthead-nav .nav-link {
    border-bottom: none;
    padding-bottom: 0;
}
/* No visual active state, by design — see ops/BRIEF.md §6 Navigation. Do
   not add a rule keyed off [aria-current="page"] here. */
.masthead-nav .nav-link:hover, .masthead-nav .nav-link:focus-visible {
    border-bottom: 1px solid var(--c-link-underline);
}
/* At >= 1280px the nav right-aligns to the display edge (column left +
   56rem), the same edge the h1, the pitch, the opening photograph and the
   catalogue hairlines share (ops/BRIEF.md §6 Masthead, §12 item 7,
   2026-09-14 pass-8, Ruling 7: "the nav is a third element on that edge").
   ".masthead-inner" is also ".block" (width: 100%; max-width: var(--block);
   margin-inline: auto), which centres it on the 40rem column — this
   override widens it to 56rem while re-anchoring its LEFT edge to the
   SAME column-left position (calc(50vw - block/2)), the same math the
   display-edge photograph and hairlines use elsewhere in this file, so
   only the right edge moves. justify-content: space-between (above) then
   naturally pushes the nav out to the new right edge; the logo stays on
   the unchanged left edge. */
@media (min-width: 1280px) {
    .masthead-inner {
        width: 56rem;
        max-width: 56rem;
        /* the centred unit's left edge, the same as every other .block */
        margin-left: calc(50% - (var(--block) + var(--gutter-gap) + var(--gutter-width)) / 2);
        margin-right: auto;
    }
}

/* 8. Footer
/* ---------------------------------------------------------- */
/* One line: primary nav, then secondary nav, then the copyright, all
   Poppins Bold --t-meta (2026-09-12 critique ruling, ops/DECISIONS.md;
   2026-09-13 critique-home-06 pass, ruling 5, adds the primary items;
   ops/BRIEF.md §6 Footer, §12 item 19). No top padding — the --space-3
   margin above is the whole gap from the last beat. .site-footer-inner is
   a plain .block, so it lands on the same left edge as every other beat
   (2026-09-13 re-ruling: no more inner-axis indent). When the landing
   band ends the page, the footer joins it instead — see §9. */
/* 2026-09-14 gate-6 pass-9: bottom padding raised from --space-2 (40px)
   to a fixed 4rem (64px), per the coordinator's explicit instruction
   ("give the footer at least 64px bottom padding, or the brief's value
   if it states one" — the brief's own stated value, --space-2, is what
   critic pass 9 flagged as reading clipped). My own CDP measurement on
   this build found padding-bottom already computing the full 40px with
   no other rule reducing it and the page's scrollHeight ending exactly
   at the footer's own padded edge — I could not reproduce an actual
   8px gap. Raising it regardless is a safe, strictly additive change
   (more clearance, no other layout depends on this value), so this
   complies with the instruction without waiting to resolve the
   discrepancy; flagged in the round's report for ghost-design/Adam. */
.site-footer {
    padding-top: 0;
    padding-bottom: 4rem;
}
.site-footer-inner {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-1) var(--space-2);
    font-family: var(--font-title);
    font-weight: 700;
}
/* The copyright is Newsreader 400 (§4's EDITORIAL rule, above), not the
   nav's Poppins 700 — ".footer-copyright" alone ties ".site-footer-inner"
   on specificity (one class each) and this rule is later in the file, so
   it would silently win the tie and re-apply the nav's face to a line
   that isn't a link. This re-declares both properties at the same
   specificity, right after the rule it corrects, per this file's own
   convention (source order, never a forced-priority declaration). */
.site-footer-inner .footer-copyright {
    font-family: var(--font-body);
    font-weight: 400;
}
/* display: contents hands each nav's own <ul>/<li> straight to the
   footer's flex row, so the primary items, the secondary items and the
   copyright line all sit as one wrapping row rather than nested lists
   inside their own boxes. */
.footer-nav-primary,
.footer-nav-primary .nav-list,
.footer-nav,
.footer-nav .nav-list {
    display: contents;
}
.footer-nav-primary .nav-link,
.footer-nav .nav-link {
    border-bottom: none;
}
.footer-nav-primary .nav-link:hover, .footer-nav-primary .nav-link:focus-visible,
.footer-nav .nav-link:hover, .footer-nav .nav-link:focus-visible {
    border-bottom: 1px solid var(--c-link-underline);
}

/* 9. Ghost cards — Callout / Signup / Header / Image / Gallery
   (ops/BRIEF.md §6 "The authoring convention" + §12 item 8). Every
   selector here is scoped under .content and, where a card ships its own
   base stylesheet via {{ghost_head}}, deliberately compounds an extra
   ancestor class so it wins the cascade without a forced-priority declaration — ghost_head
   renders after this file's <link> in default.hbs, so a bare tie on
   specificity would otherwise go to Ghost's own card CSS.
/* ---------------------------------------------------------- */

/* Callout: an outward beat 3. Emoji hidden unconditionally; no
   background; Newsreader 500 at --t-step, line height 1.3 (ops/BRIEF.md
   §6, §1, §4 Scale). */
.content > .kg-callout-card {
    background: transparent;
    border: none;
    padding: 0;
}
.content > .kg-callout-card .kg-callout-emoji { display: none; }
.content > .kg-callout-card .kg-callout-text {
    font-family: var(--font-body);
    font-weight: 500;
    font-size: var(--t-sub);
    line-height: 1.35;
    text-wrap: pretty;
}

/* Signup / Header: THE CLOSE (Adam's Option B, 2026-09-14, ops/BRIEF.md §1
   "The close"; ops/DECISIONS.md, the pass-8/Option-B/close-spec entries).
   Every page with an action ends on the SAME PAPER as everything above it
   — no band, no ground swap, no filled control. The ask is marked by
   structure only: the page's long pause, a hairline (the site's one
   remaining display-width rule), and an underlined text control. This
   retires the previous "landing band" section wholesale: the full-bleed
   breakout, the ink ground / #f5f7f5 text swap, and the "footer joins the
   band" special case are all deleted, not just recoloured.

   Ghost's own card CSS (core/frontend/src/cards/css/{signup,header_v2}.css,
   injected via {{ghost_head}}, which renders AFTER this stylesheet's
   <link> in default.hbs) reaches compound selectors like
   ".kg-header-card.kg-width-full h2.kg-header-card-heading" — two classes
   + a type + a class. Every override below repeats the .content class
   (".content.content") to clear that bar by one full class step, which is
   "raise the component's specificity", not a forced-priority declaration — see
   ops/BRIEF.md §12.

   THE HAIRLINE AT THE DISPLAY EDGE (the receiving agent's own call, per
   this handoff's "what you must decide"): rather than a full-bleed
   breakout (retired above) plus a separately-widened inner pseudo-element,
   the card's own box becomes 56rem wide at >= 1280px, anchored to the
   SAME column-left edge as the masthead nav's own display-edge rule
   (§7 Masthead) — `margin-left: calc(50vw - var(--block) / 2)` — so a
   plain `border-top` directly on the card IS the hairline, at the display
   edge, with no extra element. Below 1280px the card stays the column's
   own width, so the same border-top is "the column's width" for free —
   one declaration serves both tiers of the spec table. Inner content
   (heading/subheading/form) keeps its own separate margin-left/max-width
   centring (below, unchanged in mechanism from the previous pass), so the
   text column's width never depends on the card's own, wider box.

   ".content.content" (not a plain ".content >") on the selector below:
   Ghost's own header-card CSS carries ".kg-header-card.kg-v2{padding:0}"
   at two classes, tying a plain ".content > .kg-header-card" and winning
   on source order (it loads after this file), which silently zeroed the
   close's own padding-top on Work/About. The repeated class clears the
   tie by one step, same convention as everywhere else in this section. */
.content.content > .kg-signup-card,
.content.content > .kg-header-card {
    border-top: 1px solid var(--c-ink);
    margin-top: var(--space-turn);
    padding-top: var(--space-2);
}
@media (min-width: 1280px) {
    /* margin-left: 0, not the masthead-inner's viewport-relative calc()
       (§7) — caught in review with a real scrollWidth-vs-clientWidth
       check: this card is a normal child of ".content", which is ALREADY
       exactly the 40rem column, itself already centred by ".block". The
       masthead's own nav sits directly on ".block" with no such
       intervening wrapper, so it needs the viewport-relative push to
       reach the column from the viewport's edge; this card's left edge
       already IS the column's left edge in ordinary flow, so it only
       needs to grow RIGHTWARD — width: 56rem alone, with no left offset,
       overflows .content's own right edge by 16rem and lands exactly on
       the display edge, entirely inside the viewport at every width this
       query applies to. */
    .content.content > .kg-signup-card,
    .content.content > .kg-header-card {
        width: 56rem;
        max-width: 56rem;
        margin-left: 0;
        margin-top: var(--space-3);
    }
}
.content.content .kg-signup-card-content,
.content.content .kg-header-card-content {
    display: block;
    padding: 0;
}
.content.content .kg-signup-card-text,
.content.content .kg-header-card-text {
    align-items: flex-start;
    text-align: left;
    padding: 0;
    height: auto;
}
/* Content starts at the column's own left edge, and the heading, the
   subheading and the form all now sit at the SAME column width (the one
   40rem measure, 2026-09-13 critique-home-04 pass, ruling 3 — pass 3's
   wider heading-only allowance, min(50rem, …), is retired: a heading
   balances over up to two lines instead). The margin-left offset reads
   "50%" against the SAME containing block — the card above, which is
   100vw wide and carries no horizontal padding of its own — so 50% here
   is exactly 50vw, matching .block's own centring math with no unit
   mismatch.

   Ghost's own card CSS reaches
   ".kg-signup-card.kg-width-wide h2.kg-signup-card-heading" — a
   clamp()'d font-size at three classes + a type, exactly tying
   ".content.content h2.kg-signup-card-heading"'s specificity, and it
   loads after this file, so it would win the tie and override --t-display
   with its own clamp(). The extra ".kg-signup-card-content" ancestor
   (already a real wrapper in the markup, used the same way below for the
   subheading) clears that tie by one class step — raise specificity,
   never a forced-priority declaration, per ops/BRIEF.md §12. */
.content.content .kg-signup-card-content h2.kg-signup-card-heading,
.content.content .kg-header-card-content h2.kg-header-card-heading {
    font-family: var(--font-body);
    font-weight: 500;
    font-size: var(--t-head);
    letter-spacing: -0.015em;
    line-height: 1.1;
    text-wrap: balance;
}
/* Ghost's own card CSS carries a more specific rule for the subheading
   (ops/DECISIONS.md 2026-09-12, ops/BRIEF.md §12 "not specified before,
   check anyway"). The real ".kg-signup-card-content"/".kg-header-card-content"
   ancestor wrapper raises specificity to beat it, never a forced-priority declaration. */
.content.content .kg-signup-card-content .kg-signup-card-subheading,
.content.content .kg-header-card-content .kg-header-card-subheading {
    font-family: var(--font-body);
    font-weight: 400;
    font-size: var(--t-body);
    line-height: 1.6;
    text-wrap: pretty;
}
.content.content h2.kg-signup-card-heading + .kg-signup-card-subheading,
.content.content h2.kg-header-card-heading + .kg-header-card-subheading {
    margin-top: var(--space-1);
}

/* HOME'S CLOSE (Adam's ruling, 2026-09-20, amended 2026-09-21 round 2;
   ops/BRIEF.md §1 "The close", §7 Home). Home only — /writing/ and
   /newsletter/ keep their --t-head ask headings.

   Round 2 changes, both answering build review 22:
   1. THE MARGIN LABEL IS GONE. The Signup card's HEADING field ("Make the
      call early.") restated the sentence beside it, which the locator-
      column rule (ops/BRIEF.md §2) bans: nothing in the gutter may
      paraphrase the text next to it. The form below is the exit, and it
      is in the column, so the gutter beside the close is empty by rule.
      display: none is the interim; the field should be CLEARED in Ghost
      so the theme is not suppressing authored words (Ghost then renders
      no h2 at all and this rule becomes inert).
   2. THE SENTENCE MOVES UP ONE STEP, --t-sub (24) -> --t-step (30). At
      24px it matched the catalogue row titles directly above it, so the
      page's one long pause read as "the list ran out". --t-step is a
      post ask's size on every other page, sits below the 1.953rem
      display threshold (so it may wrap, balanced), and leaves the pitch
      at --t-head untouched. Home sets 60 / 40 / 30 / 24 / 20 / 13. */
.page-home .content.content .kg-signup-card-content h2.kg-signup-card-heading {
    display: none;
}
/* .content repeated FOUR times: the §9 "Ghost tie" rule below
   (".content.content.content.content .kg-signup-card-content
   .kg-signup-card-subheading", six classes) sets this element to
   --t-body; ".page-home" plus four ".content" clears it decisively. */
.page-home .content.content.content.content .kg-signup-card-content .kg-signup-card-subheading {
    /* Round 3 (2026-09-21): back DOWN from --t-step to --t-body. The 30px
       step was set when the newsletter was Home's only ask; with Adam's
       "both, ranked" ruling it would hand the fallback the close's one
       display moment and rank it above the conversation. At body size the
       newsletter reads as the lighter alternative it now is. */
    font-family: var(--font-body);
    font-weight: 400;
    font-size: var(--t-body);
    letter-spacing: 0;
    line-height: 1.6;
    text-wrap: pretty;
    margin-top: 0;
}

/* Alignment applies to the heading, the subheading and the form/button
   uniformly and unconditionally — one shared rule, all three at the
   column's own width.

   2026-09-14 close-B pass: this used to read "margin-left: calc(50% -
   block/2)" because the card itself was a 100vw full-bleed box, whose own
   left edge sat at the VIEWPORT's left edge — a big rightward push was
   needed to reach the column. Now that the card's own left edge already
   IS the column's left edge at every width (the close is no longer
   full-bleed, above), that push is gone: margin-left: 0, and max-width
   caps the content back to the column's own 40rem even where the card's
   own box is wider (56rem, >= 1280px, for the hairline alone).

   Ghost's own card CSS carries
   ".kg-width-wide .kg-signup-card-subheading + .kg-signup-card-form
   { margin: min(3.2vmax,64px) 0 0 }" — a margin SHORTHAND, which also
   zeroes margin-left, at three classes, tying a plain
   ".content.content .kg-signup-card-form" and winning that one longhand
   property on source order (it silently left the form flush to the
   viewport's own left edge instead of the column's). The extra
   ".kg-signup-card-content" ancestor clears the tie the same way it does
   for the heading and subheading above. */
.content.content .kg-signup-card-content h2.kg-signup-card-heading,
.content.content .kg-header-card-content h2.kg-header-card-heading,
.content.content .kg-signup-card-content .kg-signup-card-form,
.content.content .kg-header-card-content .kg-header-card-button {
    margin-left: 0;
    margin-right: 0;
    max-width: var(--block);
}
/* The subheading needs its own, higher-specificity copy of this rule
   (2026-09-14 gate-6 pass-9): Ghost's own card CSS carries
   ".kg-header-card.kg-width-full .kg-header-card-subheading:not
   (.kg-layout-split .kg-header-card-subheading) { max-width: min(65vmax,
   1200px); font-size: clamp(1.05em,2vw,1.55em) }" (and the matching
   ".kg-signup-card" rule) — FIVE classes (the card, "kg-width-full", the
   subheading, and the :not() argument's own two classes), outranking the
   four-class rule above outright, not just tying it, so the subheading
   rendered at up to 1200px wide, past the display edge on Work's price
   close (caught in review: measured at x≈1490, past the 1280 column edge
   at 1920), AND at a viewport-relative clamped font-size (measured 34px
   at 1920 — a second, independently-discovered instance of the exact
   same tie, this time on font-size rather than max-width; the pass-9
   design ruling's own "--t-body, text-wrap: pretty" spec for this
   element depends on both being fixed together). Six classes here
   clears both decisively. */
.content.content.content.content .kg-signup-card-content .kg-signup-card-subheading,
.content.content.content.content .kg-header-card-content .kg-header-card-subheading {
    margin-left: 0;
    margin-right: 0;
    max-width: var(--block);
    font-size: var(--t-body);
    text-wrap: pretty;
}
/* The heading is short on every live page ("$3,000", "Make the call
   early.") so this same Ghost tie never became visible there — but it
   exists identically (measured: max-width computed 896px, the card's own
   width, not the column's), so it gets the same fix for the same reason,
   defensively, before a longer heading ever ships. */
.content.content.content.content .kg-signup-card-content h2.kg-signup-card-heading,
.content.content.content.content .kg-header-card-content h2.kg-header-card-heading {
    max-width: var(--block);
}
/* Heading straight into the form/button (no subheading authored):
   --space-1, the same gap as heading -> subheading. Subheading into the
   form/button: --space-2 (ops/BRIEF.md §1 "Inside" row). */
.content.content .kg-signup-card-form,
.content.content h2.kg-signup-card-heading + .kg-signup-card-form,
.content.content h2.kg-header-card-heading + .kg-header-card-button {
    margin-top: var(--space-1);
}
.content.content .kg-signup-card-subheading + .kg-signup-card-form,
.content.content .kg-header-card-subheading + .kg-header-card-button {
    margin-top: var(--space-2);
}
/* Ghost's own signup/header card CSS (loaded after this file via
   {{ghost_head}}) rounds its button's corners AND, caught in review with
   a real screenshot (not just computed-style-adjacent reasoning), resets
   text-decoration to none on the button/link at a specificity this
   file's own base ".btn"/".kg-signup-card-button" rule (§6, one class)
   can't beat. Raise specificity with the real ".kg-signup-card-content"/
   ".kg-header-card-content" ancestor wrapper (already used above), never
   a forced-priority declaration, to beat both — ops/BRIEF.md §5, §12
   item 2. The underline properties are repeated here, not just in §6,
   because this is the rule that actually wins the cascade for a card's
   own button/link. */
.content.content .kg-signup-card-content .kg-signup-card-button,
.content.content .kg-header-card-content .kg-header-card-button {
    border-radius: 0;
    border: none;
    text-decoration-line: underline;
    text-decoration-thickness: 2px;
    text-underline-offset: 0.75rem;
}
.content.content .kg-signup-card-content .kg-signup-card-button:hover,
.content.content .kg-signup-card-content .kg-signup-card-button:focus-visible,
.content.content .kg-header-card-content .kg-header-card-button:hover,
.content.content .kg-header-card-content .kg-header-card-button:focus-visible {
    text-decoration-thickness: 3px;
}
.content.content .kg-signup-card-content .kg-signup-card-button {
    text-decoration-color: var(--c-free);
}
.content.content .kg-header-card-content .kg-header-card-button {
    text-decoration-color: var(--c-commercial);
}
.content.content .kg-signup-card-fields {
    background: transparent;
    border: none;
    border-radius: 0;
    padding: 0;
    gap: 0;
}
/* Ghost's own card CSS reaches ".kg-signup-card.kg-width-wide
   .kg-signup-card-fields { max-width: 500px }" — three classes, tying
   this rule's own three, and it loads after this file. The extra
   ".kg-signup-card-content" ancestor (used the same way above) clears the
   tie by one class step. */
.content.content .kg-signup-card-content .kg-signup-card-fields {
    max-width: none;
}
/* Ghost's own input carries "margin: 0 3px 0 0" for its default rounded-
   pill look; that 3px is the exact gap ops/BRIEF.md §5 says must not
   exist ("the input and its button touch, with no gap"). */
.content.content .kg-signup-card-input {
    border-radius: 0;
    font-size: var(--t-body);
    height: auto;
    margin: 0;
}
.content.content .kg-signup-card-disclaimer {
    font-size: var(--t-meta);
}
/* THE RULED INPUT (ops/BRIEF.md §5 "The close's input"; ops/DECISIONS.md
   Ruling 1). Transparent, no top or side border, a bottom rule only,
   Newsreader — this replaces the previous filled #f5f7f5 field entirely.
   Ghost's own input CSS sets a white fill, no border, 2.9em/46px height
   and a 0 3px 0 0 margin (cards.min.css) — every one of those properties
   is explicitly reset below at ".content.content .kg-signup-card-input"
   (already enough specificity to win; the ancestor-repeat convention
   applies where Ghost's own selector is otherwise a tie or higher). */
.content.content .kg-signup-card-input {
    flex: 1 1 auto;
    min-width: 0;
    width: auto;
    height: auto;
    min-height: 0;
    margin: 0;
    padding: 0.75rem 0;
    background: transparent;
    border: none;
    border-bottom: 1px solid var(--c-ink);
    border-radius: 0;
    box-shadow: none;
    color: var(--c-ink);
    font-family: var(--font-body);
    font-weight: 400;
    font-size: var(--t-body);
    line-height: 1.6;
}
.content.content .kg-signup-card-input::placeholder {
    color: var(--c-placeholder);
}
/* THE FORM ROW: input and submit on one baseline, --space-1 apart, column
   width (ops/BRIEF.md §5 "Input and submit share a baseline"). Ghost's
   own ".kg-signup-card-fields" is the actual flex row (see the reset,
   above it, at ".content.content .kg-signup-card-fields"); ".kg-signup-card-form"
   is its outer wrapper and needs no flex properties of its own — display
   isn't overridden here, only width/max-width (already handled in the
   shared alignment rule, above) and the top margin. */
.content.content .kg-signup-card-fields {
    /* flex-end, not baseline — same fix, and the same reason, as
       ".signup-form" above. */
    align-items: flex-end;
    gap: var(--space-1);
}
/* THE ACTION CONTROL — a real <button type="submit"> for the free ask, a
   real <a> for the paid one (ops/BRIEF.md §5 "The action control is
   text, not a button shape"; ops/DECISIONS.md Ruling 1). Poppins 700,
   ink, transparent, no border, an underline instead of a fill — this is
   the single biggest change from the previous pass, which filled these
   with --c-free/--c-commercial. ".kg-signup-card-button"/".kg-header-card-button"
   here are Ghost's OWN classes on the real button/link Ghost renders
   (".btn"/".btn-free"/".btn-commercial" are the theme's native-markup
   equivalents in post.hbs and partials/components/signup-form.hbs — both
   sets share this same visual rule via the combined selector in §6, "THE
   ACTION CONTROL", so this file also inherits it here without repeating
   the declarations — see that rule for the underline colours and
   states). Only the CARD-SPECIFIC overrides needed to beat Ghost's own
   card CSS live here. */
.content.content .kg-signup-card-content .kg-signup-card-button,
.content.content .kg-header-card-content .kg-header-card-button {
    display: inline-flex;
    align-items: center;
    height: auto;
    min-height: 44px;
    padding: 0.75rem 0;
    background: transparent;
    border: none;
    border-radius: 0;
    box-shadow: none;
    color: var(--c-ink);
    font-family: var(--font-title);
    font-weight: 700;
    font-size: var(--t-control);
    /* 2026-09-14 gate-6 pass-9: Ghost's own card CSS carries
       ".kg-signup-card-button{font-size:1em;line-height:1em;...}" — one
       class, tying the base ".btn"/".kg-signup-card-button" rule (§6)
       exactly, and it loads after this file, so the tie went to Ghost:
       the button's own line-height computed 18px (1em of its 18px font),
       not this file's intended 1.6 (28.8px), giving it a shorter box
       than the input beside it and misaligning the two rules in the
       control row. This four-class rule already beats the tie for every
       other property; line-height just needed to be repeated here too. */
    line-height: 1.6;
    opacity: 1;
}
/* Caught in review with a real screenshot: Ghost's card CSS carries
   ".kg-header-card.kg-v2 .kg-header-card-button.kg-style-accent
   { background-color: var(--ghost-accent-color) }" — FOUR classes, tying
   ".content.content .kg-header-card-content .kg-header-card-button"
   exactly, and it loads after this file, so the tie went to Ghost: the
   button rendered filled with the site-wide accent custom property (a
   bright pink hex, set by Ghost's own inline <style> in <head> — not one
   of this theme's five sanctioned colours, and never typed literally
   here, same convention as every other retired/foreign hex in this
   file), not our `background: transparent` above. Adding the real
   ".kg-style-accent"
   class (already on the rendered button/span — ghost-builder's own
   "buttonColor: accent" setting) to this selector reaches five classes,
   clearing the tie without a forced-priority declaration. The signup
   card's own equivalent Ghost rule is only two classes
   (".kg-signup-card-button.kg-style-accent"), already beaten by the
   plain four-class rule above, so it needs no matching fix. */
.content.content .kg-header-card-content .kg-header-card-button.kg-style-accent {
    background: transparent;
}
/* Focus ring: the close's own 4px offset (ops/BRIEF.md §5, "The close's
   input and control use outline-offset: 4px") — the site's usual 2px
   offset (§6) is overridden here, at the same specificity Ghost's own
   "outline: none" needs beating (".kg-signup-card-input:focus-visible",
   ".kg-header-card.kg-v2 .kg-header-card-button", both in cards.min.css).
   There is no more ink ground to protect the ring's contrast against —
   the accent purple reads at its normal, full-strength ratio on the page
   ground now. */
.content.content .kg-signup-card-input:focus-visible {
    border-bottom: 2px solid var(--c-link-underline);
    outline: 2px solid var(--c-link-underline);
    outline-offset: 4px;
}
.content.content .kg-signup-card-content .kg-signup-card-button:focus-visible,
.content.content .kg-header-card-content .kg-header-card-button:focus-visible {
    outline: 2px solid var(--c-link-underline);
    outline-offset: 4px;
}
/* Ghost's success/error/loading states: editorial metadata style, ink,
   left-aligned (ops/BRIEF.md §5 "Ghost's loading, success and error
   states"). Ghost's own CSS hides/shows these via a ".success"/".error"
   class on the form; this only sets their FACE, not their visibility. */
.content.content .kg-signup-card-success,
.content.content .kg-signup-card-error {
    font-family: var(--font-body);
    font-weight: 400;
    font-size: var(--t-meta);
    color: var(--c-ink);
    text-align: left;
}
@media (max-width: 899px) {
    /* Input and submit stack, submit --space-1 under a full-width input
       (ops/BRIEF.md §5, "Below 900px the submit sits --space-1 under a
       full-width input"). */
    .content.content .kg-signup-card-fields {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--space-1);
    }
    .content.content .kg-signup-card-input,
    .content.content .kg-signup-card-content .kg-signup-card-button {
        width: 100%;
    }
}

/* Image card, opening a page's beat 2 (2026-09-13 critique-home-03 pass:
   Adam's decision, "scene or face is authored through Ghost's image-card
   width" — Wide means a scene rectangle, Regular means a face circle,
   because a content-agnostic template cannot see what a photograph
   shows; that distinction is ghost-builder's per-image setting, not
   something this file can infer). ops/BRIEF.md §6, §7, §8.

   DEVIATION FROM THE HANDOFF'S STATED MECHANIC, recorded here because
   ghost-webdev decides mechanism and the handoff only specified an
   outcome: the handoff calls for the aspect-ratio on the <img> itself.
   Verified against the actual served markup in the pinned Chrome (152)
   used for sign-off, that distorts whenever the <img> also carries HTML
   width/height attributes with a different intrinsic ratio (which every
   Ghost content image does) — Chrome lets the element's natural ratio win
   over the authored `aspect-ratio`, even though the CSS Sizing spec says
   an explicit ratio (no `auto` keyword) should not be overridden.
   Reproduced in isolation outside this theme/Ghost entirely, so it is not
   a selector or specificity bug in this file. `aspect-ratio` on a plain
   (non-replaced) element has no natural ratio to conflict with, so it is
   not affected — moved here, to the <figure>. The old defect this
   replaces (a fixed-height, overflow: hidden figure clipping its own
   caption) is still avoided, because this figure carries no `overflow` at
   all: the <img> clips itself via its own border-radius/object-fit
   (Chromium clips a replaced element's painted content without needing
   `overflow: hidden` on a wrapper), so the figcaption below the
   (unclipped) figure box is never cut off. */
/* :first-child, not just ":not(.kg-width-wide)": the beat's opening
   photograph is always .content's first element (ops/BRIEF.md §8, rule 1,
   "a photograph... appears only in beat 2 and opens it"). Without this,
   these two rules — at four classes/pseudo-classes each — outrank the
   tier-1 unit's own "blockquote + .kg-image-card" (two classes + a type,
   below) and would blow a 240x240 testimonial headshot up to a 28.5rem
   circle, which is exactly what shipped until this was caught in review. */
.page-article .content > .kg-image-card.kg-width-wide:first-child {
    width: 100%;
    max-width: var(--block);
    aspect-ratio: 3 / 2;
}
.page-article .content > .kg-image-card.kg-width-wide:first-child img {
    width: 100%;
    height: 100%;
    border-radius: 0;
    object-fit: cover;
    filter: grayscale(100%) contrast(1.05);
}
.page-article .content > .kg-image-card:not(.kg-width-wide):first-child {
    width: 100%;
    max-width: 28.5rem;
    aspect-ratio: 1;
}
.page-article .content > .kg-image-card:not(.kg-width-wide):first-child img {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    object-fit: cover;
    filter: grayscale(100%) contrast(1.05);
}
/* Caption: 0.5rem below the photograph (a stated exception to the
   three-value spacing scale, ops/BRIEF.md §3), --space-2 above whatever
   follows. :first-child again, so this can't outrank the tier-1 unit's
   own heading -> subheading -> form spacing (the testimonial's own
   image card is never .content's first child). */
.page-article .content > .kg-image-card:first-child figcaption {
    margin-top: var(--offset-tight);
    text-align: right;
}
.page-article .content > .kg-image-card:first-child + * {
    margin-top: var(--space-2);
}

.article-body .content > .kg-image-card,
.issue-article .content > .kg-image-card {
    width: 100%;
    border-radius: 0;
}
.article-body .content > .kg-image-card img,
.issue-article .content > .kg-image-card img {
    width: 100%;
    height: auto;
    border-radius: 0;
    filter: none;
}
.article-body .content > .kg-image-card figcaption,
.issue-article .content > .kg-image-card figcaption {
    margin-top: var(--offset-tight);
}
.article-body .content > .kg-image-card + *,
.issue-article .content > .kg-image-card + * {
    margin-top: var(--space-2);
}
/* gscan requires .kg-width-wide to render styled, or a "wide" image/
   gallery card breaks out unstyled. This site has one column everywhere
   (ops/BRIEF.md §2) and nothing wider than the column, so "wide" is
   deliberately made identical to the column width — never a viewport
   breakout — rather than left to Ghost's own default (which pulls a wide
   card beyond the text column). Excludes the Signup/Header card (the
   landing band, §9 above, the one deliberate viewport breakout) and the
   page image card (styled to the column width directly, above) — without
   the exclusion this would tie the image card's own rule on specificity
   and win on source order, since both are four classes/pseudo-classes. */
.content .kg-width-wide:not(.kg-signup-card):not(.kg-header-card):not(.kg-image-card) {
    width: 100%;
    max-width: 100%;
}

/* Blockquote (ops/BRIEF.md §4 Quotation, "Newsreader has a real italic").
   Words a person said are set in Newsreader ITALIC — this base rule is
   also "tier-2 and post blockquotes: --t-body italic 400" (the tier-1
   pull quote override, below, raises the size and drops the line
   height). Marks are CSS-generated, never typed in Ghost, and hang: the
   opening mark's right edge sits on the column's left edge (blockquote's
   own left edge), so the quote's first letter sits on that edge like
   every other line. No text-indent, no hanging-punctuation (Safari-only,
   and it would hang the mark twice there) — 2026-09-12 critique ruling,
   ops/DECISIONS.md. Quote marks are generated with no font properties of
   their own, so they inherit the exact face/weight/size/colour of the
   quote text (ops/BRIEF.md §4 Quotation, "Quote marks"). */
.content blockquote,
.article-body .content blockquote {
    font-family: var(--font-body);
    font-weight: 400;
    font-style: italic;
    font-size: var(--t-body);
    line-height: 1.6;
    position: relative;
    quotes: "\201C" "\201D";
    border: none;
    background: none;
}
.content blockquote::before {
    content: open-quote;
    position: absolute;
    right: 100%;
}
.content blockquote::after {
    content: close-quote;
}

/* TIER-1 PULL QUOTE (2026-09-13 critique-home-04 pass, ruling 4: "a
   designed object"; sized and recoloured again in critique-home-05).
   A page's tier-1 quote only — identified the same way the tier-1 unit
   below is, by the image card that follows it directly — never a post
   blockquote (.page-article scopes that out, since post quotes have no
   attribution portrait at all).

   2026-09-13 critique-home-05 pass, ruling 3 ("a sixth size"): the pull
   quote moves off --t-step (27px, tied with the lede) onto the new
   --t-sub (22px) — "the quote now sits under [the lede], not beside it."
   Line height 1.4.

   2026-09-13 critique-home-06 pass, ruling 6 ("same air, one meaning"):
   margin-top is now --space-turn (96px) UNCONDITIONALLY, on every page —
   not --space-2 with a Home-only override to --space-turn, which is what
   let Work's tier-1 units sit 40px from the prose while Home's sat 96px:
   "the same component with different air on different pages" was a scale
   failure in its own right. Home's own attribution-to-pitch turn (160px,
   the strata's one intentional pause) is a Home-specific override on the
   ATTRIBUTION's own margin-bottom (below), not a margin-top on the pitch
   collapsing against it: the attribution is display: inline-flex (an
   inline-level box, for the portrait-beside-text layout below 1280px),
   and inline-level boxes don't reliably collapse margins with a following
   block sibling the way two block boxes do — rather than depend on that,
   Home sets the attribution's own margin-bottom straight to --space-3
   (160px), and the pitch itself carries no competing margin-top for this
   gap, so there is only ever one declared value in play, not two that
   need to agree via collapse.

   Quote marks go back to ink (ruling 6: "quote marks are ink, not
   purple") — pass 5's move to the accent purple is reverted; purple now
   means only "you can act here" (link underlines, focus ring, selection,
   the free button), a Gate 5 "one device, one meaning" fix. Everything
   but the two generated marks was already ink via ordinary inheritance;
   removing the ::before/::after override is the whole fix, so those
   rules are deleted rather than recoloured. */
.page-article .content blockquote:has(+ .kg-image-card) {
    font-weight: 400;
    font-size: var(--t-sub);
    line-height: 1.35;
    margin-top: var(--space-turn);
}

/* TIER-1 UNIT (2026-09-13 critique-home-03 pass, GAP 4; rebuilt 2026-09-14
   pass-8, Ruling 1 + ops/BRIEF.md §4 Quotation: "One locked apparatus
   unit": a 40px portrait circle ABOVE the name (Newsreader 600 --t-meta)
   and the role (Newsreader 400 --t-meta), all right-aligned — portrait
   beside name/role (the previous, gate-6-fixed design) is retired outright
   by this pass, not just adjusted. New content order from ghost-builder:
   blockquote -> image card -> p.

   MOBILE-FIRST BASE (below 1024px, ops/BRIEF.md §2 "Below 1024px"): the
   unit is two stacked, right-aligned blocks, in normal flow, `--space-1`
   below the quote — no gutter, no absolute positioning, so this base rule
   is also the below-1024 rule with no override needed there.

   >= 1024px (ops/BRIEF.md §2 "Apparatus into the gutter", §4 Quotation):
   pulled into the gutter via NEGATIVE MARGIN, not absolute positioning —
   the receiving agent's own call, per the handoff's "what you must
   decide". Absolute positioning was rejected here because it would need a
   wrapper around blockquote + figure + p (three flat, adjacency-selected
   siblings, per the same architecture note as every prior round: Ghost's
   Lexical renderer emits them flat, and JS restructuring is out), and a
   negative-margin pull is exactly the technique this file's own >= 1280px
   rail already proved for this exact unit in earlier rounds. The brief
   gives the exact offset for the portrait: `margin-top: calc(-1.35 *
   var(--t-sub))`, leveling its top with the quote's last line. The
   paragraph follows the portrait in flow (so it's already below it,
   stacked, at their new fixed width), pulled left into the gutter the
   same way. margin-bottom on the PARAGRAPH (not a margin-top on whatever
   follows) is the one declared value for "attribution -> pitch", per
   "gaps never add" (ops/BRIEF.md §3) — see the Home-specific override
   below. */
.content blockquote + .kg-image-card {
    display: block;
    width: 2.5rem;
    max-width: 2.5rem;
    aspect-ratio: 1;
    margin-top: var(--space-1);
    margin-left: auto;
}
.content blockquote + .kg-image-card img {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    object-fit: cover;
    filter: grayscale(100%) contrast(1.05);
}
/* The attribution: Newsreader, the editorial metadata style, name at 600
   via ::first-line (explicitly sanctioned by the handoff), role at 400.
   text-align: right (not centred under the portrait) matches "all
   right-aligned" (ops/BRIEF.md §4 Quotation) — the portrait's own
   margin-left: auto right-aligns IT to the same edge. */
.content blockquote + .kg-image-card + p {
    text-align: right;
    margin-top: var(--offset-tight);
    font-family: var(--font-body);
    font-weight: 400;
    font-size: var(--t-meta);
    /* --space-1 below the quote at every width below 1024px (the whole
       unit's floor, ops/BRIEF.md §2). >= 1024px replaces this with the
       gutter pull, below. */
    margin-bottom: var(--space-1);
}
.content blockquote + .kg-image-card + p::first-line {
    font-weight: 600;
}
@media (min-width: 1280px) {
    /* NOT position: absolute — tried and reverted in this same round.
       ".kg-image-card" and its following "p" are SIBLINGS of blockquote,
       not descendants of it; a sibling can never use another sibling as
       its containing block, no matter what "position" that sibling
       carries — only ANCESTORS qualify. Caught with a real geometry
       check (not just the vertical gap, which happened to measure
       correctly by coincidence: taking the unit out of flow entirely
       fixed the pitch's spacing regardless of where the unit itself
       rendered): the unit's own x-position came out strongly negative,
       hundreds of pixels off-screen, because its actual containing block
       was the viewport-sized initial containing block, not the 40rem
       blockquote. There is no shared wrapper this file can add here —
       blockquote/figure/p are flat children of Ghost's own rendered body
       content (Lexical), which the theme cannot restructure. Back to the
       margin technique, in flow, with the cancellation magnitude
       corrected against a real measured gap (see the comment below the
       pitch rule for the exact before/after numbers).
       RIGHT gutter (Adam's ruling, 2026-09-20): margin-left is now
       POSITIVE, calc(40rem + gap) — the column's own width plus the gap
       — not a negative pull off the column's left edge. Move both the
       portrait and the name/role paragraph together; moving only one
       splits a single attribution across both margins (the handoff's own
       caught mistake). */
    .content blockquote + .kg-image-card {
        width: var(--gutter-width);
        max-width: var(--gutter-width);
        aspect-ratio: auto;
        height: 2.5rem;
        margin-top: calc(-1.35 * var(--t-sub));
        margin-left: calc(var(--block) + var(--gutter-gap));
    }
    .content blockquote + .kg-image-card img {
        width: 2.5rem;
        height: 2.5rem;
        margin-left: auto;
        display: block;
    }
    .content blockquote + .kg-image-card + p {
        width: var(--gutter-width);
        margin-top: var(--offset-tight);
        margin-left: calc(var(--block) + var(--gutter-gap));
        /* Cancels the unit's own footprint below the quote, so "gaps
           never add" (ops/BRIEF.md §3): the quote's own margin-bottom
           (none) and the pitch's own stratum pause become the only
           declared values CSS actually collapses for this seam. The
           constant below is CALIBRATED against a real measured gap, not
           derived purely from font-metric arithmetic (line-height
           rounding made the arithmetic version land at 71px measured
           against a 96px target — 25px short — so this adds that
           deficit back rather than re-deriving from scratch): */
        margin-bottom: calc(-1 * (2.5rem + var(--offset-tight) + 2 * (var(--t-meta) * 1.4)) + 25px);
    }
}
/* Whatever ordinary paragraph follows a tier-1 unit (2026-09-14 gate-6
   pass-9): the attribution is pulled into the gutter at >= 1024px and its
   own footprint is cancelled (above) so "gaps never add" for the common
   case — but the attribution still visually EXTENDS about 60px past its
   own quote's bottom edge in the gutter (portrait + tight offset + two
   lines of name/role, pulled up only 1.35 lines, not the unit's whole
   height). On Work, the paragraph right after Guido Lonetti's tier-1 unit
   (the survey provenance line) started at the ordinary 24px paragraph
   gap, which is well inside that 60px overhang — his attribution read as
   sitting beside the WRONG paragraph. This targets any tier-1 unit
   followed directly by an ordinary paragraph (not matched by Home's own
   more specific pitch selector below, which wins there on specificity)
   and gives it enough clearance to sit below the attribution's real
   visual bottom, not just the cancelled-to-zero flow height. */
@media (min-width: 1280px) {
    .content blockquote + .kg-image-card + p + p {
        margin-top: calc(var(--space-1) + 60px);
    }
}
/* Home's stratum 3 pause, "proof -> pitch" (ops/BRIEF.md §7 "Four strata";
   §3 "Gaps never add"): --space-turn at every width now (2026-09-14
   close-B pass, ops/DECISIONS.md Ruling 3, superseding pass-8's own
   >= 1280px --space-3 step) — the page's one long pause moved to the
   close. Declared on the PITCH's own margin-top (not the attribution's
   margin-bottom) so there is exactly one value read for this seam,
   regardless of the gutter cancellation immediately above — see the pitch
   rule, below, for the other half of this pair. */

/* TIER 2 (no portrait): the paragraph right after the blockquote,
   directly — this selector cannot match a tier-1 attribution, because
   there an image card sits between the blockquote and the paragraph.
   ONE QUOTE GRAMMAR (2026-09-14 pass-9 design ruling 3): no more
   generated em dash — a tier-2 attribution is a first name only,
   Newsreader 600 `--t-meta` (the ::before dash rule is deleted outright,
   not hidden; the name-weight bump was already correct from the
   :first-line rule pattern used elsewhere, but this element has no
   portrait/role split to apply ::first-line to, so the whole element is
   simply 600). Apparatus (ops/BRIEF.md §4 Quotation): right-aligned at
   every width. */
.content > blockquote + p {
    font-family: var(--font-body);
    font-weight: 600;
    font-size: var(--t-meta);
    text-align: right;
    margin-top: var(--space-1);
}
/* A fixed gap between successive quotes, EITHER tier, and quote -> next
   section: --space-turn (2026-09-14 pass-9 design ruling 3, superseding
   this file's own earlier --space-2-based guess from gate-6 pass-9 the
   same day — the design ruling landed after that guess and sets the
   value explicitly). Two tier-2 quotes in a row previously measured at a
   -4px near-overlap: the attribution paragraph between them is pulled
   fully into the gutter at >= 1024px (same technique as the tier-1
   unit), so the generic ".content > * + *" 24px rule was the ONLY
   declared value the second blockquote's top margin ever saw, and the
   attribution's own gutter cancellation (needed so it doesn't add flow
   height under the FIRST quote) ate into even that. Targeting the
   blockquote that follows a tier-2 attribution specifically (three
   siblings: quote, attribution, quote) sets its own margin-top directly,
   so this seam has one explicit source of truth instead of a collapsed
   accident. */
.content > blockquote + p + blockquote {
    /* calc(...) not a bare var(--space-turn): measured against a real
       gap, not just the declared value — the attribution's own gutter
       cancellation (below) absorbs a fixed ~28px via collapse regardless
       of the target value (confirmed at the --space-2-based target
       first, then re-confirmed here at the --space-turn-based one), so
       the same +28px correction applies. */
    margin-top: calc(var(--space-turn) + 28px);
}
/* Quote -> next section is the SAME --space-turn gap (pass-9 design
   ruling 3), not just quote -> next quote. Whatever follows a tier-2
   attribution that ISN'T another quote (Work's Callout pull line, a
   plain paragraph) gets the identical treatment and the identical
   +28px collapse correction — measured directly (the Callout after
   Diana's quote landed at 22px without this).

   Two concrete selectors, not one ":not(blockquote)" catch-all: caught
   in review, ":not(blockquote)" (a pseudo-class whose specificity is
   just its own argument's — a bare type selector, contributing nothing
   at the class level) lost outright to this file's own pre-existing
   ".content > .kg-callout-card { margin-top: var(--space-2) }" (two
   classes) — TWO classes beats one class plus three types on the
   class/ID tier of specificity, regardless of type count or source
   order. Naming ".kg-callout-card" and "p" explicitly reaches two
   classes here as well, clearing the tie the same way every other
   Ghost-card override in this file does. */
.content > blockquote + p + .kg-callout-card,
.content > blockquote + p + p {
    /* +18px, not +28px: the Callout's own base rule contributes a
       slightly different collapse than a plain blockquote does,
       measured at +28px landing 10px over target (106px against 96px).
       Recalibrated down to +18px against the same real measurement. */
    margin-top: calc(var(--space-turn) + 18px);
}
@media (min-width: 1280px) {
    /* NOT position: absolute — a sibling can't use a sibling as its
       containing block; see the long comment on the tier-1 unit above,
       which hit this exact bug first. Positive margin into the RIGHT
       gutter, in flow, same technique as tier-1 (Adam's ruling,
       2026-09-20). */
    .content > blockquote + p {
        width: var(--gutter-width);
        margin-top: calc(-1.35 * var(--t-sub));
        margin-left: calc(var(--block) + var(--gutter-gap));
        margin-bottom: calc(-1 * (var(--t-meta) * 1.4));
    }
}

/* Gallery card: the client marks, all 2rem tall, in one wrapping row,
   --space-2 apart (ops/BRIEF.md §6). Ghost's own gallery.css groups
   images into rows of up to three via .kg-gallery-row; display:contents
   flattens that grouping so every mark sits in the same flex row
   regardless of count. */
.content > .kg-gallery-card {
    background: transparent;
}
.content.content .kg-gallery-container {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
}
.content.content .kg-gallery-row {
    display: contents;
}
.content.content .kg-gallery-image {
    width: auto;
    margin: 0;
}
.content.content .kg-gallery-image img {
    width: auto;
    height: 2rem;
    object-fit: contain;
}
.content > .kg-gallery-card figcaption {
    flex-basis: 100%;
    margin-top: var(--space-1);
}

/* 10. Post/page body typography
   (ops/BRIEF.md §7 "Article", body element table)
/* ---------------------------------------------------------- */
/* One measure, the 40rem column, for everything (ops/BRIEF.md §2 Grid;
   2026-09-13 critique-home-04 pass, ruling 3). Pass 3's separate, narrower
   --measure inside a wider --block is retired — body copy, quotes, lists
   and headings already sit inside .content, which is itself inside
   .block (max-width: var(--block)), so no per-element max-width is needed
   here any more; removing it is the fix, not adding a new one. */
/* Body leading opens to 1.7 (critique-home-05 pass, ruling 2: "18/30.6px",
   Adam's "more open body leading" decision) — body paragraphs only; every
   other --t-body use (excerpts, tier-2/post quotes, card subheadings,
   inputs) stays 1.6, per the scale table's own split. */
.content > p {
    font-size: var(--t-body);
    line-height: 1.7;
}
/* Page h2: Newsreader 600, -0.01em, line height 1.2 (ops/BRIEF.md §4
   Scale, "page h2 and month headings"). A post's own h2 (below) sits at
   a different size and drops the tracking — it has none of its own. */
.content > h2 {
    font-family: var(--font-body);
    font-weight: 600;
    font-size: var(--t-step);
    line-height: 1.2;
    letter-spacing: -0.01em;
}
/* On an Article or Issue, an h2 is an ordinary body heading (one section
   only, per ops/BRIEF.md §7), not a page's section-opener — --space-2
   above, --space-1 below, no rule, exactly like h3. Sized differently
   too: "post h2: --t-sub 600, balanced" (ops/BRIEF.md §4 Scale) — no
   tracking of its own, so letter-spacing resets to normal rather than
   inheriting the page h2's -0.01em. */
.article-body .content > h2,
.issue-article .content > h2 {
    font-size: var(--t-sub);
    letter-spacing: normal;
    text-wrap: balance;
    margin-top: var(--space-2);
}
.article-body .content > h2 + *,
.issue-article .content > h2 + * {
    margin-top: var(--space-1);
}
/* h3, issue row titles and the week numeral: Newsreader 600 at --t-body
   (ops/BRIEF.md §4 Scale). */
.content > h3 {
    font-family: var(--font-body);
    font-weight: 600;
    font-size: var(--t-body);
    line-height: 1.4;
    margin-top: var(--space-2);
}
.content > h3 + * { margin-top: var(--space-1); }

/* :not(.home-rows): Home's template-rendered row list (§ "Home's body of
   work", below) is also a plain ".content > ul", but it's a set of rows,
   not an authored body list, and must not pick up Ghost body content's
   en-dash marker or its indent (2026-09-13 critique-home-04 pass, caught
   in review — it inherited both by default the first time this rendered). */
.content > ul:not(.home-rows),
.content > ol {
    padding-left: 1.25rem;
}
.content > ul:not(.home-rows) > li,
.content > ol > li {
    position: relative;
    margin: 0;
    font-size: var(--t-body);
    line-height: 1.6;
}
.content > ul:not(.home-rows) > li { list-style: none; }
.content > ul:not(.home-rows) > li::before {
    content: '\2013';
    position: absolute;
    left: -1.25rem;
}
.content > ol {
    list-style: decimal;
}
.content > ol > li { margin-left: 1.25rem; }

/* LEAD-INS (ops/BRIEF.md §2, §6; 2026-09-14 pass-9 design ruling 4): a
   bold phrase followed by a <br> at the START of a paragraph or list
   item (e.g. Work's agenda, "15 minutes<br>— Breakout...") is apparatus:
   at >= 1280px it hangs in the RIGHT gutter (Adam's ruling, 2026-09-20),
   right-aligned, level with its own line; below 1280 it renders as
   authored, inline.

   POSITIONING TECHNIQUE (the receiving agent's own call, per the
   handoff): position: absolute against the paragraph/list item itself.
   ".content > ul:not(.home-rows) > li"/".content > ol > li" are already
   position: relative (for their own hanging en-dash marker, above); a
   bare ".content > p" needs the same treatment added here, scoped with
   :has() so it only applies where a lead-in is actually present (adding
   position: relative unconditionally to every body paragraph would risk
   an unrelated z-index/stacking side effect for no benefit elsewhere).
   Absolute, not a negative-margin pull: the strong is the very FIRST
   inline content of its own line, so "level with its line" is simply
   top: 0 against the paragraph/item's own top — no preceding sibling
   height to estimate or cancel, unlike every other gutter item in this
   file that sits beside LATER content. */
@media (min-width: 1280px) {
    .content > p:has(> strong:first-child + br) {
        position: relative;
    }
    /* left is measured from each containing block's OWN left edge, not
       the column's — and a list item's left edge isn't the column's left
       edge: ".content > ul:not(.home-rows)"/".content > ol" carry their
       own 1.25rem padding-left (list-marker indent, above), and an
       ".content > ol > li" adds a second 1.25rem margin-left on top of
       that for its numeral. A bare "calc(40rem + gap)" landed the lead-in
       20px past the display edge on Work's agenda (caught with a real
       getBoundingClientRect() check, not just visual inspection) — each
       selector below subtracts its own container's indent so every
       lead-in still lands exactly on the display edge regardless of
       which list it authors from. A bare paragraph has no indent, so its
       calc is unchanged. */
    .content > ul:not(.home-rows) > li > strong:first-child:has(+ br) {
        left: calc(var(--block) + var(--gutter-gap) - 1.25rem);
    }
    .content > ol > li > strong:first-child:has(+ br) {
        left: calc(var(--block) + var(--gutter-gap) - 2.5rem);
    }
    .content > p > strong:first-child:has(+ br) {
        left: calc(var(--block) + var(--gutter-gap));
    }
    .content > ul:not(.home-rows) > li > strong:first-child:has(+ br),
    .content > ol > li > strong:first-child:has(+ br),
    .content > p > strong:first-child:has(+ br) {
        position: absolute;
        /* first baseline on the line's first baseline (ops/BRIEF.md §2
           anchor rule), not top-aligned: 13px beside a 20px line */
        top: var(--baseline-lead);
        right: auto;
        width: var(--gutter-width);
        text-align: right;
        font-family: var(--font-body);
        font-weight: 600;
        font-size: var(--t-meta);
    }
    .content > p > strong:first-child:has(+ br) {
        top: var(--baseline-lead-p);
    }
    /* The <br> that separated the lead-in from its line, now redundant —
       the lead-in no longer occupies the start of that line at all. */
    .content > ul:not(.home-rows) > li > strong:first-child + br,
    .content > ol > li > strong:first-child + br,
    .content > p > strong:first-child + br {
        display: none;
    }
}

.content > pre {
    background: var(--c-ink);
    color: var(--c-ground);
    font-family: var(--font-mono);
    font-size: var(--t-meta);
    line-height: 1.6;
    padding: var(--space-1);
    overflow-x: auto;
}
.content code {
    font-family: var(--font-mono);
    font-size: 0.9em;
}

.content > table {
    display: block;
    overflow-x: auto;
}
.content > table th,
.content > table td {
    border-bottom: 1px solid var(--c-ink);
    padding: var(--space-1) 0;
    text-align: left;
}
.content > table th {
    font-family: var(--font-body);
    font-weight: 600;
    font-size: var(--t-meta);
}
.content > table td {
    font-family: var(--font-body);
    font-size: var(--t-body);
}

/* Footnotes: a list at the end of the body at --t-meta, with back-links
   (ops/BRIEF.md §7). Best-effort — Ghost's Lexical editor has no native
   footnote card; this styles whatever hand-authored markup uses these
   conventional class/id names, and is unverified against real content. */
.content .footnotes,
.content [id^="fn"],
.content [class*="footnote"] {
    font-size: var(--t-meta);
}

/* Beat 3 action heading — the theme-rendered ask on a post (not a Ghost
   card). Post title and post ask share one size: --t-step (30px), below
   the 1.953rem one-line threshold, so it wraps, balanced, instead of
   forcing a line (ops/BRIEF.md §4 Scale, "Display budgets" — this closes
   the post/issue one-line failure the scale check found: these fields
   run to 60 characters and were never going to fit on one line). */
.action-heading {
    font-family: var(--font-body);
    font-weight: 600;
    font-size: var(--t-step);
    line-height: 1.15;
    letter-spacing: -0.01em;
    text-wrap: balance;
}
.beat-close.is-free .signup-form { margin-top: var(--space-1); }
.beat-close .btn { margin-top: var(--space-1); }

/* .beat-close.band: the theme-rendered ask on a post (Article's link,
   Issue's non-member Signup) — the SAME close anatomy as the Ghost
   Signup/Header card above (hairline, long pause, padding-top), but
   native markup rather than a Ghost card, so it needs its own copy of
   the rule (ops/BRIEF.md §1 "The close"; 2026-09-14 close-B pass). The
   class name ".band" is unchanged from the previous round (renaming it
   is a template edit with no visual effect, out of scope for a CSS-only
   pass) but it no longer means "landing band" — no background, no
   breakout, no ground swap. Normal flow, same paper as the rest of the
   page. */
.beat-close.band {
    border-top: 1px solid var(--c-ink);
    margin-top: var(--space-turn);
    padding-top: var(--space-2);
}
@media (min-width: 1280px) {
    /* margin-left: 0, not a viewport-relative calc() — same fix, and the
       same reason, as the Ghost-card close above: ".beat-close.band" is a
       direct child of "main.block", whose own content box already IS the
       40rem column, centred. Growing the box to 56rem with no left
       offset overflows the column's own right edge by 16rem, landing on
       the display edge without ever approaching the viewport's edge. */
    .beat-close.band {
        width: 56rem;
        max-width: 56rem;
        margin-left: 0;
        margin-top: var(--space-3);
    }
}
/* Heading, button/link and form all sit at the column's own width — the
   close is no longer wider than the column except for its own hairline
   (the box itself, above), so no margin-left push is needed any more
   (2026-09-14 close-B pass; see the matching comment on the Ghost-card
   alignment rule for why the old "50% - block/2" formula is retired). */
.beat-close.band .action-heading,
.beat-close.band .btn,
.beat-close.band .signup-form {
    margin-left: 0;
    margin-right: 0;
    max-width: var(--block);
}
.beat-close.band .action-heading {
    text-wrap: balance;
}

/* THE FOOTER (ops/BRIEF.md §6 Footer; ops/DECISIONS.md Ruling 2): one
   line, on the page's own ground, --space-turn below the last element of
   main — no band to join any more, so every page reaches the footer the
   same way, through the ordinary beat-to-footer margin already declared
   on ".site-footer" (§5 Grid primitives). The old per-template
   "footer joins the band" rewrite (background swap, breakout, its own
   focus-ring override) is deleted outright, not adjusted — there is
   nothing left for the footer to join. */
/* Under any page whose close holds a signup form (Home, Read, Newsletter,
   an Issue, and a gated Article's fallback), the footer's "Sign up" link
   is redundant with the form directly above it — hide it (ops/BRIEF.md
   §1, §6). ":has(.kg-signup-card, .signup-form)" on <body> matches
   regardless of which of the two markup shapes rendered the form,
   without needing the previous per-template ":last-child" chain (that
   chain existed only to detect "the band is the page's last element",
   which mattered when joining required exact adjacency to the footer;
   a plain page-wide :has() is sufficient and simpler now that the footer
   is never restyled, only conditionally hides one nav item). */
body:has(.kg-signup-card, .signup-form, [data-members-form]) .footer-nav li:has(a[href*="#/portal"]) {
    display: none;
}

/* Feature photo on an article: always a scene, a 3:2 rectangle at the
   column's width (ops/BRIEF.md §7 "Article", §8 "Article feature images
   are always scenes"; 2026-09-13 critique-home-03 pass — was a 28.5rem
   circle under critique-home-02, before Adam's rectangle decision).
   ".feature-photo" shares the ".scene-photo" base class with the
   article-row thumbnail, so the size and the caption fix below are scoped
   to ".feature-photo" alone rather than changed on the shared base —
   2026-09-12 critique ruling, ops/DECISIONS.md.

   Sized the same way, and for the same reason, as the page image card
   above: aspect-ratio on the <figure> (a plain element, so it has no
   natural ratio of its own to fight), not the <img> (a replaced element
   whose HTML width/height attributes win the ratio fight in the
   sign-off Chrome — see the long comment above). ".scene-photo img"
   already gives the <img> the matching width: 100%; height: 100%;
   object-fit: cover; filter it needs — both dimensions are explicit, not
   auto, so there is nothing left for the browser to compute from its
   intrinsic ratio. overflow stays visible (cancelling the base class's
   overflow: hidden) so the figcaption, which follows the image inside the
   same figure, is never clipped. */
.feature-photo {
    width: 100%;
    max-width: var(--block);
    aspect-ratio: 3 / 2;
    overflow: visible;
}
.feature-photo figcaption {
    margin-top: var(--offset-tight);
    text-align: right;
}
.feature-photo + * {
    margin-top: var(--space-2);
}

/* Page lede: Newsreader 400 at --t-step, line height 1.3 (ops/BRIEF.md §4
   Scale). Runs the column's width (unrestricted — only body copy,
   quotes, lists and h2/h3 take the narrower reading measure, §2 Grid).
   Post lede (below) is a size up, at a slightly looser line height.
   Note this covers page excerpts and post ledes both, per the same
   selector already used across page.hbs and post.hbs. */
.lede {
    font-family: var(--font-body);
    font-weight: 400;
    font-size: var(--t-sub);
    line-height: 1.35;
    text-wrap: pretty;
}
/* Post lede: --t-sub, line height 1.35 (ops/BRIEF.md §4 Scale, "post
   lede"). */
.article-body .lede,
.issue-article .lede {
    font-size: var(--t-sub);
    line-height: 1.35;
}

/* Page h1: --t-display, shared with the page's action heading — Adam's
   2026-09-13 decision retiring "the largest type on a page is its
   action" (ops/DECISIONS.md; ops/BRIEF.md §4 Scale). Post h1 (.post-title,
   below) sits at --t-step instead, alongside the post ask.

   2026-09-13 critique-home-04 pass, ruling 3: the h1 no longer runs past
   the column — there is one 40rem measure everywhere now, and a display
   heading balances over at most two lines within it instead. This retires
   pass 3's "width: max-content" workaround (recorded here because it was a
   real, caught-in-review bug worth remembering the shape of): that hack
   existed only because the heading's target width was WIDER than its own
   parent, which a plain max-width can never achieve on a block box. Now
   that the target width and the parent's width are the same 40rem, a
   plain block with max-width: var(--block) already sizes correctly with
   no special-cased width property and no <900px override to undo. The
   one-line nowrap treatment (>= 900px) lives at the true end of the file
   — see §15. */
.page-title {
    font-family: var(--font-body);
    font-weight: 500;
    font-size: var(--t-display);
    line-height: 1.05;
    letter-spacing: -0.02em;
    max-width: var(--block);
    text-wrap: balance;
}
/* Post title and post ask heading share one size and treatment: --t-step
   (30px), below the one-line threshold, so they wrap, balanced, rather
   than forcing a single line (ops/BRIEF.md §4 Scale, "Display budgets" —
   this closes the post/issue one-line failure the scale check found). */
.post-title {
    font-family: var(--font-body);
    font-weight: 600;
    font-size: var(--t-step);
    line-height: 1.15;
    letter-spacing: -0.01em;
    text-wrap: balance;
}
/* Month heading (an issue's own "the month" section head — post.hbs):
   Newsreader 600, -0.01em, line height 1.2, same treatment as a page's
   own h2 (ops/BRIEF.md §4 Scale, "page h2 and month headings"). */
.section-head {
    font-family: var(--font-body);
    font-weight: 600;
    font-size: var(--t-step);
    line-height: 1.2;
    letter-spacing: -0.01em;
}
.index-cross-link {
    font-family: var(--font-body);
    font-size: var(--t-body);
}

/* HOME'S SECOND ACT (2026-09-13 critique-home-04 pass; reworked in
   critique-home-06 into the pitch + Work link + catalogue label;
   ops/BRIEF.md §7 Home; ops/DECISIONS.md "Adam ... Home gets a short
   second act"). page.hbs renders the catalogue label, the rows and
   home-close's card straight into .content, after {{content}}, only on
   the page bound to "/" (.page-home) — see page.hbs's own long comment
   for why {{#is "home"}} over the slug. The pitch and the Work link are
   themselves plain Ghost body content (home's own second-to-last and
   last authored paragraphs) — no template markup for them, found here by
   adjacency, same as everything else in this file.

   NEITHER THE PITCH NOR THE WORK LINK HAS A CLASS OF ITS OWN: they are
   simply the last two paragraphs Ghost's body content emits before this
   template's own catalogue label/rows and home-close's card follow them.
   ":has()" is how each is found. This can't be ":last-child"/
   ":nth-last-child()" — the literal selectors the handoff itself
   suggests — because the rows, the label and home-close's card are all
   appended into the SAME .content div (see above), so neither paragraph
   is actually .content's last or second-to-last DOM child any more (the
   Signup card is last).

   Two variants each, because what follows the Work link differs: the
   catalogue label (rows on and non-empty) or directly the Signup card
   (rows off, or the query returned none). The pitch is found by looking
   TWO siblings ahead, ":has(+ p + X)" — a single relative selector with a
   two-step sibling combinator chain, not ":has()" nested inside ":has()"
   (which the spec disallows) — checked directly against the live page,
   and it matches. Because the Work link's own immediate next sibling is
   always the label or the card directly (never another <p> first), the
   pitch's own two-hop selector can never also match the Work link, so
   this needs no extra ":not()" the way the identity line's selector did
   in earlier rounds. */
/* Stratum 3, "proof -> pitch" (ops/BRIEF.md §7 "Four strata", §3 "Gaps
   never add"; 2026-09-14 close-B pass, ops/DECISIONS.md Ruling 3):
   --space-turn at EVERY width now, not just below 1280px — with the band
   gone, the page's one long pause moved to the close (the hairline's own
   margin-top, above), so this seam no longer competes for "the largest
   gap on Home". Declared once, here, on the pitch's own margin-top — the
   tier-1 attribution's cancelled footprint (above) means this is the
   only value read for the seam, never summed with it. */
.page-home .content > p:is(:has(+ p + .catalogue):not(.kg-image-card + p), :has(+ blockquote + .kg-image-card + p + p + .catalogue), :has(+ blockquote + .kg-image-card + p + .catalogue), :has(+ blockquote + .kg-image-card + p + .offer)),
.page-home > .content > p:has(+ p + .kg-signup-card) {
    font-family: var(--font-body);
    font-weight: 500;
    font-size: var(--t-head);
    letter-spacing: -0.015em;
    line-height: 1.1;
    margin-top: var(--space-turn);
}
/* The Work link: apparatus, a control label, Poppins 700 (ops/BRIEF.md §4
   Families, chrome, never Newsreader) — moved from 18px to --t-meta
   (2026-09-14 pass-8, item 7). Below 1280px it sits --space-1 below the
   pitch, right-aligned at the column's right edge (no gutter); >= 1280px
   it hangs in the RIGHT gutter (Adam's ruling, 2026-09-20), level with the
   pitch, via the SAME margin technique as the tier-1/tier-2 attributions
   above — the pitch is guaranteed exactly one line (ops/BRIEF.md §4
   Display budgets, "the one-line rule"), so its line-box height is
   deterministic, unlike a catalogue row's variable-length excerpt, which
   needs true absolute positioning instead (see §11 below). */
.page-home .content > p:has(+ .catalogue):not(.kg-image-card + p),
.page-home > .content > p:has(+ .kg-signup-card) {
    font-family: var(--font-title);
    font-weight: 700;
    font-size: var(--t-meta);
    letter-spacing: 0.01em;
    text-align: right;
    margin-top: var(--space-1);
}
@media (min-width: 1280px) {
    .page-home .content > p:has(+ .catalogue):not(.kg-image-card + p),
    .page-home > .content > p:has(+ .kg-signup-card) {
        width: var(--gutter-width);
        /* + --baseline-head: drops the 13px line so its baseline sits ON
           the pitch's first baseline, not 16px above it (round 2, the
           anchor rule refined to baselines, ops/BRIEF.md §2). The same
           amount comes back off margin-bottom so the flow below is
           unchanged. */
        margin-top: calc(-1.1 * var(--t-head) + var(--baseline-head));
        margin-left: calc(var(--block) + var(--gutter-gap));
        margin-bottom: calc(-1 * (var(--t-meta) * 1.4) - var(--baseline-head));
    }
}
/* Work link -> catalogue: --space-turn, now on the ".catalogue" wrapper
   (page.hbs, 2026-09-14 pass-8) rather than on the label itself, since the
   label moves out of flow at >= 1024px (below) and can no longer carry the
   block's own top margin. Label -> first hairline: the tight offset below
   1024px; >= 1024px the label hangs in the gutter, LEVEL WITH the first
   hairline (ops/BRIEF.md §2 "the catalogue label, level with the first
   row's hairline") — achieved by making ".catalogue" the positioned host
   (it wraps both the label and ul.home-rows, added in page.hbs for exactly
   this) and taking the label out of flow, so ul.home-rows becomes
   ".catalogue"'s first in-flow child and starts right at its own top edge,
   with nothing left to level against but that.

   ".catalogue > h2.catalogue-label", not the bare class: the generic body
   h2 rules (§10) reach ".content > h2" (a class + a type) for the
   meta-tier font-size/tracking, and — because .catalogue-label's ancestor
   <main> also carries .page-article — ".page-article .content > h2" (two
   classes + a type) for margin-top: var(--space-3), the "a body h2 opens
   the next section" rule. Both would otherwise outrank a bare
   ".catalogue-label" (one class) and silently turn it into a 27px section
   heading 160px below the Work link. Matching their own specificity with
   extra ancestor classes, the same convention this file already uses
   against Ghost's injected card CSS, clears both ties. */
.page-home .content > .catalogue,
.article-body .content > .catalogue {
    margin-top: var(--space-turn);
}
.page-home .content .catalogue > h2.catalogue-label,
.article-body .content .catalogue > h2.catalogue-label {
    font-family: var(--font-title);
    font-weight: 700;
    font-size: var(--t-meta);
    letter-spacing: 0.01em;
    text-align: right;
}
.page-home .content .catalogue > h2.catalogue-label + ul.home-rows,
.article-body .content .catalogue > h2.catalogue-label + ul.home-rows {
    margin-top: var(--offset-tight);
}
@media (min-width: 1280px) {
    .page-home .content > .catalogue,
    .article-body .content > .catalogue {
        position: relative;
    }
    .page-home .content .catalogue > h2.catalogue-label,
    .article-body .content .catalogue > h2.catalogue-label {
        position: absolute;
        top: 0;
        left: calc(var(--block) + var(--gutter-gap));
        right: auto;
        width: var(--gutter-width);
    }
    .page-home .content .catalogue > h2.catalogue-label + ul.home-rows,
    .article-body .content .catalogue > h2.catalogue-label + ul.home-rows {
        margin-top: 0;
    }
}
/* The catalogue label's underline-at-rest and generated arrow are set
   once, in the shared "STANDALONE ARROW LINKS" rule in §6 above, alongside
   the Work link and every outward link (ops/BRIEF.md §5, §2 item 12,
   2026-09-14 pass-8, Ruling 5) — not repeated here. */

/* 11. Catalogue rows — Home and /writing/ (ops/BRIEF.md §7 "Home", "the
   catalogue row"; "Read"). One shared rule set for both: Home's rows are
   <li> inside <ul class="home-rows">, /writing/'s (and, sharing the same
   look, tag/author's mixed-row.hbs) are <div> inside .beat-list — the
   spec is "shared by Home and /writing/" in appearance, not literally one
   markup shape, so a combined selector list is how that's built.

   2026-09-13 critique-home-05 pass, ruling 4: hairlines return here
   specifically (§11 "hairline rules as structure" bans them everywhere
   else) — a border-top on every row and a border-bottom on the last,
   padding-block: var(--space-1) inside, replacing critique-home-04's
   plain margin-based row gap entirely (a hairline plus padding both
   separates rows and marks the turn into the catalogue, so no separate
   margin is needed between rows any more). */
.home-row,
.article-row {
    border-top: 1px solid var(--c-ink);
    padding-block: var(--space-1);
    margin: 0;
    /* Positioned host for the meta line's absolute placement at >= 1024px
       (below) and, on .article-row, the thumbnail margin figure
       (2026-09-14 pass-8). No effect on normal flow at any width. */
    position: relative;
}
.home-rows > .home-row:last-child,
.article-row:last-child {
    border-bottom: 1px solid var(--c-ink);
}
/* Home's catalogue label sits on the first row's hairline (the anchor
   rule's "on the rule" case). At --space-1 the first row's title and
   meta sat 25px under the label, so label and meta read as one two-line
   rail entry (build review 22). The first row gets --space-2 above its
   content instead: the label's own clear space, on the scale. The meta's
   absolute `top` reads the same custom property, so it follows. */

/* ...except when the close's own rule is the next line down (build review
   19, Home gate 6): the list's trailing 640px rule and the close card's
   896px rule sat 162px apart at different widths and read as ONE doubled
   rule with a hole punched in it. Far enough apart that the CDP seam check
   (pairs within 16px) never saw it. The close's rule wins the seam — it is
   the wider of the two and it is the one marking the turn out of the
   catalogue — so the list simply stops. Two shapes, because Home nests the
   rows in ".catalogue" with the card as its next sibling, while /writing/
   ends a ".beat" and opens a separate ".beat-close". */
.catalogue:has(+ .kg-card) > .home-rows > .home-row:last-child,
.beat:has(+ .beat-close) .article-row:last-child,
.article-body .content > .catalogue > .home-rows > .home-row:last-child {
    border-bottom: 0;
}
/* /writing/'s row thumbnail (ops/BRIEF.md §2 Grid, §7 Read; 2026-09-14
   pass-8, Ruling 2): below 1024px it is a plain 152px-wide 3:2 rectangle
   ABOVE the row text, left-aligned — normal flow, thumbnail-link first,
   text second, exactly the shape a `display: block` row already gives
   these two children with no rule needed here beyond sizing. The old
   >= 900px side-by-side flex row (photo left of text) is retired outright:
   this pass moves that job to the >= 1024px gutter instead. */
.article-row-photo {
    width: 9.5rem;
    aspect-ratio: 3 / 2;
}
.article-row-text { min-width: 0; }
@media (min-width: 1280px) {
    /* >= 1280px: the thumbnail becomes a margin figure — a margin pull
       into the RIGHT gutter (Adam's ruling, 2026-09-20; same technique as
       every other apparatus item in this file), top-aligned with the row
       title (ops/BRIEF.md §2, "top-aligned with the row title").
       .article-row-text's own top already IS the row title's top (the
       title is its first child), so this only needs to zero the
       thumbnail's own flow height (a negative margin-bottom) rather than
       track the title precisely — simpler and exactly as reliable as the
       tier-1/Work-link technique above, because the thumbnail's own
       height (a fixed 3:2 box) is deterministic, unlike a
       variable-length excerpt. */
    .article-row-photo-link {
        display: block;
        width: var(--gutter-width);
        margin-left: calc(var(--block) + var(--gutter-gap));
        margin-bottom: calc(-1 * (var(--gutter-width) * 2 / 3));
    }
    .article-row-photo {
        width: 100%;
    }
    /* Row text starts on the column axis (ops/BRIEF.md §7 Read, "Row text
       starts at the column edge"): with the thumbnail pulled fully into
       the gutter above, .article-row-text is already the row's only
       in-flow, full-width box, so no width override is needed here. */
}
/* Title: Newsreader 600 at --t-sub (24px), -0.005em, line height 1.2,
   text-wrap: balance (ops/BRIEF.md §4 Scale — "never a single word alone
   on the last line", Ruling 4; no pixel budget, balance alone is the
   fix), underlined only on hover/focus (never a hairline the reader could
   mistake for the row's own rule). */
.home-row-title,
.article-row-title {
    font-family: var(--font-body);
    font-weight: 600;
    font-size: var(--t-sub);
    line-height: 1.2;
    letter-spacing: -0.005em;
    text-wrap: balance;
}
/* Excerpt: the tight offset below the title. The clamp is a SAFETY NET
   only, not the primary control (2026-09-13 critique-home-06 pass, ruling
   4) — excerpts are written to fit (<= 140 characters as of the
   2026-09-14 Newsreader pass, two 640px lines), so the clamp rarely
   engages. 2 lines at every width >= 900px (2026-09-14 pass-8: /writing/'s
   row text now runs the FULL 640px column at every width, like Home's,
   since the thumbnail is a gutter margin figure from 1024px and a plain
   stacked block above the text below that — there is no narrower,
   photo-beside-text column left to budget for any more). Both drop to 4
   below 900px, where a stacked photo leaves the column its own full width
   but at a narrower device. Newsreader 400, line height 1.6, matching
   body leading (2026-09-14 pass-8, item 7 — was 1.5). */
.home-row-excerpt,
.article-row-excerpt {
    margin-top: var(--offset-tight);
    font-family: var(--font-body);
    font-weight: 400;
    font-size: var(--t-body);
    line-height: 1.6;
    -webkit-line-clamp: 2;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
@media (max-width: 899px) {
    .home-row-excerpt,
    .article-row-excerpt {
        -webkit-line-clamp: 4;
    }
}
.article-row-excerpt-link { color: var(--c-ink); border-bottom: none; }
/* Meta line: apparatus, "{primary tag} · {N} min read" — no date, ever
   (ops/BRIEF.md §9's Record veto). The tag links to its own tag page in
   the inherited link style; reading_time is plain Ghost-produced text.
   Below 1024px: the tight offset below the excerpt, right-aligned, same
   as before. >= 1024px (ops/BRIEF.md §2, "level with the row title"): true
   `position: absolute` against the row itself (".home-row"/".article-row",
   both positioned hosts, above) — NOT a negative-margin pull, because the
   excerpt between the title and this meta line is variable-length body
   copy, so a fixed negative margin could never reliably track "the row
   title's first line" the way it can for the tier-1 unit or the Work
   link, whose preceding siblings have deterministic heights. Absolute
   positioning against the row's own top edge sidesteps the excerpt's
   height entirely. */
.home-row-meta,
.article-row-meta {
    margin-top: var(--offset-tight);
    text-align: right;
}
/* "N min read" must never break internally (2026-09-14 gate-6 pass-9): at
   the 1024-1279px narrow gutter (128px), "{tag} · 4 min read" wrapped
   with the "4" stranded alone on its own line — the tag can wrap, but
   the reading-time phrase must move as one unit. ".reading-time" wraps
   Ghost's own {{reading_time}} output (page.hbs, writing.hbs,
   mixed-row.hbs, post.hbs's article/issue meta line) for exactly this
   rule; it carries no other styling of its own. */
.reading-time {
    white-space: nowrap;
}
@media (min-width: 1280px) {
    .home-row-meta,
    .article-row-meta {
        position: absolute;
        /* + --baseline-sub: the 13px meta shares the 24px title's first
           baseline instead of top-aligning to it (round 2). */
        top: calc(var(--row-pad-top, var(--space-1)) + var(--baseline-sub));
        left: calc(var(--block) + var(--gutter-gap));
        right: auto;
        width: var(--gutter-width);
        margin-top: 0;
    }
    /* An article row that carries a thumbnail (ops/BRIEF.md §7 Read: "an
       article carries a photograph") already fills the SAME gutter slot
       with the margin-figure photo, top-aligned with the title (§11
       above) — caught in review, both apparatus items landed on the exact
       same rect, the meta line's text rendering on top of the photo. The
       fix stacks the meta line below the photo, inside the gutter, rather
       than level with the title: `top` becomes the photo's own height
       (gutter-width * 2/3, its 3:2 ratio) plus the tight offset, the same
       "photo -> caption" spacing this file uses everywhere else a
       photograph is followed by a smaller apparatus line. Rows with no
       photo (Home's rows always; a /writing/ or tag/author row whose post
       has no feature_image) are unaffected and keep the plain
       level-with-the-title position, above. */
    .article-row:has(.article-row-photo-link) .article-row-meta {
        top: calc(var(--space-1) + (var(--gutter-width) * 2 / 3) + var(--offset-tight));
    }
    /* The photo + meta stack in the gutter is now taller than a short
       row's own in-flow content (title + a one- or two-line excerpt) can
       be — since both are `position: absolute` and don't otherwise add
       to the row's own height, a short row let the stack overflow past
       its own bottom border into the NEXT row (caught in review: the
       meta line rendered inside the following row's photo). min-height
       guarantees the row is always at least as tall as its own gutter
       content: top and bottom padding, plus the photo's height, the
       tight offset, and one meta line. */
    .article-row:has(.article-row-photo-link) {
        min-height: calc(2 * var(--space-1) + (var(--gutter-width) * 2 / 3) + var(--offset-tight) + (var(--t-meta) * 1.4));
    }
}

.newsletter-month + .newsletter-month { margin-top: var(--space-2); }
.newsletter-month-head > * + * { margin-top: var(--space-1); }
/* A month heading (ops/BRIEF.md §4 Scale, "page h2 and month headings":
   600, -0.01em, line height 1.2). */
.newsletter-month-name {
    font-family: var(--font-body);
    font-weight: 600;
    font-size: var(--t-step);
    line-height: 1.2;
    letter-spacing: -0.01em;
    display: block;
}
/* The month's date range is apparatus, right-aligned below 1024px
   (ops/BRIEF.md §7 Newsletter, §2 "level with the month heading"); >=
   1024px it hangs in the gutter via `position: absolute` against
   ".newsletter-month-head" (already the shared parent of the heading and
   the range in newsletter.hbs) — true absolute positioning, not a
   negative-margin pull, since the heading's own height is variable
   (month names differ in length and can wrap). */
.newsletter-month-range {
    display: block;
    text-align: right;
}
@media (min-width: 1280px) {
    .newsletter-month-head {
        position: relative;
    }
    .newsletter-month-range {
        position: absolute;
        top: 0;
        left: calc(var(--block) + var(--gutter-gap));
        right: auto;
        width: var(--gutter-width);
        margin-top: 0;
    }
}
.newsletter-issue-row {
    display: flex;
    align-items: baseline;
    gap: var(--space-1);
}
.newsletter-issue-row + .newsletter-issue-row,
.newsletter-issue-row + p.newsletter-issue-excerpt + .newsletter-issue-row {
    margin-top: var(--space-1);
}
/* Issue row titles: Newsreader 600 at --t-body (ops/BRIEF.md §4 Scale).
   No numeral (2026-09-14 pass-8, Ruling 3: "issue rows carry no numeral")
   — ".newsletter-issue-num" and its flex-basis slot are removed outright,
   not just hidden, and the excerpt's own indent (previously matching the
   numeral's 2.5rem + gap) goes with it, so the excerpt starts flush with
   the title above it. */
.newsletter-issue-title {
    font-family: var(--font-body);
    font-weight: 600;
    font-size: var(--t-body);
}
.newsletter-issue-excerpt {
    font-family: var(--font-body);
    font-size: var(--t-body);
    line-height: 1.6;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 1;
    overflow: hidden;
}

/* An issue's own meta line reads "{month name} · {send date}", no week
   numeral (2026-09-14 pass-8, Ruling 3). Newsreader 600 at --t-body
   (ops/BRIEF.md §4 Scale) — month/date keep the same weight for one
   consistent meta-line (2026-09-12 critique ruling, unchanged by this
   pass). 700 is not in the loaded weight range (400-600), so 600 replaces
   it here too. */
.issue-month, .issue-date {
    font-family: var(--font-body);
    font-weight: 600;
}

/* 12. Utility pages, build-guard flag, placeholders
/* ---------------------------------------------------------- */
.utility-article .beat-list > * + * { margin-top: var(--space-2); }

/* Loud on purpose — a build defect signal, never content
   (partials/components/limit-cap-flag.hbs). Stays inside the closed
   palette (ops/BRIEF.md §12 item 1) — inverted ink/ground plus a thick
   commercial-fill border reads as obviously broken without introducing a
   colour the rest of the system doesn't already use. Should never render
   in a passing build. */
.build-guard-flag {
    background: var(--c-ink);
    color: var(--c-ground);
    border: 4px solid var(--c-commercial);
    padding: var(--space-1);
    font-family: var(--font-title);
    font-weight: 700;
}

/* No .placeholder utility here: the theme's own asks (post.hbs) read
   @custom.article_ask_heading etc. directly, and Ghost always supplies
   package.json's [ADAM: ...] default text until Adam fills the setting
   in — so the placeholder string is guaranteed non-empty and a
   {{#if}}/{{else}} fallback would be dead code. [COPY:.../[MARKETER:...
   strings live in Ghost-authored content, not in the theme, and marking
   them is ghost-marketer/ghost-builder's job, not something CSS can do
   (there is no way to select arbitrary text content). */

/* 13. Motion (ops/BRIEF.md §10, reduced) — every transition in this file
   reads --motion-duration rather than a literal 120ms, so reduced motion
   is one variable flip, never a specificity fight or a forced-priority declaration. */
:root {
    --motion-duration: 120ms;
}
@media (prefers-reduced-motion: reduce) {
    :root {
        --motion-duration: 0ms;
    }
}

/* 14. WIDE LAYOUT, >= 1280px (2026-09-13 critique-home-05 pass, ruling 1;
   ops/BRIEF.md §2 Grid). Adam's decision: display elements — the page h1
   and the opening scene photograph — break the 40rem text column at wide
   widths, running right only, while every text block keeps its one left
   edge. Three items of marginalia (the caption, the tier-1 attribution
   unit, and the quote's already-hanging opening mark) move into a 12rem
   rail, 2rem left of the column.

   THIS SECTION MUST STAY LAST IN THE FILE. Caught in review: every
   selector below (.page-title, .feature-photo, the page image card, the
   tier-1 unit) also has a plain, unconditional base rule earlier in this
   file, at the SAME specificity (one class, or the same compound
   selector). A media query adds no specificity of its own — only being
   later in source order lets an equal-specificity rule win once its
   condition is true — so when this block lived earlier in the file
   (immediately after the tier-2 quote rule), every one of its overrides
   that had a same-specificity base rule appearing AFTER it (.page-title
   and .feature-photo both do) was silently losing to that later base
   rule at every width, wide included: the h1 never left 640px and the
   photo never left the column. Moving the whole block here, after
   everything it overrides, is the fix — not raising specificity, which
   this file's own convention reserves for beating Ghost's injected card
   CSS, not its own rules.

   WHAT I DECIDED (the handoff's own "what the receiving agent must
   decide"): no ancestor in this template sets overflow other than <html>'s
   own overflow-x: clip (the landing band's breakout guard, §4) — nothing
   here needs an explicit "overflow: visible" override, because nothing
   between the h1/figure and <html> ever set overflow: hidden in the first
   place, and the widened boxes are sized (below) to always stay within
   the viewport at every width >= 1280px, so <html>'s own clip is never
   reached. "float: none" isn't needed either: the tier-1 attribution unit
   was never floated (§ "TIER-1 UNIT" above uses inline-block, not float),
   and it stays out of float entirely at this breakpoint too — a plain
   block with a negative margin-left, which keeps it in normal flow so it
   still occupies its own height, exactly as the handoff requires. */
/* 15. ONE-LINE DISPLAY HEADINGS, >= 900px (2026-09-14 Newsreader pass,
   ops/BRIEF.md §4 "Display budgets" — measured, unblocked). Every display
   heading at 1.953rem or larger (--t-display, --t-head) sets on one line
   from 900px up: the page h1, page band headings (Signup/Header card
   headings in a page body, and the two indexes' closing cards), and
   Home's pitch. The theme-rendered POST ask heading (.action-heading) and
   .post-title are DELIBERATELY NOT in this list any more — they moved to
   --t-step (30px), below the 1.953rem threshold, and wrap, balanced,
   per Ruling 3 (ops/DECISIONS.md; this closed the post/issue one-line
   failure the scale check found).

   THE FIX FOR THE 900-1023px OVERFLOW IS IN THE TOKEN, NOT HERE:
   --t-display itself now steps to 3.75rem (60px) only at >= 1024px,
   staying at 2.5rem (40px) from 900-1023px (see §1). Home's h1 measures
   753.5px at 60px — 27px over its 788px budget's margin would have been
   fine, but 27px over the OLD 726px budget if it rendered that large as
   early as 900px, per the handoff's own measurement. This nowrap rule
   itself is unchanged by that fix and applies uniformly from 900px: at
   40px the widest live string (Home's h1) is about 502px, comfortably
   inside the formula's own allowance; at 60px (>= 1024px) the widest is
   753.5px, inside its 788px budget.

   Same "width: max-content, not max-width alone" fix as the display edge
   below, and for the same reason: each of these headings' own parent
   stays the 40rem column at every width from 900px up (only the opening
   photograph and the catalogue hairlines get wider, and only at >=
   1280px, below), so a plain max-width alone can never grow the heading
   past its parent — see critique-home-04's original bug writeup, still
   the clearest account of why this project uses width: max-content
   instead of the fit-content keyword, which is bounded by the parent the
   same way max-width is.

   white-space: nowrap forces the true single line the budgets are
   designed for, rather than trusting text-wrap: balance to never wrap —
   if a heading is authored past its budget, nowrap makes the overflow
   visible (this file cannot "report the string" the handoff asks for;
   that's a verification-time check against a live page, done by
   whoever's driving CDP, not something CSS can do) rather than silently
   wrapping it into a second line the one-line rule was supposed to
   prevent. THIS SECTION MUST STAY AFTER every non-conditional base rule
   for the same selectors, for the same reason recorded on the display
   edge below — that bug is exactly why both sections live at the true
   end of the file. */
@media (min-width: 900px) {
    .page-title,
    .content.content .kg-signup-card-content h2.kg-signup-card-heading,
    .content.content .kg-header-card-content h2.kg-header-card-heading,
    .page-home .content > p:is(:has(+ p + .catalogue):not(.kg-image-card + p), :has(+ blockquote + .kg-image-card + p + p + .catalogue), :has(+ blockquote + .kg-image-card + p + .catalogue), :has(+ blockquote + .kg-image-card + p + .offer)),
    .page-home > .content > p:has(+ p + .kg-signup-card) {
        width: max-content;
        max-width: min(56rem, calc(100vw - (100vw - var(--block)) / 2 - 1.25rem));
        white-space: nowrap;
    }
}

/* 16. APPARATUS: the scene photograph's caption, the ONE exception, >=
   1280px only (ops/BRIEF.md §2 Grid, "a photograph's caption is the one
   exception, and it moves"; Adam's ruling, 2026-09-20). A photograph that
   runs to the display edge occupies the gutter for its own height, so its
   caption cannot sit beside it the way every other apparatus item does.
   It drops directly beneath the photograph instead — still apparatus,
   still ending on the same display edge as everything else, just the
   only item that reads below its subject rather than beside it.

   2026-09-21 (the locator-column ruling, ops/BRIEF.md §2): the caption is
   now constrained to the gutter's own 14rem track and offset into it,
   instead of ranging right across the full 56rem. Same terminal edge and
   same style — but a short caption set across 56rem starts at an
   arbitrary x inside the text column and reads as the photograph's own
   footer; set in the gutter's track it reads as the gutter's second
   entry, which is what puts the identifying device on the first screen.
   It wraps to two or three lines at 13px, inside the brief's four-line
   cap. Below
   1280px the photograph is column width, and the plain unconditional
   base rule (.page-article .content > .kg-image-card:first-child
   figcaption / .feature-photo figcaption, above) already sets it
   in-flow and right-aligned — nothing extra is needed there.

   THIS SECTION MUST STAY LAST IN THE FILE. Caught in review, unchanged
   principle from earlier rounds: these selectors also have a plain,
   unconditional base rule earlier in this file, at the SAME specificity
   (one class, or the same compound selector) — a media query adds no
   specificity of its own, so only being LATER in source order lets an
   equal-specificity override win. Moving this block here, after
   everything it overrides, is the fix — not raising specificity, which
   this file's own convention reserves for beating Ghost's injected card
   CSS, not its own rules. */
@media (min-width: 1280px) {
    .page-article .content > .kg-image-card.kg-width-wide:first-child figcaption,
    .page-article .content > .kg-image-card:not(.kg-width-wide):first-child figcaption,
    .feature-photo figcaption {
        position: static;
        display: block;
        width: var(--gutter-width);
        max-width: var(--gutter-width);
        margin: 0.75rem 0 0 calc(var(--block) + var(--gutter-gap));
        text-align: right;
    }
}

/* THE DISPLAY EDGE, >= 1280px only (2026-09-13 critique-home-05 pass,
   ruling 1; ops/BRIEF.md §2 Grid). Adam's decision: display elements —
   the page h1 and the opening scene photograph — break the 40rem text
   column at wide widths, running right only, while every text block
   keeps its one left edge.

   2026-09-14 close-B pass: catalogue hairlines are RETIRED from this
   section outright (ops/DECISIONS.md, the Option-B/close-spec entries,
   "Catalogue hairlines back to column width... the close's rule is now
   the only display-width rule"). Home's and /writing/'s row width:56rem
   override, and the matching max-width cap on the row title/excerpt/meta/
   text, are deleted — rows are unconditionally column-width now, at
   every breakpoint, with no override here. The photograph is the only
   thing left that breaks the column at >= 1280px; the close's own
   hairline (§9 above) is the site's other, and now only other,
   display-width rule. */
@media (min-width: 1280px) {
    .page-article .content > .kg-image-card.kg-width-wide:first-child,
    .feature-photo {
        width: 56rem;
        max-width: none;
    }
}


/* ==========================================================================
   Enquiry form (partials/components/enquiry-form.hbs) — 2026-09-21.
   The site's one door to a conversation; both purpose reviews ranked its
   absence first. Built from parts this file already owns rather than a new
   visual language: ruled fields like the signup input (no fills, no boxes,
   no radii), Poppins meta-tier labels like every other piece of apparatus,
   and the single commercial-underline control the brief allows per page
   (ops/BRIEF.md §5). At >= 1280 the section's label hangs in the right
   gutter on the display edge, exactly like every other locator (BRIEF §2,
   rev 10: a block's exit is legitimate gutter content — "position").
   ========================================================================== */
.enquiry {
    position: relative;
    margin-top: var(--space-2);
}
.enquiry-label {
    font-family: var(--font-title);
    font-weight: 700;
    font-size: var(--t-meta);
    letter-spacing: 0.01em;
    line-height: 1.6;
    margin: 0 0 var(--space-1);
    color: var(--c-ink);
}
@media (min-width: 1280px) {
    .enquiry-label {
        position: absolute;
        top: 0;
        left: calc(40rem + var(--gutter-gap));
        width: var(--gutter-width);
        margin: 0;
        text-align: right;
    }
}
.enquiry-form { margin: 0; }
.enquiry-field { margin: 0 0 var(--space-1); }
.enquiry-field label {
    display: block;
    font-family: var(--font-title);
    font-weight: 700;
    font-size: var(--t-meta);
    letter-spacing: 0.01em;
    color: var(--c-ink);
}
.enquiry-optional { font-weight: 400; }
.enquiry-field input[type="text"],
.enquiry-field input[type="email"],
.enquiry-field textarea {
    display: block;
    width: 100%;
    background: transparent;
    border: none;
    border-bottom: 1px solid var(--c-ink);
    border-radius: 0;
    box-shadow: none;
    padding: 0.5rem 0;
    color: var(--c-ink);
    font-family: var(--font-body);
    font-weight: 400;
    font-size: var(--t-body);
    line-height: 1.6;
}
.enquiry-field textarea { resize: vertical; min-height: 7.5rem; }
/* Honeypot: moved off-canvas rather than display:none, so naive bots still
   see and fill it; aria-hidden and tabindex=-1 in the markup keep people
   and assistive tech away from it. */
.enquiry-trap {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}
.enquiry-status,
.enquiry-fallback,
.enquiry-sent {
    font-family: var(--font-body);
    font-size: var(--t-body);
    line-height: 1.6;
    color: var(--c-ink);
    margin: var(--space-1) 0 0;
}
.enquiry-status:empty { display: none; }
/* Errors are carried by weight as well as wording — never by colour alone. */
.enquiry-status.is-error { font-weight: 600; }
.enquiry-form .btn[disabled] { opacity: 0.5; cursor: default; }


/* ==========================================================================
   HOME, 2026-09-21 (ops/BRIEF.md §1, §2, §3, §7 Home). MUST STAY LAST:
   it overrides the tier-1 unit, the Work link, the catalogue label and the
   Signup-card close at equal or higher specificity.

   1. TWO TIERS OF AIR BETWEEN HOME'S UNITS. --space-3 above each display
      statement (the pitch, the ask's h2); --space-turn at every other seam
      between units (pitch -> catalogue, the close -> footer).
   2. THE TESTIMONIAL IS GLOSS. The quote leaves the reading column: at
      >= 1280px it floats into the gutter, its first baseline on the
      pitch's first baseline, at the meta tier, attribution beneath, then
      the pitch's own exit, "Work with me". The essay runs straight into
      the claim. The portrait chip is not shown on Home.
   3. THE CLOSE DECIDES. The conversation is the one control in the
      column. The newsletter is a rail link (the /newsletter/ page title,
      the standalone arrow-link tier) with the latest issue as its proof,
      beside the control. Home-close's Signup card is not shown.
   ========================================================================== */

/* 1. Rhythm */
/* The pitch (the claim) is matched in both content orders: the older one,
   where the quote came before it, and the current one, where the quote
   follows it. The attribution paragraph is excluded explicitly, since in
   the current order it is also "a p two before the catalogue". */
.page-home > .content > p:is(:has(+ p + .catalogue):not(.kg-image-card + p), :has(+ blockquote + .kg-image-card + p + p + .catalogue), :has(+ blockquote + .kg-image-card + p + .catalogue), :has(+ blockquote + .kg-image-card + p + .offer)) {
    margin-top: var(--space-3);
}
.page-home > .content > .catalogue {
    margin-top: var(--space-turn);
}
.page-home > .content > .home-close {
    margin-top: var(--space-3);
}
/* The masthead is chrome, not the article's first line: on Home the
   first beat sits --space-turn below it, not --space-2. */
main.block.page-home > .beat-opening:first-child {
    margin-top: var(--space-turn);
}
/* The lede's line pitch never tighter than the body's (24 x 1.45 = 34.8
   against 20 x 1.7 = 34). */
.page-home .lede {
    line-height: 1.45;
}

/* 2. The claim and its proof. The quote sits in the reading column
   directly UNDER the claim, at the tier-1 pull-quote scale (--t-sub
   italic, set by the shared tier-1 rule above), --space-2 below it. Its
   attribution is gloss: in the gutter at >= 1280px with its first
   baseline on the quote's first baseline, then the claim's exit, "Work
   with me". No portrait chip on Home. */
.page-home > .content > blockquote + .kg-image-card {
    display: none;
}
.page-home > .content > blockquote:has(+ .kg-image-card) {
    margin-top: var(--space-2);
}
.page-home > .content > blockquote + .kg-image-card + p {
    margin-top: var(--offset-tight);
    margin-bottom: 0;
}
.page-home > .content > blockquote + .kg-image-card + p + p:has(+ .catalogue):not(.kg-image-card + p) {
    margin-top: var(--space-1);
}

@media (min-width: 1280px) {
    /* The catalogue label stands ON its first rule: its baseline 2px
       above the hairline ("Read these first" has no descenders), not the
       full line-box descent above it. */
    .page-home .content .catalogue > h2.catalogue-label {
        top: auto;
        bottom: calc(100% - var(--descent-meta));
    }

    /* The quote floats in the column so the attribution and the Work
       link, in flow and carried into the gutter by margin-left, start at
       the quote's top. The catalogue clears the quote; the quote's own
       margin-bottom is the pause. */
    .page-home > .content > blockquote:has(+ .kg-image-card) {
        float: left;
        width: 100%;
        margin-bottom: var(--space-turn);
    }
    .page-home > .content > blockquote + .kg-image-card + p,
    .page-home > .content > blockquote + .kg-image-card + p + p:has(+ .catalogue):not(.kg-image-card + p) {
        float: none;
        width: var(--gutter-width);
        margin-left: calc(var(--block) + var(--gutter-gap));
        margin-right: 0;
        margin-bottom: 0;
    }
    .page-home > .content > blockquote + .kg-image-card + p {
        margin-top: calc(var(--space-2) + var(--baseline-quote));
    }
    .page-home > .content > .catalogue {
        clear: left;
    }
}

/* 3. The close */
.page-home .home-close > h2:first-child {
    font-family: var(--font-body);
    font-weight: 500;
    font-size: var(--t-head);
    letter-spacing: -0.015em;
    line-height: 1.1;
    text-wrap: balance;
    margin-top: 0;
}
.page-home .home-close > p:has(> a:only-child[href*="/work-with-me/"]) {
    margin-top: var(--space-2);
}
.page-home .home-close > p > a:only-child[href*="/work-with-me/"] {
    display: inline-flex;
    align-items: center;
    color: var(--c-ink);
    font-family: var(--font-title);
    font-weight: 700;
    font-size: var(--t-control);
    line-height: 1.6;
    min-height: 44px;
    padding: 0.75rem 0;
    border-bottom: 0;
    text-decoration-line: underline;
    text-decoration-thickness: 2px;
    text-underline-offset: 0.75rem;
    text-decoration-color: var(--c-free);
    transition: text-decoration-thickness var(--motion-duration) ease-out;
}
.page-home .home-close > p > a:only-child[href*="/work-with-me/"]:hover,
.page-home .home-close > p > a:only-child[href*="/work-with-me/"]:focus-visible {
    text-decoration-thickness: 3px;
}
.page-home .home-close > p > a:only-child[href*="/work-with-me/"]::after {
    content: "\00a0→" / "";
}
/* THE CLOSE IS ONE ACT IN TWO ROWS, on the column's one axis (2026-09-21;
   ops/BRIEF.md §1 and §7 Home; purpose review 03: the newsletter is the
   NOT-YET version of the conversation). Row one: the heading, the
   sentence, the conversation's control — the one underlined control on the
   page. Row two, beneath it: its own hairline row at the column's width,
   the newsletter's lead-in sentence, then a ruled email field and a quiet
   submit on one line (stacked below 900px). The submit is the standalone
   arrow-link tier — Poppins 700 --t-meta, no underline at rest — so the
   input's rule is the only rule at that seam. Nothing of the close sits in
   the gutter. Ghost's native members form: it subscribes in place. */
.page-home .content.content.home-close > .kg-signup-card {
    display: block;
    border-top: 1px solid var(--c-ink);
    margin: var(--space-2) 0 0;
    padding: var(--space-1) 0 0;
    width: 100%;
    max-width: var(--block);
    background: transparent;
}
.page-home .content.content.home-close .kg-signup-card-content .kg-signup-card-subheading + .kg-signup-card-form {
    margin-top: var(--space-1);
}
.page-home .content.content.home-close .kg-signup-card-content .kg-signup-card-fields {
    flex-direction: row;
    align-items: flex-end;
    gap: var(--space-1);
}
.page-home .content.content.home-close .kg-signup-card-content .kg-signup-card-input {
    flex: 1 1 auto;
    width: auto;
    min-height: 44px;
}
.page-home .content.content.home-close .kg-signup-card-content .kg-signup-card-button {
    flex: 0 0 auto;
    width: auto;
    min-height: 44px;
    font-size: var(--t-meta);
    letter-spacing: 0.01em;
    line-height: 1.4;
    text-decoration-line: none;
}
.page-home .content.content.home-close .kg-signup-card-content .kg-signup-card-button:hover,
.page-home .content.content.home-close .kg-signup-card-content .kg-signup-card-button:focus-visible {
    text-decoration-line: underline;
    text-decoration-thickness: 2px;
    text-underline-offset: 0.35em;
}
@media (max-width: 899px) {
    .page-home .content.content.home-close .kg-signup-card-content .kg-signup-card-fields {
        flex-direction: column;
        align-items: stretch;
        gap: var(--offset-tight);
    }
    .page-home .content.content.home-close .kg-signup-card-content .kg-signup-card-button {
        align-self: flex-start;
    }
}

/* The price section's anchor on Work (Adam's ruling, 2026-09-21: Home's
   conversation link lands on Work's price). An empty "#price" element the
   content places directly before the price card; breathing room above. */
#price {
    scroll-margin-top: var(--space-2);
}


/* ==========================================================================
   THE LEDGER (2026-09-21; ops/BRIEF.md §2, §7 Home and Work). A body list
   on a PAGE whose items all open with a lead-in (a bold verb, then a line
   break) is a ledger: Home's and Work's STOP / PIVOT / INVEST. It is the
   page's one typographic event after the h1 — the paper the essay says the
   call is already on:
   - statements at --t-sub, Newsreader 400 (a step above body);
   - each row between hairlines; at >= 1280px the hairlines run the whole
     56rem unit, the only rules on the site that cross from the column into
     the gutter, so each verb is joined to its statement by its own rule;
   - the verbs at the statements' size, Newsreader 600, right-aligned on the
     display edge at >= 1280px, sharing the statement's first baseline (same
     size and leading, so top-aligned boxes share it exactly); below 1280px
     each verb sits on its own line above its statement, as authored.
   Posts are excluded (.page-article): an article's lead-in lists stay
   ordinary lists.
   ========================================================================== */
.page-article .content > ul:not(.home-rows):has(> li > strong:first-child + br) {
    padding-left: 0;
    margin-top: var(--space-2);
}
.page-article .content > ul:not(.home-rows):has(> li > strong:first-child + br) > li {
    font-size: var(--t-sub);
    line-height: 1.35;
    text-wrap: pretty;
    padding-block: var(--space-1);
    border-top: 1px solid var(--c-ink);
}
.page-article .content > ul:not(.home-rows):has(> li > strong:first-child + br) > li:last-child {
    border-bottom: 1px solid var(--c-ink);
}
.page-article .content > ul:not(.home-rows):has(> li > strong:first-child + br) > li::before {
    content: none;
}
.page-article .content > ul:not(.home-rows):has(> li > strong:first-child + br) > li > strong:first-child {
    font-family: var(--font-body);
    font-weight: 600;
    font-size: inherit;
}
@media (min-width: 1280px) {
    .page-article .content > ul:not(.home-rows):has(> li > strong:first-child + br) {
        width: calc(var(--block) + var(--gutter-gap) + var(--gutter-width));
    }
    .page-article .content > ul:not(.home-rows):has(> li > strong:first-child + br) > li {
        padding-right: calc(var(--gutter-gap) + var(--gutter-width));
    }
    .page-article .content > ul:not(.home-rows):has(> li > strong:first-child + br) > li > strong:first-child {
        top: var(--space-1);
        left: auto;
        right: 0;
        width: var(--gutter-width);
        font-size: var(--t-sub);
        line-height: 1.35;
    }
}

/* "Read these first" sits on the FIRST TITLE'S baseline, the way a row's
   meta line sits on its title (critics across three panels read the
   on-the-rule setting as floating). The first row's own meta line then
   drops one meta line beneath it, so the rail reads label, then meta. */
@media (min-width: 1280px) {
    .page-home .content .catalogue > h2.catalogue-label {
        top: calc(var(--space-1) + var(--baseline-label));
        bottom: auto;
    }
    .page-home .catalogue .home-rows > .home-row:first-child .home-row-meta {
        top: calc(var(--space-1) + var(--baseline-sub) + var(--t-meta) * 1.4);
    }
}


/* ==========================================================================
   THE SHEET, THE MARGIN, THE RULES (2026-09-21; ops/BRIEF.md §1, §2, §7).

   A. THE SHEET. ".ledger" is the paper the essay says the call is already
      on: a Ghost HTML card (markup in ops/BRIEF.md §7) holding a head line
      and three rows, verb then condition. It is a bounded object: a 2px ink
      rule opens and closes it, 1px rules separate the head and the rows, no
      box, no fill. At >= 1280px it spans the whole 56rem unit, because its
      verbs occupy the margin, and each verb is set at --t-head, Newsreader
      600, right-aligned on the display edge on its condition's first
      baseline — the loudest type after the h1. ".ledger-blank" is its twin
      at the close: the same sheet with empty rows, the reader's paper, an
      image not a form (aria-hidden in the markup; nothing focusable).
   B. THE MARGIN IS FOR ANNOTATION ONLY. "Read these first" and "Work with
      me" come into the column; the margin keeps metadata, attributions and
      the sheet's own verbs.
   C. ONE RULE LOGIC: a rule spans column plus margin wherever the margin
      beside it is occupied (the sheet, catalogue and article rows), and
      the column only where it is empty (the close's not-yet row).
   ========================================================================== */

/* A. The sheet */
.content > .ledger {
    margin: var(--space-2) 0 0;
    padding: 0;
    border-top: 2px solid var(--c-ink);
    border-bottom: 2px solid var(--c-ink);
}
.ledger > .ledger-head {
    margin: 0;
    padding-block: var(--space-1);
    font-family: var(--font-title);
    font-weight: 700;
    font-size: var(--t-meta);
    letter-spacing: 0.01em;
    line-height: 1.4;
    text-align: left;
    color: var(--c-ink);
}
.ledger > dl {
    margin: 0;
}
.ledger .ledger-row {
    position: relative;
    margin: 0;
    padding-block: var(--space-1);
    border-top: 1px solid var(--c-ink);
}
.ledger .ledger-row > dt {
    margin: 0;
    font-family: var(--font-body);
    font-weight: 600;
    font-size: var(--t-step);
    letter-spacing: 0;
    line-height: 1.2;
}
.ledger .ledger-row > dd {
    margin: var(--offset-tight) 0 0;
    font-family: var(--font-body);
    font-weight: 400;
    font-size: var(--t-sub);
    line-height: 1.35;
    text-wrap: pretty;
}
/* The blank twin: rows the height of two written lines, left empty. */
.ledger-blank .ledger-row > dd {
    min-height: calc(2 * 1.35 * var(--t-sub));
}
@media (min-width: 1280px) {
    .content > .ledger {
        width: calc(var(--block) + var(--gutter-gap) + var(--gutter-width));
    }
    .ledger > .ledger-head,
    .ledger .ledger-row {
        padding-right: calc(var(--gutter-gap) + var(--gutter-width));
    }
    .ledger .ledger-row > dt {
        position: absolute;
        top: calc(var(--space-1) + var(--baseline-verb));
        right: 0;
        width: var(--gutter-width);
        text-align: right;
        font-size: var(--t-head);
        line-height: 1;
    }
    .ledger .ledger-row > dd {
        margin-top: 0;
    }
}
/* The blank sheet sits under the close's heading; the sentence follows. */
.page-home .home-close > .ledger {
    margin-top: var(--space-2);
}
.page-home .home-close > .ledger + p {
    margin-top: var(--space-2);
}

/* B. The margin carries annotation only */
.page-home .content .catalogue > h2.catalogue-label {
    text-align: left;
}
.page-home > .content > blockquote + .kg-image-card + p + p:has(+ .catalogue):not(.kg-image-card + p) {
    text-align: left;
}
@media (min-width: 1280px) {
    .page-home .content .catalogue > h2.catalogue-label {
        position: static;
        width: auto;
        margin: 0 0 var(--offset-tight);
    }
    .page-home .catalogue .home-rows > .home-row:first-child .home-row-meta {
        top: calc(var(--space-1) + var(--baseline-sub));
    }
    /* "Work with me", if present, drops under the quote in the column; the
       quote's margin-bottom becomes the small gap above it. Without it the
       catalogue clears the quote at --space-turn, as before. */
    .page-home > .content > blockquote:has(+ .kg-image-card + p + p + .catalogue) {
        margin-bottom: var(--space-1);
    }
    .page-home > .content > blockquote + .kg-image-card + p + p:has(+ .catalogue):not(.kg-image-card + p) {
        clear: left;
        width: auto;
        margin-left: 0;
        margin-top: 0;
    }
}

/* C. One rule logic: rows whose margin is occupied rule across it */
@media (min-width: 1280px) {
    .home-row,
    .article-row {
        width: calc(var(--block) + var(--gutter-gap) + var(--gutter-width));
        padding-right: calc(var(--gutter-gap) + var(--gutter-width));
    }
}


/* ==========================================================================
   THE SHEET HOLDS ITS ACTION; THE ENDING STAYS ON THE FRAME (2026-09-21;
   ops/BRIEF.md §1, §2, §7 Home).
   - The blank sheet's closing row, ".ledger-foot", carries the sentence and
     "Start a conversation" inside the sheet, above its closing 2px rule, so
     the paper and its action are one object. Only the empty rows are
     hidden from assistive tech (aria-hidden on the <dl>); the head line,
     the sentence and the link are read. The link is the only interactive
     element in the sheet.
   - The blank sheet's verbs step down to --t-step: the reader's sheet is
     subordinate to its heading ("Tell me which one's dead.", --t-head);
     the filled sheet keeps --t-head as the page's loudest event.
   - The not-yet row spans the 56rem unit like every other rule on the
     page at >= 1280px: the row's hairline, and one field rule carrying the
     email field and its submit, the submit ending on the display edge as
     part of the field's own line.
   ========================================================================== */
.ledger > .ledger-foot {
    border-top: 1px solid var(--c-ink);
    padding-block: var(--space-1);
}
.ledger > .ledger-foot > p {
    margin: 0;
    font-family: var(--font-body);
    font-weight: 400;
    font-size: var(--t-body);
    line-height: 1.6;
    text-wrap: pretty;
}
.ledger > .ledger-foot > p + p {
    margin-top: var(--space-1);
}
.ledger > .ledger-foot > p > a:only-child {
    display: inline-flex;
    align-items: center;
    color: var(--c-ink);
    font-family: var(--font-title);
    font-weight: 700;
    font-size: var(--t-control);
    line-height: 1.6;
    min-height: 44px;
    padding: 0.75rem 0;
    border-bottom: 0;
    text-decoration-line: underline;
    text-decoration-thickness: 2px;
    text-underline-offset: 0.75rem;
    text-decoration-color: var(--c-free);
    transition: text-decoration-thickness var(--motion-duration) ease-out;
}
.ledger > .ledger-foot > p > a:only-child:hover,
.ledger > .ledger-foot > p > a:only-child:focus-visible {
    text-decoration-thickness: 3px;
}
.ledger > .ledger-foot > p > a:only-child::after {
    content: "\00a0→" / "";
}
.page-home .content.content.home-close > .ledger + .kg-signup-card {
    margin-top: var(--space-turn);
}
@media (min-width: 1280px) {
    .ledger > .ledger-foot {
        padding-right: calc(var(--gutter-gap) + var(--gutter-width));
    }
    .ledger-blank .ledger-row > dt {
        font-size: var(--t-step);
        top: calc(var(--space-1) + var(--baseline-verb-step));
    }

    /* The not-yet row on the 56rem frame */
    .page-home .content.content.home-close > .kg-signup-card {
        width: calc(var(--block) + var(--gutter-gap) + var(--gutter-width));
        max-width: none;
    }
    .page-home .content.content.home-close .kg-signup-card-content .kg-signup-card-form {
        max-width: none;
        width: 100%;
    }
    .page-home .content.content.home-close .kg-signup-card-content .kg-signup-card-fields {
        align-items: center;
        border-bottom: 1px solid var(--c-ink);
    }
    .page-home .content.content.home-close .kg-signup-card-content .kg-signup-card-input {
        border-bottom: 0;
    }
    .page-home .content.content.home-close .kg-signup-card-content .kg-signup-card-input:focus-visible {
        border-bottom: 0;
    }
}


/* ==========================================================================
   THE BLANK SHEET IS THE FORM (2026-09-21; ops/DECISIONS.md "The blank sheet
   becomes the form"; ops/BRIEF.md §7 Home). partials/components/ledger-form.hbs.
   - Every row is a writing line: the textarea or input has no border of its
     own; the row's rules are its underlines. The verb or word is the row's
     real <label>, set where the filled sheet sets its verbs.
   - ONE CLOSURE FOR BOTH SHEETS: each closes with its 2px rule directly
     under its last row. On the form that is the work-email row; the terms
     and the submit follow directly beneath the sheet, as the page follows
     the filled sheet.
   - The submit is the page's one primary control (Poppins 700
     --t-control, purple 2px underline). The newsletter row below loses its
     top rule, so the sheet's closing rule never meets another at one seam.
   - Both sheets' verbs are --t-step: the sheet's rank comes from its frame
     and its 24px conditions, and it no longer ties the 40px headings.
   ========================================================================== */
.content > .ledger.ledger-form {
    border-bottom: 0;
}
.ledger-form .ledger-row:has(+ .ledger-after) {
    border-bottom: 2px solid var(--c-ink);
}
.ledger-form .ledger-verb {
    display: block;
    margin: 0;
    font-family: var(--font-body);
    font-weight: 600;
    font-size: var(--t-step);
    line-height: 1.2;
    color: var(--c-ink);
}
.ledger-form .ledger-word {
    display: block;
    margin: 0;
    font-family: var(--font-title);
    font-weight: 700;
    font-size: var(--t-meta);
    letter-spacing: 0.01em;
    line-height: 1.4;
    color: var(--c-ink);
}
.ledger-form .ledger-line,
.ledger-form input.ledger-line {
    display: block;
    width: 100%;
    min-height: 44px;
    margin: var(--offset-tight) 0 0;
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    color: var(--c-ink);
    font-family: var(--font-body);
    font-weight: 400;
    font-size: var(--t-sub);
    line-height: 1.35;
}
.ledger-form textarea.ledger-line {
    height: calc(2 * 1.35 * var(--t-sub));
    resize: none;
    overflow: auto;
}
.ledger-form .ledger-line:focus-visible {
    outline: 2px solid var(--c-link-underline);
    outline-offset: 4px;
}
.ledger-form > .ledger-after {
    max-width: var(--block);
    padding-top: var(--space-1);
}
.ledger-form .ledger-terms {
    margin: 0 0 var(--space-1);
    font-family: var(--font-body);
    font-size: var(--t-body);
    line-height: 1.6;
    text-wrap: pretty;
}
.ledger-form .enquiry-status {
    margin-top: var(--space-1);
}
.page-home .content.content.home-close > .kg-signup-card {
    border-top: 0;
}
@media (min-width: 1280px) {
    .ledger .ledger-row > dt {
        font-size: var(--t-step);
        top: calc(var(--space-1) + var(--baseline-verb-step));
    }
    .ledger-form .ledger-verb,
    .ledger-form .ledger-word {
        position: absolute;
        right: 0;
        width: var(--gutter-width);
        text-align: right;
    }
    .ledger-form .ledger-verb {
        top: calc(var(--space-1) + var(--baseline-verb-step));
        line-height: 1;
    }
    .ledger-form .ledger-word {
        top: calc(var(--space-1) + var(--baseline-word));
    }
    .ledger-form .ledger-line,
    .ledger-form input.ledger-line {
        margin-top: 0;
    }
}

/* WORK: the enquiry's label is now a sentence (the free first conversation
   and the reply time), so it leaves the gutter and heads the form in the
   column, at the outward-line register. A sentence of terms is not a
   locator; the gutter keeps annotation only. */
.enquiry-label,
.enquiry > .enquiry-label {
    position: static;
    width: auto;
    margin: 0 0 var(--space-1);
    font-family: var(--font-body);
    font-weight: 500;
    font-size: var(--t-sub);
    letter-spacing: 0;
    line-height: 1.35;
    text-align: left;
    text-wrap: pretty;
}
/* The shared enquiry script renders between the sheet-form and the Signup
   card, so the not-yet row's pause cannot be keyed on adjacency. */
.page-home .content.content.home-close > .kg-signup-card {
    margin-top: var(--space-turn);
}


/* ==========================================================================
   THE SHEET-FORM'S AFFORDANCE (2026-09-21; ops/BRIEF.md §7 Home).
   - Each writing row's text sits ON the rule below it (the next row's top
     rule is the row's writing line): --offset-tight under the field, not
     --space-1.
   - A faint prompt in every field, the primer field's placeholder colour
     and size (--c-placeholder, --t-body).
   - The submit is the sheet's last row and sits on the closing 2px rule.
     It carries no underline of its own there, so the closing rule is its
     line; the rule turns purple on hover and focus.
   - Two kinds of link, two treatments: Poppins with an arrow is the
     primary action only. "Read these first" loses its arrow; the primer's
     submit takes the inline-link treatment (Newsreader, 1px purple
     underline), not the control's.
   ========================================================================== */
.ledger-form .ledger-row {
    padding-bottom: var(--offset-tight);
}
.ledger-form .ledger-line::placeholder {
    color: var(--c-placeholder);
    font-size: var(--t-body);
    opacity: 1;
}
.ledger-form .ledger-row-submit {
    padding-block: var(--offset-tight) 0;
    border-bottom: 2px solid var(--c-ink);
    transition: border-bottom-color var(--motion-duration) ease-out;
}
.ledger-form .ledger-row-submit:has(button:hover, button:focus-visible) {
    border-bottom-color: var(--c-link-underline);
}
.ledger-form .ledger-row-submit > .btn {
    text-decoration-line: none;
}
.ledger-form .ledger-row-submit > .btn:focus-visible {
    outline: 2px solid var(--c-link-underline);
    outline-offset: 4px;
}
.ledger-form > .ledger-after .ledger-terms {
    margin: 0;
    font-size: var(--t-meta);
    line-height: 1.4;
}
.page-home .content .catalogue-label a::after {
    content: none;
}
.page-home .content.content.home-close .kg-signup-card-content .kg-signup-card-button {
    font-family: var(--font-body);
    font-weight: 400;
    font-size: var(--t-body);
    letter-spacing: 0;
    line-height: 1.6;
    text-decoration-line: underline;
    text-decoration-thickness: 1px;
    text-decoration-color: var(--c-link-underline);
    text-underline-offset: 0.2em;
}
.page-home .content.content.home-close .kg-signup-card-content .kg-signup-card-button::after {
    content: none;
}
.page-home .content.content.home-close .kg-signup-card-content .kg-signup-card-button:hover,
.page-home .content.content.home-close .kg-signup-card-content .kg-signup-card-button:focus-visible {
    text-decoration-thickness: 2px;
}
/* Inputs: a deterministic text line (44px box, one 1.35 line centred by
   padding) so their labels can share the typed text's baseline. */
.ledger-form input.ledger-line {
    height: auto;
    padding-block: calc((44px - 1.35 * var(--t-sub)) / 2);
    line-height: 1.35;
}


/* ==========================================================================
   ONE EMAIL FIELD, TWO RANKED EXITS (2026-09-21; ops/BRIEF.md §7 Home).
   The sheet's last row holds both exits on the closing rule: the primary,
   "Start a conversation", as the action control; the secondary, the
   primer, as an inline link at body size — subordinate by face, size and
   position. The secondary posts through a hidden native Ghost members form
   (ledger-form.hbs). Home-close's Signup card is no longer rendered.
   One label system: every row label is Newsreader 600 --t-step.
   ========================================================================== */
.ledger-form .ledger-row-submit {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    column-gap: var(--space-2);
}
.ledger-form .ledger-primer {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0.75rem 0;
    margin: 0;
    background: transparent;
    border: 0;
    border-radius: 0;
    color: var(--c-ink);
    cursor: pointer;
    font-family: var(--font-body);
    font-weight: 400;
    font-size: var(--t-body);
    line-height: 1.6;
    text-decoration-line: underline;
    text-decoration-thickness: 1px;
    text-decoration-color: var(--c-link-underline);
    text-underline-offset: 0.2em;
}
.ledger-form .ledger-primer[hidden] { display: none; }
.ledger-form .ledger-primer:hover,
.ledger-form .ledger-primer:focus-visible {
    text-decoration-thickness: 2px;
}
.ledger-form .ledger-primer:focus-visible {
    outline: 2px solid var(--c-link-underline);
    outline-offset: 4px;
}
.ledger-form .ledger-primer[disabled] { opacity: 0.5; cursor: default; }
form.ledger-members[hidden] { display: none; }
@media (max-width: 899px) {
    .ledger-form .ledger-row-submit {
        flex-direction: column;
        align-items: flex-start;
    }
}
@media (min-width: 1280px) {
    .ledger-form .ledger-row-field .ledger-verb {
        top: calc(var(--space-1) + var(--baseline-verb-step) + (44px - 1.35 * var(--t-sub)) / 2);
    }
}

/* Home's first-screen locator: what Adam does, level with the h1. */
.page-stamp {
    margin: 0;
    text-align: right;
    font-family: var(--font-body);
    font-weight: 400;
    font-size: var(--t-meta);
    line-height: 1.4;
}
@media (min-width: 1280px) {
    .page-home > .beat-opening {
        position: relative;
    }
    .page-home > .beat-opening > .page-stamp {
        position: absolute;
        top: var(--baseline-stamp);
        left: calc(var(--block) + var(--gutter-gap));
        width: var(--gutter-width);
    }
    .page-home > .beat-opening > .page-stamp + .page-title {
        margin-top: 0;
    }
}

/* ==========================================================================
   FIRST SCREEN AND SHEET FOOT, 2026-09-21 (ops/BRIEF.md §2, §7 Home).
   - The stamp sits in the gutter on the LEDE's first baseline, out of the
     h1's path: the h1 may run past the column into the gutter (one line at
     >= 900px, 1.05 x --t-display tall), the lede never does.
   - Name and Work email are field labels, the sheet head's Poppins 700
     --t-meta, not the verdicts' display serif: one device, one meaning.
   - The secondary exit takes its own line under the primary, on the
     column's left axis.
   ========================================================================== */
@media (min-width: 1280px) {
    .page-home > .beat-opening > .page-stamp {
        top: calc(1.05 * var(--t-display) + var(--space-1) + var(--baseline-lede));
    }
}
.ledger-form .ledger-row-submit {
    flex-direction: column;
    align-items: flex-start;
    row-gap: 0;
}


/* ==========================================================================
   THE MARGIN CARRIES WORK'S AND THE ARTICLE'S ENDINGS (2026-09-21;
   ops/BRIEF.md §2, §7 Work and Article).
   WORK
   - The price is a verdict: a Header card with no button (a figure and its
     terms) sets its heading in the margin at the ledger verbs' size,
     right-aligned on the display edge, on the terms' first baseline.
   - The enquiry form is ruled like the sheet: one full-unit rule per row,
     the label in the margin on the field's first baseline, the field on
     the full measure with no border of its own; a rule closes the last row.
   - Its submit is a free action ("start with a free conversation"), so it
     takes the purple underline: the accent keeps one meaning on Work.
   - Client marks default to 1.5rem; page.hbs equalises them by ratio.
   ARTICLE
   - "The fix:"-style lead-ins and numbered h2 prefixes (marked by the
     script in post.hbs) hang in the margin, level with their lines.
   ========================================================================== */
.content.content .kg-gallery-image img {
    height: 1.5rem;
}
@media (min-width: 1280px) {
    .content.content > .kg-header-card:not(:has(.kg-header-card-button)) {
        position: relative;
    }
    .page-article .content.content.content.content > .kg-header-card:not(:has(.kg-header-card-button)) .kg-header-card-content h2.kg-header-card-heading {
        position: absolute;
        top: var(--baseline-price);
        right: 0;
        width: var(--gutter-width);
        max-width: var(--gutter-width);
        margin: 0;
        text-align: right;
        font-size: var(--t-step);
        font-weight: 600;
        letter-spacing: 0;
        line-height: 1;
        white-space: nowrap;
    }
    .page-article .content.content.content.content > .kg-header-card:not(:has(.kg-header-card-button)) .kg-header-card-content .kg-header-card-subheading {
        margin-top: 0;
    }

    .enquiry-form {
        width: calc(var(--block) + var(--gutter-gap) + var(--gutter-width));
    }
    .enquiry-form > .enquiry-field {
        position: relative;
        margin: 0;
        padding: var(--space-1) calc(var(--gutter-gap) + var(--gutter-width)) var(--offset-tight) 0;
        border-top: 1px solid var(--c-ink);
    }
    .enquiry-form > .enquiry-field:has(+ .enquiry-trap) {
        border-bottom: 1px solid var(--c-ink);
    }
    .enquiry-form > .enquiry-field > label {
        position: absolute;
        top: calc(var(--space-1) + var(--baseline-field));
        right: 0;
        width: var(--gutter-width);
        text-align: right;
        line-height: 1.4;
    }
    .enquiry-form > .enquiry-field input[type="text"],
    .enquiry-form > .enquiry-field input[type="email"],
    .enquiry-form > .enquiry-field textarea {
        border-bottom: 0;
        min-height: 44px;
    }
    .enquiry-form > .btn {
        margin-top: var(--space-1);
    }

    .article-body .content > p:has(> strong.lead-in) {
        position: relative;
    }
    .article-body .content > p > strong.lead-in {
        position: absolute;
        top: var(--baseline-lead-p);
        left: calc(var(--block) + var(--gutter-gap));
        width: var(--gutter-width);
        text-align: right;
        font-family: var(--font-body);
        font-weight: 600;
        font-size: var(--t-meta);
        line-height: 1.4;
    }
    .article-body .content > h2:has(> .h2-prefix) {
        position: relative;
    }
    .article-body .content > h2 > .h2-prefix {
        position: absolute;
        top: 0;
        left: calc(var(--block) + var(--gutter-gap));
        width: var(--gutter-width);
        text-align: right;
    }
    .article-body .content > h2 > .h2-sep {
        display: none;
    }
}


/* ==========================================================================
   WORK AND ARTICLE FINISH (2026-09-21; ops/BRIEF.md §2, §7).
   - Work's textarea: no resize grip. Its only visible line is its row's
     rule, so a grip at the field's own edge would sit in the empty track
     between column and label.
   - Client marks set by the lettering, not the box: each wordmark's cap
     height (--cap, measured on the rendered glyphs as a fraction of the
     image height) lands at one value, --logo-cap, and each mark's
     wordmark baseline (--base) sits on one line. Widths are unequal by
     design. A mark not listed here falls back to 1.5rem, centred.
   - The article's "Read next" label: the margin's label face (Newsreader
     600 --t-meta), on the first title's baseline, clear of the rule; the
     row's meta drops one line beneath it.
   - Hung h2 prefixes are labels, not second headings: the lead-in tier,
     Newsreader 600 --t-meta, on the heading's first baseline.
   ========================================================================== */
.enquiry-form textarea {
    resize: none;
}
.content.content .kg-gallery-card .kg-gallery-container {
    --logo-cap: 13px;
    align-items: flex-end;
    row-gap: var(--space-1);
}
.content.content .kg-gallery-card .kg-gallery-image img[src*="elsevier"]        { --cap: 0.28; --base: 0.75; }
.content.content .kg-gallery-card .kg-gallery-image img[src*="first-american"]  { --cap: 0.26; --base: 0.63; }
.content.content .kg-gallery-card .kg-gallery-image img[src*="pendo"]           { --cap: 0.70; --base: 0.78; }
.content.content .kg-gallery-card .kg-gallery-image img[src*="pfizer"]          { --cap: 0.44; --base: 0.72; }
.content.content .kg-gallery-card .kg-gallery-image img[src*="smartrecruiters"] { --cap: 0.98; --base: 1; }
.content.content .kg-gallery-card .kg-gallery-image img[style*="--cap"],
.content.content .kg-gallery-card .kg-gallery-image img[src*="elsevier"],
.content.content .kg-gallery-card .kg-gallery-image img[src*="first-american"],
.content.content .kg-gallery-card .kg-gallery-image img[src*="pendo"],
.content.content .kg-gallery-card .kg-gallery-image img[src*="pfizer"],
.content.content .kg-gallery-card .kg-gallery-image img[src*="smartrecruiters"] {
    width: auto;
    height: calc(var(--logo-cap) / var(--cap));
    margin-bottom: calc((var(--base) - 1) * var(--logo-cap) / var(--cap));
}
@media (min-width: 1280px) {
    .article-body .content .catalogue > h2.catalogue-label {
        top: calc(var(--space-1) + var(--baseline-sub) + 1px);
        font-family: var(--font-body);
        font-weight: 600;
        letter-spacing: 0;
        line-height: 1.4;
    }
    .article-body .content .catalogue > h2.catalogue-label a {
        font-family: var(--font-body);
        font-weight: 600;
    }
    .article-body .content .catalogue .home-rows > .home-row:first-child .home-row-meta {
        top: calc(var(--space-1) + var(--baseline-sub) + var(--t-meta) * 1.4);
    }
    .article-body .content > h2 > .h2-prefix {
        top: var(--baseline-prefix);
        font-family: var(--font-body);
        font-weight: 600;
        font-size: var(--t-meta);
        letter-spacing: 0;
        line-height: 1.4;
    }
}


/* ==========================================================================
   WORK'S SECTIONS, FORM AND MARKS; HOME'S OFFER ROW (2026-09-22;
   ops/BRIEF.md §2, §7 Home and Work). Home rules above are untouched.
   ========================================================================== */

/* WORK: one opening device for every section. A section opens on a
   full-unit 1px rule with its h2 --space-1 beneath it (the ledger row's
   grammar). The price is not a section: it is the last row of "What
   you're paying for", so it follows its paragraphs at --space-2, not
   after the long pause. */
.page-work-with-me .content > h2 {
    border-top: 1px solid var(--c-ink);
    padding-top: var(--space-1);
}
.page-work-with-me .content.content > .kg-header-card {
    margin-top: var(--space-2);
}
@media (min-width: 1280px) {
    .page-work-with-me .content > h2 {
        width: calc(var(--block) + var(--gutter-gap) + var(--gutter-width));
        padding-right: calc(var(--gutter-gap) + var(--gutter-width));
    }
    .page-work-with-me .content.content > .kg-header-card {
        margin-top: var(--space-2);
    }
}

/* WORK: the form's rows read as writable, as Home's sheet does: a faint
   prompt on each writing line (strings in the partial's placeholders),
   the free-text field three lines tall rather than an empty band. */
.enquiry-form .enquiry-field input::placeholder,
.enquiry-form .enquiry-field textarea::placeholder {
    color: var(--c-placeholder);
    font-size: var(--t-body);
    opacity: 1;
}
.enquiry-form .enquiry-field textarea {
    min-height: 0;
    height: calc(3 * 1.6 * var(--t-body) + 1rem);
}

/* WORK: the cropped wordmarks (crests removed; originals kept beside
   them). Both are cropped to their lettering, so cap and baseline sit at
   the image's own edges. With every mark at one cap height the five fit
   one row at --space-1 gaps. */
.content.content .kg-gallery-card .kg-gallery-image img[src*="elsevier-wordmark"]       { --cap: 0.97; --base: 0.986; }
.content.content .kg-gallery-card .kg-gallery-image img[src*="first-american-wordmark"] { --cap: 0.83; --base: 0.88; }
.content.content .kg-gallery-card .kg-gallery-container {
    column-gap: var(--space-1);
}

/* HOME: the offer row, in the ledger's grammar. An HTML card in the home
   record after the testimonial's attribution:
   <div class="offer"><p class="offer-label">LABEL</p><p class="offer-text">SENTENCES</p></div>
   Its own 1px rules across the unit, the label in the margin (the
   margin's label face) on the text's first baseline, the text at the
   ledger's --t-sub. */
.page-home > .content > .offer {
    clear: left;
    margin-top: var(--space-turn);
    padding-block: var(--space-1);
    border-top: 1px solid var(--c-ink);
    border-bottom: 1px solid var(--c-ink);
}
.page-home > .content > .offer > .offer-label {
    margin: 0 0 var(--offset-tight);
    font-family: var(--font-body);
    font-weight: 600;
    font-size: var(--t-meta);
    line-height: 1.4;
}
.page-home > .content > .offer > .offer-text {
    margin: 0;
    font-family: var(--font-body);
    font-weight: 400;
    font-size: var(--t-sub);
    line-height: 1.35;
    text-wrap: pretty;
}
@media (min-width: 1280px) {
    .page-home > .content > blockquote:has(+ .kg-image-card + p + .offer) {
        margin-bottom: var(--space-turn);
    }
    .page-home > .content > .offer {
        position: relative;
        width: calc(var(--block) + var(--gutter-gap) + var(--gutter-width));
        padding-right: calc(var(--gutter-gap) + var(--gutter-width));
    }
    .page-home > .content > .offer > .offer-label {
        position: absolute;
        top: calc(var(--space-1) + var(--baseline-offer));
        right: 0;
        width: var(--gutter-width);
        margin: 0;
        text-align: right;
    }
}

/* ==========================================================================
   ABOUT (2026-09-22; ops/DECISIONS.md "About portrait rectangular";
   ops/BRIEF.md §7 About). About only; Home and Work untouched.
   - The portrait is a rectangle at the reading width, not a circle.
   - Its caption sits in the margin on the photograph's top edge, the
     margin's label face, under the anchor rule.
   - The close is one unit: an empty subheading takes no space, and the
     link sits --space-1 under its heading.
   - The lede's line pitch is never tighter than the body's.
   ========================================================================== */
.page-article.page-about .content > .kg-image-card:not(.kg-width-wide) {
    position: relative;
    width: 100%;
    max-width: var(--block);
    aspect-ratio: auto;
}
.page-article.page-about .content > .kg-image-card:not(.kg-width-wide) img {
    width: 100%;
    height: auto;
    border-radius: 0;
}
.page-article.page-about .content > .kg-image-card figcaption {
    text-align: right;
}
@media (min-width: 1280px) {
    .page-article.page-about .content > .kg-image-card:not(.kg-width-wide) figcaption {
        position: absolute;
        top: var(--baseline-caption);
        left: calc(var(--block) + var(--gutter-gap));
        width: var(--gutter-width);
        max-width: var(--gutter-width);
        margin: 0;
        text-align: right;
    }
}
.page-about .content.content .kg-header-card-content .kg-header-card-subheading:empty {
    display: none;
}
.page-about .content.content .kg-header-card-content h2.kg-header-card-heading + .kg-header-card-subheading:empty + .kg-header-card-button {
    margin-top: var(--space-1);
}
.page-about .lede {
    line-height: 1.45;
}

/* ABOUT'S LOCATORS: role or organisation and years, true and authored.
   The opening's comes from the theme setting and sits on the lede's first
   baseline; each body paragraph's is a lead-in (<strong>…</strong><br>),
   hung by the site-wide lead-in rule. Both in the lead-in face. */
.page-about > .beat-opening > .page-stamp {
    font-weight: 600;
}
@media (min-width: 1280px) {
    .page-about > .beat-opening {
        position: relative;
    }
    .page-about > .beat-opening > .page-stamp {
        position: absolute;
        top: calc(1.05 * var(--t-display) + var(--space-1) + var(--baseline-lede));
        left: calc(var(--block) + var(--gutter-gap));
        width: var(--gutter-width);
    }
    .page-about > .beat-opening > .page-stamp + .page-title {
        margin-top: 0;
    }
}
/* About's body leading puts the paragraph's first baseline 2px higher
   than the article's, so its lead-ins drop 2px less. */
.page-about {
    --baseline-lead-p: 8px;
}

/* The article's lead-in may carry its gloss: "The fix: one line". The
   label keeps the lead-in weight; the gloss is regular, so the margin
   reads as notes, not a column of labels. About's portrait keeps its
   treatment wherever it sits in the body (it follows the paragraph that
   resolves the lede's story). */
.article-body .content > p > strong.lead-in > .lead-gloss {
    font-weight: 400;
}
.page-about .content > p + .kg-image-card,
.page-article.page-about .content > .kg-image-card + p {
    margin-top: var(--space-2);
}
