/* ==========================================================================
   Anchor — SSLaboratory base theme
   --------------------------------------------------------------------------
   Register: professional services. Traditional, stable, unfashionable on
   purpose. Light-only by design — a firm's site should look the same to
   everyone.

   --brand-primary, --brand-accent and --brand-support are injected by
   default.hbs from the theme's custom settings. Everything else derives from
   them, so restyling for another client is a settings pass, not a fork.
   ========================================================================== */

:root {
    /* brand-* are injected by default.hbs; these are only a safety net. */
    --brand-primary: #1B365D;
    --brand-accent: #A32C2B;
    /* The quieter third colour most logos carry. Marks and fine rules only:
       it holds AA as text on white but not on --brand-primary. */
    --brand-support: #56627A;

    /*
       Typography comes from Ghost's native font picker (Design & branding),
       which sets --gh-font-heading / --gh-font-body. The fallbacks below are
       system faces, so the site is correct and instant with no webfont loaded.
    */
    --font-heading: var(--gh-font-heading, Georgia, "Times New Roman", serif);
    --font-body: var(--gh-font-body, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif);

    --paper: #FFFFFF;
    --paper-alt: #F5F6F8;
    --ink: #1A1D21;
    --ink-muted: #5C6570;
    --rule: #DCE0E6;

    --measure: 68ch;
    --wrap: 1120px;
    --wrap-narrow: 720px;
    --home-column: 900px;

    --step: 8px;
    --radius: 3px;
}

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

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

/* In-page navigation (/#results) would otherwise land under the sticky header. */
[id] { scroll-margin-top: calc(var(--step) * 13); }
/* The header runs to two rows on a phone. */
@media (max-width: 639px) {
    [id] { scroll-margin-top: calc(var(--step) * 18); }
}

@media (prefers-reduced-motion: no-preference) {
    html { scroll-behavior: smooth; }
}

body {
    margin: 0;
    /* clip, not hidden. The mid-page credibility band breaks out to 100vw,
       which overhangs by the scrollbar width; clip trims that. `hidden` would
       do the same but makes body a scroll container, which silently kills
       position:sticky on the header. */
    overflow-x: clip;
    background: var(--paper);
    color: var(--ink);
    font-family: var(--font-body);
    font-size: 17px;
    line-height: 1.65;
    -webkit-font-smoothing: antialiased;
}

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

a { color: var(--brand-accent); text-underline-offset: 2px; }
a:hover { text-decoration: none; }

:focus-visible {
    outline: 2px solid var(--brand-accent);
    outline-offset: 2px;
    border-radius: var(--radius);
}

h1, h2, h3, h4 {
    font-family: var(--font-heading);
    font-weight: 600;
    line-height: 1.18;
    letter-spacing: -0.01em;
    color: var(--brand-primary);
    text-wrap: balance;
    margin: 0 0 calc(var(--step) * 2);
}

h1 { font-size: clamp(32px, 5vw, 46px); }
h2 { font-size: clamp(24px, 3.4vw, 32px); }
h3 { font-size: 21px; }

p { margin: 0 0 calc(var(--step) * 2.5); }

/* --- Layout ------------------------------------------------------------- */

.wrap {
    width: 100%;
    max-width: var(--wrap);
    margin-inline: auto;
    padding-inline: clamp(20px, 5vw, 40px);
}

.wrap--narrow { max-width: var(--wrap-narrow); }

.site-main { display: block; }

.prose { max-width: var(--measure); }
.prose > * + * { margin-top: calc(var(--step) * 2); }
.prose h2, .prose h3 { margin-top: calc(var(--step) * 5); }
.prose ul, .prose ol { padding-left: calc(var(--step) * 3); }
.prose li + li { margin-top: var(--step); }
.prose blockquote {
    margin: calc(var(--step) * 4) 0;
    padding-left: calc(var(--step) * 3);
    border-left: 3px solid var(--brand-accent);
    font-family: var(--font-heading);
    font-size: 20px;
    color: var(--brand-primary);
}
.prose figure { margin: calc(var(--step) * 4) 0; }
.prose figcaption {
    margin-top: var(--step);
    font-size: 14px;
    color: var(--ink-muted);
}
.prose code {
    font-size: 0.9em;
    background: var(--paper-alt);
    padding: 0.1em 0.35em;
    border-radius: var(--radius);
}
.prose > table { display: block; overflow-x: auto; }

/* --- Header ------------------------------------------------------------- */

/* Sticky so the booking button stays reachable through a long front page.
   No JS: there is no scroll-state shadow, just the permanent hairline. */
.site-header {
    position: sticky;
    top: 0;
    z-index: 10;
    border-bottom: 1px solid var(--rule);
    background: var(--paper);
}

.site-header__inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: calc(var(--step) * 2) calc(var(--step) * 4);
    padding-block: calc(var(--step) * 2.5);
}

.site-header__brand {
    text-decoration: none;
    color: var(--brand-primary);
    margin-right: auto;
}
.site-header__brand img { max-height: 44px; width: auto; }

.site-header__wordmark {
    font-family: var(--font-heading);
    font-size: 21px;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.site-nav__list {
    display: flex;
    gap: calc(var(--step) * 3);
    list-style: none;
    margin: 0;
    padding: 0;
}

.site-nav__item a {
    color: var(--ink);
    text-decoration: none;
    font-size: 15px;
    font-weight: 500;
}
.site-nav__item a:hover { color: var(--brand-accent); }

/* On a phone, logo and booking button share the first row and the nav takes
   a full row beneath. Left to wrap in source order, four nav items push the
   button onto a third row and the sticky header eats a fifth of the screen. */
@media (max-width: 639px) {
    .site-nav { order: 3; flex-basis: 100%; }
    .site-nav__list { flex-wrap: wrap; gap: var(--step) calc(var(--step) * 2.5); }
}

/* --- Buttons ------------------------------------------------------------ */

.button {
    display: inline-block;
    background: var(--brand-accent);
    color: #FFFFFF;
    font-family: var(--font-body);
    font-size: 16px;
    font-weight: 600;
    line-height: 1.2;
    text-decoration: none;
    padding: calc(var(--step) * 1.75) calc(var(--step) * 3);
    border-radius: var(--radius);
    border: 1px solid transparent;
}
.button { transition: background-color 0.15s ease, filter 0.15s ease; }
.button:hover { filter: brightness(0.92); }

.button--small { font-size: 14px; padding: calc(var(--step) * 1.25) calc(var(--step) * 2); }

.button--secondary {
    background: transparent;
    color: var(--brand-primary);
    border-color: var(--rule);
}

/* --- Home: hero front page -----------------------------------------------
   Everything here is scoped to .home so the treatment cannot leak onto About,
   posts or letter pages, which stay document-shaped on purpose.

   Page rhythm: full-bleed brand hero -> (optional credibility strip) -> body
   on paper, punctuated by brand bands the editor inserts -> full-bleed brand
   closing band. Alternating paper and navy is what stops the homepage reading
   as one long article column.
   -------------------------------------------------------------------------- */

.hero {
    position: relative;
    background-color: var(--brand-primary);
    color: #FFFFFF;
    padding-block: clamp(72px, 13vw, 148px);
    overflow: hidden;
}

/* Optional background photograph, always behind a brand scrim so the type
   stays legible whatever the client uploads. */
.hero--image {
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}
.hero--image::before {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--brand-primary);
    opacity: 0.86;
}

@supports (background: color-mix(in srgb, red 50%, transparent)) {
    .hero--image::before {
        opacity: 1;
        background: linear-gradient(
            100deg,
            color-mix(in srgb, var(--brand-primary) 94%, transparent) 0%,
            color-mix(in srgb, var(--brand-primary) 78%, transparent) 62%,
            color-mix(in srgb, var(--brand-primary) 62%, transparent) 100%);
    }
}

.hero__inner { position: relative; }

/* Sized for a question-length headline. The number has moved three times: at
   the original 68px an ~80-character title ran to five lines and pushed the
   button below a laptop fold; 52px on a 30ch measure then held a ~90-character
   question to three; and it came down again for a 115-character WHY statement
   that briefly led the page.

   The headline is the question again, so 52px would be defensible. It stays at
   48px on a 32ch measure deliberately: the client reported the question reading
   as truncated on his own screen at the larger setting, and until that is
   reproduced the more forgiving of the two is the one to ship. Revisit both
   together, not separately.

   At 24ch, text-wrap: balance split a line to four with a stranded short
   second line, so the measure is deliberately not narrower than this. */
.hero__title {
    color: #FFFFFF;
    font-size: clamp(28px, 5vw, 48px);
    line-height: 1.12;
    letter-spacing: -0.015em;
    max-width: 32ch;
    margin-bottom: calc(var(--step) * 3);
}

.hero__lede {
    font-family: var(--font-heading);
    font-size: clamp(18px, 2.2vw, 22px);
    line-height: 1.5;
    color: rgba(255, 255, 255, 0.84);
    max-width: 52ch;
    margin-bottom: calc(var(--step) * 4);
}

/* The booking button and the optional hero link share a line. The link is for
   an on-page jump ("See the results"), so it is styled as a link rather than
   as a second button competing with the booking ask. */
.hero__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: calc(var(--step) * 2) calc(var(--step) * 4);
}
.hero__link {
    color: #FFFFFF;
    font-weight: 600;
    text-decoration-color: rgba(255, 255, 255, 0.45);
    text-underline-offset: 5px;
}
.hero__link:hover { text-decoration: underline; text-decoration-color: #FFFFFF; }
/* A down arrow only for an on-page anchor. Empty alt text, so a screen reader
   does not announce "downwards arrow" after the label. */
.hero__link[href^="#"]::after {
    content: "\00A0\2193";
    content: "\00A0\2193" / "";
}

/* The accent burgundy and the brand navy sit at almost the same lightness, so
   an accent button on the hero would sink into it. White reverses out cleanly
   and is the right register for this kind of site anyway. */
.hero .booking { padding-block: 0; }
.hero .booking__inner { padding-inline: 0; max-width: none; }
.hero .button {
    background: #FFFFFF;
    color: var(--brand-primary);
    font-size: 17px;
    padding: calc(var(--step) * 2.25) calc(var(--step) * 4);
}
.hero .button:hover { background: rgba(255, 255, 255, 0.88); filter: none; }

/* --- Credibility band ---------------------------------------------------- */

.credibility {
    background: var(--paper-alt);
    border-bottom: 1px solid var(--rule);
    padding-block: calc(var(--step) * 3);
}
/* Set as a tracked, uppercase stat row rather than a sentence. The client
   still types one string in one setting; the separators are literal pipes,
   because Handlebars has no split helper and three settings to hold three
   numbers would be three things to get wrong. Keep it to three or four
   short segments — uppercase tracking is unreadable at sentence length. */
.credibility p {
    margin: 0;
    text-align: center;
    font-size: 13px;
    font-weight: 600;
    line-height: 1.6;
    letter-spacing: 0.11em;
    text-transform: uppercase;
    word-spacing: 0.15em;
    color: var(--ink-muted);
}

/* --- Mid-page credibility band -------------------------------------------
   The second strip, sitting roughly halfway down the body.

   Unlike the top strip this one cannot be a theme region: everything between
   the credibility band and the closing CTA is a single {{content}} blob, and
   Handlebars cannot split it, so there is no hook halfway down to render into.
   It is inserted by the editor as an HTML card and breaks out of the reading
   column on its own. The snippet is in the README and in content/home.md.

   Deliberately a different instrument from the top strip: that one is small,
   tracked and numeric, this one is serif and sentence-shaped. Two bands in the
   same voice would read as a mistake.

   `margin-inline: calc(50% - 50vw)` is the whole breakout. Percentage margins
   resolve against the containing block's inline size, and that block is
   centred, so the arithmetic lands on the viewport edges at any width without
   needing to know the column's own measurements.
   -------------------------------------------------------------------------- */

.credibility--mid {
    margin-block: clamp(64px, 9vw, 104px);
    margin-inline: calc(50% - 50vw);
    padding-block: clamp(48px, 7vw, 76px);
    background: var(--paper-alt);
    border-block: 1px solid var(--rule);
}

/* A short accent rule above the line, so the band reads as placed rather than
   as a stray paragraph that happens to sit on grey. */
.credibility--mid::before {
    content: "";
    display: block;
    width: 40px;
    height: 3px;
    margin: 0 auto calc(var(--step) * 3);
    background: var(--brand-accent);
}

.credibility--mid p {
    max-width: 46ch;
    margin: 0 auto;
    text-align: center;
    font-family: var(--font-heading);
    font-size: clamp(20px, 2.6vw, 26px);
    line-height: 1.4;
    color: var(--brand-primary);
    text-wrap: balance;
}

/* If Ghost wraps an HTML card in its own div, zero that div's margin so the
   inserted block's own rhythm is the one that applies. */
.prose .kg-html-card:has(> .credibility--mid),
.prose .kg-html-card:has(> .band),
.prose .kg-html-card:has(> .stats),
.prose .kg-html-card:has(> .letter__for),
.prose .kg-html-card:has(> .photo),
.prose .kg-html-card:has(> .voices),
.prose .kg-html-card:has(> .bio-card) { margin-block: 0; }

/* --- Brand bands ----------------------------------------------------------
   Full-bleed navy bands inserted mid-page as HTML cards, for the same reason
   as the grey band above: the body is one {{content}} field and the theme has
   nowhere to render into halfway down. Two shapes:

     <aside class="band band--statement"><p>…</p></aside>
         one sentence, serif, centred

     <section class="band" id="…"><h2>…</h2> … </section>
         a titled section (a results block, say) whose content stays aligned
         to the body column

   The grey band is for a line to be read; a navy band is for a line to land.

   `padding-inline: calc(50vw - 50%)` mirrors the margin breakout and puts the
   content box back on the column edges, so a heading inside the band lines up
   with the headings above and below it.

   Burgundy cannot mark anything on navy (the two sit at nearly the same
   lightness), so marks inside a band are white at reduced opacity.
   -------------------------------------------------------------------------- */

.band {
    margin-block: clamp(64px, 9vw, 104px);
    margin-inline: calc(50% - 50vw);
    padding-block: clamp(56px, 8vw, 96px);
    padding-inline: calc(50vw - 50%);
    background: var(--brand-primary);
    color: #FFFFFF;
}
.band > :last-child { margin-bottom: 0; }
.band p { color: rgba(255, 255, 255, 0.84); }
.band a { color: #FFFFFF; }

.home__body .band h2,
.home__body .band h3,
.page__body .band h2,
.page__body .band h3,
.letter .band h2,
.letter .band h3 { margin-top: 0; color: #FFFFFF; }
.home__body .band h2::before,
.home__body .band h3::before,
.page__body .band h2::before,
.page__body .band h3::before,
.letter .band h2::before,
.letter .band h3::before { background: #FFFFFF; opacity: 0.5; }

.band .band__note {
    font-size: 14px;
    color: rgba(255, 255, 255, 0.7);
}
/* Wide enough for a closing question to hold one line on desktop, so an
   editor's <br> after it decides the break rather than the measure. */
.band p.band__close {
    max-width: 60ch;
    font-family: var(--font-heading);
    font-size: clamp(20px, 2.4vw, 24px);
    line-height: 1.4;
    color: #FFFFFF;
}

.band--statement { text-align: center; }
.band--statement::before {
    content: "";
    display: block;
    width: 40px;
    height: 3px;
    margin: 0 auto calc(var(--step) * 3);
    background: #FFFFFF;
    opacity: 0.5;
}
.band--statement p {
    max-width: 44ch;
    margin: 0 auto;
    font-family: var(--font-heading);
    font-size: clamp(22px, 2.8vw, 30px);
    line-height: 1.4;
    color: #FFFFFF;
    text-wrap: balance;
}

/* --- Stat row -------------------------------------------------------------
   Large figures with a short label under each, inserted as an HTML card:

     <div class="stats">
       <p class="stats__item"><strong>35+</strong> years of experience</p>
     </div>

   Each item is an ordinary sentence with the figure in bold, so it still
   reads correctly if the classes are ever stripped.

   Figures are set in the body sans, not the heading serif. Georgia, the serif
   fallback, has old-style numerals whose 3s and 5s drop below the baseline;
   at display size "35+" looks like it is sinking. Lining, tabular sans
   figures sit level and align column to column.

   The 96px track minimum keeps three figures across on a phone.
   -------------------------------------------------------------------------- */

.stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 96px), 1fr));
    gap: calc(var(--step) * 3) clamp(16px, 3vw, 40px);
    margin-block: calc(var(--step) * 5);
    padding-top: calc(var(--step) * 3);
    border-top: 2px solid var(--brand-support);
}
/* A flex column, so that a label can be told to absorb the slack and carry a
   source line down to the bottom edge of the item — see .stats__label below.
   Grid items already stretch to the row height, which is what makes there be
   slack to absorb. An item with no label span is laid out exactly as before. */
.stats__item {
    display: flex;
    flex-direction: column;
    margin: 0;
    font-size: 15px;
    line-height: 1.45;
    color: var(--ink-muted);
}
.stats__item strong {
    display: block;
    margin-bottom: calc(var(--step) * 0.75);
    font-family: var(--font-body);
    font-size: clamp(34px, 4.6vw, 48px);
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.02em;
    font-variant-numeric: lining-nums tabular-nums;
    color: var(--brand-accent);
}

/* Where the figure came from. A page arguing that most improvement efforts fail
   is only as good as its sources, and a number with a name under it is worth
   more here than the same number floating free.

   <cite> rather than a span or a small: the element's actual job is to name the
   work a quotation or figure is taken from. Its default italic is turned off —
   "Gartner" is a publisher, not a title.

   Set below a hairline so the figure and its label stay one unit and the source
   reads as a footnote to both, rather than as a third line of the label. */
/* The label takes the slack, so the hairline above the sources lands on one
   line across the row even when one label wraps to two lines and its neighbour
   does not. Needs the span: the label is otherwise a bare text node, and an
   anonymous flex item cannot be given flex-grow. */
.stats__item .stats__label { flex: 1 1 auto; }

.stats__item cite {
    display: block;
    margin-top: calc(var(--step) * 1.5);
    padding-top: var(--step);
    border-top: 1px solid var(--rule);
    font-size: 13px;
    font-style: normal;
    line-height: 1.4;
    color: var(--ink-muted);
}

/* Long labels. Three figures across a phone suits "35+ years"; with a label
   like "Higher operating profit — professional services" each column is
   ~110px and the label runs to four lines. stats--stack puts one figure per
   row below 640px instead. */
@media (max-width: 639px) {
    .stats--stack { grid-template-columns: 1fr; }
}

/* Inside a band the figures go white and grow: that block is the payoff. */
.band .stats {
    margin-block: calc(var(--step) * 4);
    border-top-color: rgba(255, 255, 255, 0.28);
}
.band .stats__item { font-size: 16px; color: rgba(255, 255, 255, 0.84); }
.band .stats__item strong { font-size: clamp(48px, 8vw, 84px); color: #FFFFFF; }
.band .stats__item cite {
    border-top-color: rgba(255, 255, 255, 0.24);
    color: rgba(255, 255, 255, 0.66);
}

/* --- Home body ----------------------------------------------------------- */

/* Wider than a reading column so the feature grids have room, with running
   text still constrained to a comfortable measure. */
.home__body {
    max-width: var(--home-column);
    padding-top: clamp(56px, 8vw, 96px);
}
.home__body > p,
.home__body > h2,
.home__body > h3,
.home__body > blockquote { max-width: var(--measure); }

/* Sections open with a short accent rule and real air, so the page reads as
   blocks rather than as continuous prose.

   The rule is the heading's own ::before rather than a full-width border
   between sections. A hairline spanning the column separates two things
   without emphasising either; a short mark sitting directly above the words
   belongs to the heading, so each section reads as a titled block. It also
   picks up the accent rule on the mid-page credibility band, which is the
   only other place the burgundy is used as a mark rather than as type.

   Shared by the homepage and by standard pages (About). Posts and letter
   pages are deliberately left document-shaped and do not opt in.

   h2 and h3 are treated identically on purpose: the copy uses a single heading
   level throughout, and a page that mixes them wants both to read as section
   openers rather than as a two-deep outline. */
.home__body h2,
.home__body h3,
.page__body h2,
.page__body h3 {
    font-family: var(--font-heading);
    /* Pages run in the 720px column, so they take a smaller step than the
       homepage's 900px one. Both are a large jump on 17px body text, which is
       the measurement that actually matters. */
    font-size: clamp(26px, 3.4vw, 32px);
    font-weight: 700;
    line-height: 1.15;
    color: var(--brand-primary);
    margin-top: calc(var(--step) * 11);
    margin-bottom: calc(var(--step) * 3);
}
.home__body h2,
.home__body h3 { font-size: clamp(28px, 3.8vw, 38px); }

.home__body h2::before,
.home__body h3::before,
.page__body h2::before,
.page__body h3::before {
    content: "";
    display: block;
    width: 48px;
    height: 3px;
    margin-bottom: calc(var(--step) * 2.5);
    background: var(--brand-accent);
}
.home__body > h2:first-child,
.home__body > h3:first-child,
.page__body > h2:first-child,
.page__body > h3:first-child { margin-top: 0; }

/* Lists become check grids. Two treatments, and the content picks which one
   it gets — which is the only way to have two on a page whose whole middle is
   a single {{content}} blob with no wrappers to hook onto.

     plain bullet                -> compact checked row, two columns
     bullet opening with bold    -> card, mark stacked above the lead-in,
                                    three columns

   So a list of offers reads as feature cards and a list of symptoms reads as
   a checklist, and the editor gets both by doing nothing more exotic than
   bolding the first few words. Browsers without :has() fall back to the
   compact row everywhere, which is correct, just flatter.

   Marks are in --brand-support rather than the primary navy: the logo's own
   third colour, and quiet enough that eight of them do not shout.

   The check itself is a CSS background data-URI, not an icon font — see the
   theme constraints in the README. */

.home__body ul {
    list-style: none;
    padding: 0;
    margin-block: calc(var(--step) * 4);
    display: grid;
    gap: calc(var(--step) * 3);
}
@media (min-width: 640px) {
    .home__body ul {
        grid-template-columns: 1fr 1fr;
        gap: calc(var(--step) * 3) calc(var(--step) * 5);
    }
    .home__body ul:has(li strong) {
        grid-template-columns: repeat(3, 1fr);
        gap: calc(var(--step) * 4);
    }
}

.home__body ul li {
    position: relative;
    margin: 0;
    padding-left: calc(var(--step) * 4.5);
    font-size: 16px;
    line-height: 1.55;
}
.home__body ul li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.15em;
    width: 22px;
    height: 22px;
    border-radius: 6px;
    background: var(--brand-support) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='%23fff' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round' d='M5 12.5l5 5L19 7'/%3E%3C/svg%3E") center / 13px no-repeat;
}

/* Plain checklists take a hairline under each row, so a long list scans as a
   set of rows rather than a loose cloud of checks. */
.home__body ul:not(:has(li strong)) { row-gap: 0; }
.home__body ul:not(:has(li strong)) li {
    padding-block: calc(var(--step) * 1.75);
    border-bottom: 1px solid var(--rule);
}
.home__body ul:not(:has(li strong)) li::before { top: calc(var(--step) * 1.75 + 0.15em); }

/* Card treatment. The mark leaves the text flow and sits above the lead-in. */
.home__body ul li:has(strong) {
    padding-left: 0;
    font-size: 15px;
    color: var(--ink-muted);
}
.home__body ul li:has(strong)::before {
    position: static;
    display: block;
    width: 30px;
    height: 30px;
    background-size: 17px;
    margin-bottom: calc(var(--step) * 2);
}
.home__body ul li strong {
    display: block;
    margin-bottom: calc(var(--step) * 0.75);
    color: var(--brand-primary);
    font-weight: 600;
    font-size: 16px;
}

/* Icon cards. In the card layout a list item that opens with an icon swaps the
   check for that icon, in the same support-colour square, so a list can carry a
   picture per item without introducing a second visual language. The square
   grows from 30px to 40px: a pictogram needs more room than a check to read.

     <li><span class="icon icon--brain" aria-hidden="true"></span><strong>Lead-in</strong> Description</li>

   Card layout only. At checklist size the pictograms blur into each other, so
   an icon in a plain row is hidden and the check stays. A Ghost bullet cannot
   carry the span, which means an icon list is always inserted as an HTML card.
   Without :has() the icon is hidden and the item falls back to a checked row. */
.home__body ul li > .icon { display: none; }
.home__body ul li:has(strong):has(> .icon)::before {
    width: 40px;
    height: 40px;
    border-radius: 8px;
    background-image: none;
}
.home__body ul li:has(strong) > .icon {
    display: block;
    position: absolute;
    top: calc(var(--card-pad, 0px) + 9px);
    left: calc(var(--card-pad, 0px) + 9px);
    width: 22px;
    height: 22px;
    color: #FFFFFF;
}

/* Optional eyebrow above a card's lead-in, for numbered cards ("01"). */
.home__body ul li .eyebrow {
    display: block;
    margin-bottom: calc(var(--step) * 0.75);
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--ink-muted);
}

/* Card counts that do not suit three columns. Two cards take half each rather
   than leaving an empty third. Five cards run as one row once the column is
   wide enough — a set of five is usually one idea in five parts, and 3 + 2
   splits it — and fall back to three across below that. */
@media (min-width: 640px) {
    .home__body ul:has(li strong):has(> li:nth-child(2):last-child) {
        grid-template-columns: 1fr 1fr;
    }
}
@media (min-width: 960px) {
    .home__body ul:has(li strong):has(> li:nth-child(5):last-child) {
        grid-template-columns: repeat(5, 1fr);
        gap: calc(var(--step) * 3);
    }
}

/* Featured card. One item in a card list can be set on the brand colour — the
   option that matters. Every card in that list then takes a hairline box and
   padding, so the featured one reads as the same shape filled in rather than as
   a different component.

     <li class="is-featured">…</li> */
.home__body ul:has(> li.is-featured) > li {
    --card-pad: calc(var(--step) * 4);
    padding: var(--card-pad);
    border: 1px solid var(--rule);
    border-radius: var(--radius);
}
.home__body ul > li.is-featured {
    background: var(--brand-primary);
    border-color: var(--brand-primary);
    color: rgba(255, 255, 255, 0.86);
}
.home__body ul > li.is-featured strong { color: #FFFFFF; }
.home__body ul > li.is-featured .eyebrow { color: rgba(255, 255, 255, 0.72); }
/* Support slate is only 2.6:1 on the navy, so the mark goes translucent white. */
.home__body ul > li.is-featured::before { background-color: rgba(255, 255, 255, 0.16); }

/* On a phone the cards stack, and a 40px square above every lead-in doubles
   the height of the list. The icon moves beside the text instead. */
@media (max-width: 639px) {
    .home__body ul li:has(strong):has(> .icon) {
        min-height: calc(var(--card-pad, 0px) * 2 + 40px);
        padding-left: calc(var(--card-pad, 0px) + 56px);
    }
    .home__body ul li:has(strong):has(> .icon)::before {
        position: absolute;
        top: var(--card-pad, 0px);
        left: var(--card-pad, 0px);
        margin: 0;
    }
}

/* A list inside a card. A card that has to enumerate — the kinds of change a
   project plan covers, the things a second plan does — needs its own bullets,
   and without this the nested list inherits the entire card treatment from the
   rules above: its own grid, a 40px support-colour square on every item, and a
   hairline under each row, because the inner list has no bold lead-ins and so
   reads to `:has()` as a plain checklist.

   Reset to an ordinary disc list, a step down in size, so it sits under the
   description as supporting detail rather than competing with the card's own
   lead-in. Marks are `::marker`, not a second set of drawn squares — nesting
   one check grid inside another would make the card unreadable.

   Scoped through `li:has(strong)` — "a list inside a card" — rather than by
   depth alone. That is the true condition, and it also outranks the checklist
   rules above, which match the inner list on specificity and would otherwise
   win on source order. */
.home__body ul li:has(strong) ul {
    display: block;
    list-style: disc;
    margin: calc(var(--step) * 2) 0 0;
    padding-left: calc(var(--step) * 2.5);
}
.home__body ul li:has(strong) ul li {
    margin: 0;
    padding: 0;
    border: 0;
    font-size: 15px;
    line-height: 1.5;
    color: inherit;
}
.home__body ul li:has(strong) ul li + li { margin-top: calc(var(--step) * 0.75); }
.home__body ul li:has(strong) ul li::before { content: none; }

/* The support slate is only 2.6:1 on the navy, so on the featured card the
   markers go translucent white — the same swap the check squares make. */
.home__body ul li:has(strong) ul li::marker { color: var(--brand-support); }
.home__body ul li.is-featured ul li::marker { color: rgba(255, 255, 255, 0.55); }

/* Quotes, same trick as the lists: the shape of the content chooses the
   treatment. A quote that carries its own attribution paragraph is a
   testimonial and gets the card; a one-paragraph quote is a pull quote and
   stays open, so the Deming line reads as an aside rather than as evidence. */
.home__body blockquote {
    margin-block: calc(var(--step) * 6);
    padding: 0 0 0 calc(var(--step) * 3);
    background: none;
    border-left: 3px solid var(--brand-accent);
    border-radius: 0;
    font-family: var(--font-heading);
    font-style: italic;
    font-size: 21px;
    line-height: 1.5;
    color: var(--brand-primary);
}
.home__body blockquote:has(p + p) {
    padding: calc(var(--step) * 4) calc(var(--step) * 4.5);
    background: var(--paper-alt);
    border-radius: 0 var(--radius) var(--radius) 0;
    font-size: 19px;
}
/* The card is furniture, so it spans the column; the open pull quote is still
   running text and stays on the reading measure set above. */
.home__body > blockquote:has(p + p) { max-width: none; }
.home__body blockquote p:last-child { margin-bottom: 0; }

/* Attribution. Only ever the trailing paragraph of a multi-paragraph quote,
   so a single-paragraph pull quote that ends in an em-dash is left alone. */
.home__body blockquote p + p:last-child {
    font-family: var(--font-body);
    font-style: normal;
    font-size: 15px;
    line-height: 1.5;
    color: var(--ink-muted);
}
.home__body blockquote p + p:last-child strong { color: var(--ink); }

/* --- Overheard lines ------------------------------------------------------
   What the room says when a change is announced after the last few failed:
   "Here we go again." The only block on the site that quotes people who are
   not endorsing anything.

   Deliberately neither of the two quote treatments above. Both of those are
   evidence offered in the client's favour — the testimonial card is a customer
   vouching, the burgundy pull quote is a line worth keeping — and lending
   either shape to a sentence like "another flavour of the month" would dress
   skepticism up as a selling point.

   So it is the pull quote with the brand drained out of it: same left rule,
   same serif, but the rule is the hairline grey and the type is muted. The one
   passage on the page describing the cost of lost credibility is the one the
   brand palette does not put its name to.

   Stacked at every width, never columned. The three lines are a crescendo and
   are meant to be read in order; three across would set them out as equal
   options and lose the sequence.

     <div class="voices">
       <p class="voices__line">Here we go again.</p>
     </div>
   ------------------------------------------------------------------------- */

.voices {
    max-width: var(--measure);
    margin-block: calc(var(--step) * 4);
    padding-left: calc(var(--step) * 3);
    border-left: 3px solid var(--rule);
}

.voices__line {
    margin: 0;
    font-family: var(--font-heading);
    font-style: italic;
    font-size: clamp(18px, 2.2vw, 21px);
    line-height: 1.45;
    color: var(--ink-muted);
}
.voices__line + .voices__line { margin-top: calc(var(--step) * 2); }

/* Quote marks drawn by the stylesheet, so each line is typed as a plain
   sentence and all three get the same curly pair however the editor's keyboard
   behaves. Paired with the `/ ""` alternative text so a screen reader is not
   made to announce the punctuation three times. */
.voices__line::before {
    content: "\201C";
    content: "\201C" / "";
}
.voices__line::after {
    content: "\201D";
    content: "\201D" / "";
}

/* --- Home closing band --------------------------------------------------- */

.home .booking--closing {
    margin-top: clamp(56px, 8vw, 88px);
    background: var(--brand-primary);
    border-top: 0;
    color: #FFFFFF;
}
/* Full wrap width, not the narrow reading column: the band is a piece of
   page furniture, and pinning the prompt and the button to the same left and
   right edges as the header is what makes it read as one. */
.home .booking--closing .booking__inner { max-width: var(--wrap); }
.home .booking--closing .booking__prompt { color: #FFFFFF; }
.home .booking--closing .button {
    background: #FFFFFF;
    color: var(--brand-primary);
}
.home .booking--closing .button:hover { background: rgba(255, 255, 255, 0.88); filter: none; }
.home .booking--closing .booking__email { color: rgba(255, 255, 255, 0.8); }
.home .booking--closing .booking__email a { color: #FFFFFF; }
.home .booking--closing .booking__note { color: rgba(255, 255, 255, 0.72); }

/* When the body ends on a brand band, the closing band continues it instead
   of stacking a second navy block beneath: no gap, no prompt of its own (the
   band's last line is the invitation), and pulled in to the body column so the
   button sits directly under that line. Both selectors cover the band whether
   or not Ghost wraps the HTML card in a div. Without :has() the two bands
   simply stack, which is still correct. */
.home__body > .band:last-child,
.home__body > :last-child > .band {
    margin-bottom: 0;
    padding-bottom: calc(var(--step) * 4);
}
.home:has(.home__body > .band:last-child, .home__body > :last-child > .band) .booking--closing {
    margin-top: 0;
    padding-top: 0;
    padding-bottom: clamp(56px, 8vw, 96px);
}
.home:has(.home__body > .band:last-child, .home__body > :last-child > .band) .booking--closing .booking__inner {
    max-width: var(--home-column);
}
.home:has(.home__body > .band:last-child, .home__body > :last-child > .band) .booking--closing .booking__prompt {
    display: none;
}

/* --- Page / post / letter --------------------------------------------- */

.page__header,
.post__header,
.letter__header {
    padding-block: clamp(40px, 6vw, 68px) calc(var(--step) * 3);
}

.page__lede,
.letter__lede {
    font-family: var(--font-heading);
    font-size: 20px;
    line-height: 1.5;
    color: var(--ink-muted);
    max-width: 56ch;
}

/* A lead-in line that sits above body copy without becoming a section heading.

   Jim sets this line at 16pt against 14pt body in his own document — larger
   and in the brand navy, but not bold, and not a title. Published as an <h3>
   it picked up the accent-mark heading treatment and read as a section heading
   standing alongside the real ones; published as body copy it disappeared.

   Deliberately navy rather than the muted grey of .page__lede, and a step
   smaller, so that on a page carrying both it reads as subordinate to the page
   lede instead of competing with it. */
.prose .standfirst {
    font-family: var(--font-heading);
    font-size: 19px;
    line-height: 1.5;
    color: var(--brand-primary);
    max-width: 56ch;
}

.post__meta,
.archive__item-meta {
    font-size: 14px;
    color: var(--ink-muted);
    margin: 0;
}
.post__meta-sep { margin-inline: 0.5em; }

.letter__eyebrow {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ink-muted);
    margin: 0 0 var(--step);
}

/* --- Letter close: sign-off and booking, as one block ---------------------
   A letter ends with a person, so the sign-off carries a portrait, a name and
   a credential line rather than a logo and a site tagline. The booking button
   sits in the same block: the reader finishes the letter, meets the sender,
   and the ask is right there. A sign-off followed by a separate band making
   the same ask reads as two endings.

   The band chrome -- grey ground, top rule -- belongs to this section, so the
   booking partial nested inside it renders bare. See .booking--letter below.
   ------------------------------------------------------------------------- */

.letter__close {
    margin-top: calc(var(--step) * 6);
    border-top: 1px solid var(--rule);
    background: var(--paper-alt);
    padding-block: clamp(36px, 6vw, 56px);
}

.signature {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: calc(var(--step) * 2) calc(var(--step) * 3);
}

/* 96px, against the About bio card's 180px. This is a sign-off, not an
   introduction: the portrait is here to put a face to the name at the end of
   a letter, and at the end of a letter it should not outweigh the ask beside
   it. The same 400x400 headshot is sharp at this size on any screen. */
.signature__photo {
    flex: none;
    width: 96px;
    height: 96px;
    border-radius: 50%;
    object-fit: cover;
    border: 1px solid var(--rule);
}

/* Fallback when no portrait is set: the site logo, at the size it had when
   the footer was a logo and a tagline. */
.signature__mark { flex: none; max-height: 40px; width: auto; }

/* 16rem basis, as on the bio card: below that the text is narrower than the
   portrait and the block should stack. */
.signature__body { flex: 1 1 16rem; }

.signature__name {
    margin: 0 0 calc(var(--step) * 0.5);
    font-family: var(--font-heading);
    font-size: 21px;
    font-weight: 700;
    line-height: 1.2;
    color: var(--brand-primary);
}
.signature__line { margin: 0; font-size: 15px; line-height: 1.5; color: var(--ink-muted); }
.signature__contact { margin: calc(var(--step) * 0.5) 0 0; font-size: 15px; }

/* --- Letter: who it was written for ---------------------------------------
   One line at the top of the body, naming the audience the letter is for. It
   is the strongest "this was written for you" signal on the page, and it is
   deliberately content rather than a tag: tags label the page in admin, and
   nothing that labels the page is allowed to reach the reader.

     <p class="letter__for">Written for managing partners at mid-size firms</p>

   Serif and sentence-shaped, against the tracked uppercase eyebrow above the
   headline. Two lines in the same instrument, one under the other, read as a
   stutter rather than as two different things.
   ------------------------------------------------------------------------- */

.prose .letter__for {
    display: flex;
    align-items: center;
    gap: calc(var(--step) * 1.5);
    margin: 0 0 calc(var(--step) * 4);
    font-family: var(--font-heading);
    font-size: 16px;
    line-height: 1.4;
    color: var(--ink-muted);
}
.prose .letter__for::before {
    content: "";
    flex: none;
    width: 24px;
    height: 2px;
    background: var(--brand-accent);
}

.feature-image { margin-block: calc(var(--step) * 3); }
.feature-image figcaption {
    margin-top: var(--step);
    font-size: 14px;
    color: var(--ink-muted);
}

/* --- Booking ------------------------------------------------------------ */

.booking { padding-block: calc(var(--step) * 3); }

.booking--closing {
    margin-top: calc(var(--step) * 6);
    border-top: 1px solid var(--rule);
    background: var(--paper-alt);
    padding-block: clamp(36px, 6vw, 56px);
}

/* Inside the letter close the surrounding section already supplies the ground
   and the top rule, so the variant renders bare and a hairline across the
   column separates the ask from the signature above it. */
.booking--letter { margin: 0; padding-block: 0; background: none; border: 0; }
.letter__close .booking__inner {
    margin-top: calc(var(--step) * 3);
    padding-top: calc(var(--step) * 3);
    border-top: 1px solid var(--rule);
}

.booking__inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: calc(var(--step) * 2) calc(var(--step) * 3);
}

.booking__prompt {
    font-family: var(--font-heading);
    font-size: clamp(20px, 2.6vw, 25px);
    color: var(--brand-primary);
    margin: 0;
    flex: 1 1 22ch;
}

.booking__email {
    margin: 0;
    font-size: 15px;
    color: var(--ink-muted);
}

/* Full row under the button and email, from the closing_note setting. */
.booking__note {
    flex-basis: 100%;
    margin: 0;
    font-size: 14px;
    color: var(--ink-muted);
}

/* Phone-only booking button inside a section, for a long page where the next
   booking button is several screens away. The sticky header button is small
   and easy to miss on a phone; on desktop it is always in view, so this stays
   hidden. Pair with data-booking so it follows booking_url (see main.js):

     <p class="mobile-cta"><a class="button" href="#contact" data-booking>Book a call</a></p> */
.mobile-cta { display: none; }
@media (max-width: 639px) {
    .mobile-cta { display: block; }
    .mobile-cta .button { display: block; text-align: center; }
}

/* --- Archive (fallback) ------------------------------------------------- */

.archive__title { padding-block: clamp(40px, 6vw, 64px) calc(var(--step) * 3); }

.archive__item {
    padding-block: calc(var(--step) * 3);
    border-top: 1px solid var(--rule);
}
.archive__item-title { font-size: 22px; margin-bottom: var(--step); }
.archive__item-title a { color: var(--brand-primary); text-decoration: none; }
.archive__item-title a:hover { text-decoration: underline; }
.archive__item-excerpt { color: var(--ink-muted); margin: var(--step) 0 0; }

.pagination {
    display: flex;
    justify-content: space-between;
    gap: calc(var(--step) * 2);
    padding-block: calc(var(--step) * 4);
    border-top: 1px solid var(--rule);
    font-size: 15px;
}

/* --- Error -------------------------------------------------------------- */

.error { padding-block: clamp(64px, 12vw, 128px); text-align: center; }
.error__code {
    font-family: var(--font-heading);
    font-size: 64px;
    color: var(--rule);
    margin: 0;
    line-height: 1;
}
.error__message { color: var(--ink-muted); }

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

.site-footer {
    margin-top: calc(var(--step) * 8);
    border-top: 1px solid var(--rule);
    padding-block: calc(var(--step) * 5);
}
.site-footer__inner {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: calc(var(--step) * 3) calc(var(--step) * 6);
}
.site-footer__brand { max-width: 46ch; }

/* The footer is a two-column row — brand on the left, secondary navigation on
   the right. Until Privacy / Terms exist there is no secondary navigation, so
   the brand block is the row's only child: `space-between` has nothing to push
   it against and `max-width: 46ch` keeps it narrow, leaving a small block
   stranded at the left of a full-width wrap. It reads as a bug rather than a
   choice.

   Centre it, and give it a slightly wider measure so the tagline holds one
   line. `:only-child` stops matching the moment a secondary nav item is added
   under Settings -> Navigation, and the two-column layout returns on its own
   with nothing to undo here. */
.site-footer__inner > .site-footer__brand:only-child {
    max-width: 60ch;
    margin-inline: auto;
    text-align: center;
}
.site-footer__nav ul {
    display: flex;
    flex-wrap: wrap;
    gap: calc(var(--step) * 3);
    list-style: none;
    margin: 0;
    padding: 0;
}
.site-footer__nav a {
    font-size: 14px;
    color: var(--ink-muted);
    text-decoration: none;
}
.site-footer__nav a:hover { color: var(--brand-accent); }
.site-footer__title {
    font-family: var(--font-heading);
    font-size: 20px;
    font-weight: 600;
    color: var(--brand-primary);
    margin: 0 0 var(--step);
}
.site-footer__description,
.site-footer__contact,
.site-footer__legal {
    font-size: 15px;
    color: var(--ink-muted);
    margin: 0 0 var(--step);
}
.site-footer__legal { margin-bottom: 0; }
.site-footer__contact a { color: var(--brand-primary); }

/* --- Bio card ------------------------------------------------------------
   The About-page identity block, and the answer to a headshot that cannot be
   made bigger.

   jim-headshot-400.jpeg is a 400x400 LinkedIn download that measures 200 on a
   Laplacian-variance sharpness check and loses only ~1.7 grey levels per pixel
   on a 2x down/up round trip — it carries noticeably less real detail than its
   dimensions suggest, so 180px is a hard ceiling on a 2x screen. See
   export/assets/README.md.

   A 180px circle floated alone against 1,200 words reads as a small photo. The
   same 180px circle set into a panel beside a name and a credential line reads
   as a deliberate bio block, because the structure around it, not the image,
   is carrying the weight. Replace with a proper portrait treatment only when a
   photographer's original arrives.

   Insert with an HTML card so the classes survive the editor — see the README.
   -------------------------------------------------------------------------- */

.prose .bio-card {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: calc(var(--step) * 3) calc(var(--step) * 4);
    margin-block: calc(var(--step) * 4);
    padding: calc(var(--step) * 4);
    background: var(--paper-alt);
    border-radius: var(--radius);
}

.prose .bio-card img {
    flex: none;
    width: 180px;
    height: 180px;
    border-radius: 50%;
    object-fit: cover;
    border: 1px solid var(--rule);
}

/* 16rem basis: below that the text is narrower than the portrait and the card
   should stack instead. */
.bio-card__body { flex: 1 1 16rem; }

.bio-card__name {
    margin: 0 0 calc(var(--step) * 0.5);
    font-family: var(--font-heading);
    font-size: 24px;
    font-weight: 700;
    line-height: 1.2;
    color: var(--brand-primary);
}

.bio-card__role {
    margin: 0 0 calc(var(--step) * 2);
    font-size: 15px;
    color: var(--ink-muted);
}

.bio-card__credential {
    margin: 0;
    padding-top: calc(var(--step) * 2);
    border-top: 1px solid var(--rule);
    font-size: 15px;
    line-height: 1.5;
    color: var(--ink);
}

/* --- Bio portrait --------------------------------------------------------
   Deliberately capped at 180px. A headshot exported at LinkedIn's 400x400
   has roughly 200px of usable CSS width on a 2x screen and 133px on a 3x
   phone; past that it visibly softens. Small and sharp beats large and mushy.

   Insert with an HTML card in the editor so the class survives:
     <figure class="portrait">
       <img src="..." alt="..." width="360" height="360" loading="lazy">
     </figure>
   -------------------------------------------------------------------------- */

.prose .portrait {
    margin: 0 0 calc(var(--step) * 3);
}

.prose .portrait img {
    width: 180px;
    height: 180px;
    border-radius: 50%;
    object-fit: cover;
    border: 1px solid var(--rule);
}

.prose .portrait figcaption {
    max-width: 180px;
    margin-top: var(--step);
    font-size: 14px;
    line-height: 1.4;
    color: var(--ink-muted);
}

@media (min-width: 620px) {
    .prose .portrait {
        float: right;
        margin: calc(var(--step) * 0.5) 0 calc(var(--step) * 2) calc(var(--step) * 4);
    }
}

/* --- Photograph beside the copy ------------------------------------------
   A rectangular photograph set into the text column, for a photo of the
   client at work. Distinct from .portrait above, which is a 180px circle for
   a headshot: a three-quarter shot of someone gesturing does not survive
   being cropped to a circle, and at 180px the gesture is lost anyway.

   Floated at 260px from 620px up, full width below that -- the same
   breakpoint and behaviour as .portrait, so the two read as one family.

   Insert with an HTML card so the class survives the editor:
     <figure class="photo photo--float">
       <img src="..." alt="..." width="1400" height="2036" loading="lazy">
     </figure>
   ------------------------------------------------------------------------- */

.prose .photo { margin: 0 0 calc(var(--step) * 3); }

.prose .photo img {
    display: block;
    width: 100%;
    height: auto;
    border-radius: var(--radius);
    border: 1px solid var(--rule);
}

.prose .photo figcaption {
    margin-top: var(--step);
    font-size: 14px;
    line-height: 1.4;
    color: var(--ink-muted);
}

@media (min-width: 620px) {
    .prose .photo--float {
        float: right;
        width: 260px;
        margin: calc(var(--step) * 0.5) 0 calc(var(--step) * 3) calc(var(--step) * 4);
    }
}

/* --- Editor cards (Koenig) ---------------------------------------------
   The editor can set an image, gallery or embed to break out of the text
   column. .kg-width-wide and .kg-width-full are required by Ghost.
   ---------------------------------------------------------------------- */

.prose :where(.kg-card) { margin-block: calc(var(--step) * 4); }

.prose :where(.kg-width-wide, .kg-width-full) {
    position: relative;
    left: 50%;
    transform: translateX(-50%);
}

.prose .kg-width-wide { width: min(1120px, calc(100vw - 40px)); }

.prose .kg-width-full { width: 100vw; }

.prose :where(.kg-width-wide, .kg-width-full) img { width: 100%; }

.prose .kg-image { margin-inline: auto; }

.kg-card figcaption,
.kg-card .kg-card-caption {
    margin-top: var(--step);
    font-size: 14px;
    line-height: 1.5;
    color: var(--ink-muted);
    text-align: center;
}

.prose .kg-bookmark-card a.kg-bookmark-container {
    display: flex;
    flex-wrap: wrap;
    text-decoration: none;
    color: inherit;
    border: 1px solid var(--rule);
    border-radius: var(--radius);
    overflow: hidden;
}

.kg-bookmark-content { flex: 1 1 240px; padding: calc(var(--step) * 2); }
.kg-bookmark-title { font-weight: 600; color: var(--brand-primary); }
.kg-bookmark-description,
.kg-bookmark-metadata { font-size: 14px; color: var(--ink-muted); }

.prose .kg-button-card a.kg-btn {
    display: inline-block;
    background: var(--brand-accent);
    color: #FFFFFF;
    font-weight: 600;
    text-decoration: none;
    padding: calc(var(--step) * 1.75) calc(var(--step) * 3);
    border-radius: var(--radius);
}

.prose .kg-callout-card {
    display: flex;
    gap: calc(var(--step) * 1.5);
    padding: calc(var(--step) * 2);
    background: var(--paper-alt);
    border-left: 3px solid var(--brand-accent);
}

/* On the homepage a callout is a boxed story set apart from the running
   argument: a hairline box with a support-colour cap, deliberately not the
   burgundy left rule, which already belongs to the pull quote. Ghost's own card
   CSS colours callouts by variant; this outranks all of them, so the editor's
   colour choice does not matter. */
.home__body .kg-callout-card {
    max-width: var(--measure);
    margin-block: calc(var(--step) * 4);
    padding: calc(var(--step) * 3.5) calc(var(--step) * 4);
    background: var(--paper-alt);
    border: 1px solid var(--rule);
    border-top: 3px solid var(--brand-support);
    border-radius: 0 0 var(--radius) var(--radius);
}
.home__body .kg-callout-text {
    font-size: 16px;
    line-height: 1.6;
    color: var(--ink-muted);
}

/* --- Icons ---------------------------------------------------------------
   Phosphor Icons, Fill weight. MIT licence, Copyright (c) 2023 Phosphor Icons,
   https://phosphoricons.com — the licence text ships in the theme's LICENSE.

     <span class="icon icon--brain" aria-hidden="true"></span>

   Each icon is a CSS mask over a currentColor fill, so it takes the colour of
   the text around it and needs no per-colour variants. Same constraint as the
   check marks: data-URIs in this file, no icon font, no extra request. Names
   are Phosphor's, minus the weight suffix. Always pair an icon with visible
   text and keep aria-hidden="true" — none of them carries meaning on its own.
   -------------------------------------------------------------------------- */

.icon {
    display: inline-block;
    flex: none;
    width: 1em;
    height: 1em;
    vertical-align: -0.125em;
    background-color: currentColor;
    -webkit-mask: var(--icon) center / contain no-repeat;
    mask: var(--icon) center / contain no-repeat;
}
.icon--arrow-down { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M205.66,149.66l-72,72a8,8,0,0,1-11.32,0l-72-72A8,8,0,0,1,56,136h64V40a8,8,0,0,1,16,0v96h64a8,8,0,0,1,5.66,13.66Z'/%3E%3C/svg%3E"); }
.icon--arrow-up { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M207.39,115.06A8,8,0,0,1,200,120H136v96a8,8,0,0,1-16,0V120H56a8,8,0,0,1-5.66-13.66l72-72a8,8,0,0,1,11.32,0l72,72A8,8,0,0,1,207.39,115.06Z'/%3E%3C/svg%3E"); }
.icon--brain { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M212,76V72a44,44,0,0,0-74.86-31.31,3.93,3.93,0,0,0-1.14,2.8v88.72a4,4,0,0,0,6.2,3.33A47.67,47.67,0,0,1,167.68,128a8.18,8.18,0,0,1,8.31,7.58,8,8,0,0,1-8,8.42,32,32,0,0,0-32,32v33.88a4,4,0,0,0,1.49,3.12,47.92,47.92,0,0,0,74.21-17.16,4,4,0,0,0-4.49-5.56A68.06,68.06,0,0,1,192,192h-7.73a8.18,8.18,0,0,1-8.25-7.47,8,8,0,0,1,8-8.53h8a51.6,51.6,0,0,0,24-5.88v0A52,52,0,0,0,212,76Zm-12,36h-4a36,36,0,0,1-36-36V72a8,8,0,0,1,16,0v4a20,20,0,0,0,20,20h4a8,8,0,0,1,0,16ZM88,28A44.05,44.05,0,0,0,44,72v4a52,52,0,0,0-4,94.12h0A51.6,51.6,0,0,0,64,176h7.73A8.18,8.18,0,0,1,80,183.47,8,8,0,0,1,72,192H64a67.48,67.48,0,0,1-15.21-1.73,4,4,0,0,0-4.5,5.55A47.93,47.93,0,0,0,118.51,213a4,4,0,0,0,1.49-3.12V176a32,32,0,0,0-32-32,8,8,0,0,1-8-8.42A8.18,8.18,0,0,1,88.32,128a47.67,47.67,0,0,1,25.48,7.54,4,4,0,0,0,6.2-3.33V43.49a4,4,0,0,0-1.14-2.81A43.85,43.85,0,0,0,88,28Zm8,48a36,36,0,0,1-36,36H56a8,8,0,0,1,0-16h4A20,20,0,0,0,80,76V72a8,8,0,0,1,16,0Z'/%3E%3C/svg%3E"); }
.icon--calendar-x { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M208,32H184V24a8,8,0,0,0-16,0v8H88V24a8,8,0,0,0-16,0v8H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM157.66,170.34a8,8,0,0,1-11.32,11.32L128,163.31l-18.34,18.35a8,8,0,0,1-11.32-11.32L116.69,152,98.34,133.66a8,8,0,0,1,11.32-11.32L128,140.69l18.34-18.35a8,8,0,0,1,11.32,11.32L139.31,152ZM208,80H48V48H72v8a8,8,0,0,0,16,0V48h80v8a8,8,0,0,0,16,0V48h24Z'/%3E%3C/svg%3E"); }
.icon--check-circle { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm45.66,85.66-56,56a8,8,0,0,1-11.32,0l-24-24a8,8,0,0,1,11.32-11.32L112,148.69l50.34-50.35a8,8,0,0,1,11.32,11.32Z'/%3E%3C/svg%3E"); }
.icon--envelope-simple { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M224,48H32a8,8,0,0,0-8,8V192a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A8,8,0,0,0,224,48Zm-8,144H40V74.19l82.59,75.71a8,8,0,0,0,10.82,0L216,74.19V192Z'/%3E%3C/svg%3E"); }
.icon--hand-coins { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M128.09,57.38a36,36,0,0,1,55.17-27.82,4,4,0,0,1-.56,7A52.06,52.06,0,0,0,152,84c0,1.17,0,2.34.12,3.49a4,4,0,0,1-6,3.76A36,36,0,0,1,128.09,57.38ZM240,160.61a24.47,24.47,0,0,1-13.6,22l-.44.2-38.83,16.54a6.94,6.94,0,0,1-1.19.4l-64,16A7.93,7.93,0,0,1,120,216H16A16,16,0,0,1,0,200V160a16,16,0,0,1,16-16H44.69l22.62-22.63A31.82,31.82,0,0,1,89.94,112H140a28,28,0,0,1,27.25,34.45l41.84-9.62A24.61,24.61,0,0,1,240,160.61Zm-16,0a8.61,8.61,0,0,0-10.87-8.3l-.31.08-67,15.41a8.32,8.32,0,0,1-1.79.2H112a8,8,0,0,1,0-16h28a12,12,0,0,0,0-24H89.94a15.86,15.86,0,0,0-11.31,4.69L56,155.31V200h63l62.43-15.61,38-16.18A8.56,8.56,0,0,0,224,160.61ZM168,84a36,36,0,1,0,36-36A36,36,0,0,0,168,84Z'/%3E%3C/svg%3E"); }
.icon--handshake { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M254.3,107.91,228.78,56.85a16,16,0,0,0-21.47-7.15L182.44,62.13,130.05,48.27a8.14,8.14,0,0,0-4.1,0L73.56,62.13,48.69,49.7a16,16,0,0,0-21.47,7.15L1.7,107.9a16,16,0,0,0,7.15,21.47l27,13.51,55.49,39.63a8.06,8.06,0,0,0,2.71,1.25l64,16a8,8,0,0,0,7.6-2.1l40-40,15.08-15.08,26.42-13.21a16,16,0,0,0,7.15-21.46Zm-54.89,33.37L165,113.72a8,8,0,0,0-10.68.61C136.51,132.27,116.66,130,104,122L147.24,80h31.81l27.21,54.41Zm-41.87,41.86L99.42,168.61l-49.2-35.14,28-56L128,64.28l9.8,2.59-45,43.68-.08.09a16,16,0,0,0,2.72,24.81c20.56,13.13,45.37,11,64.91-5L188,152.66Zm-25.72,34.8a8,8,0,0,1-7.75,6.06,8.13,8.13,0,0,1-1.95-.24L80.41,213.33a7.89,7.89,0,0,1-2.71-1.25L51.35,193.26a8,8,0,0,1,9.3-13l25.11,17.94L126,208.24A8,8,0,0,1,131.82,217.94Z'/%3E%3C/svg%3E"); }
.icon--hard-drives { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M208,40H48A16,16,0,0,0,32,56v48a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V56A16,16,0,0,0,208,40ZM180,92a12,12,0,1,1,12-12A12,12,0,0,1,180,92Z'/%3E%3Cpath d='M208,136H48a16,16,0,0,0-16,16v48a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V152A16,16,0,0,0,208,136Zm-28,52a12,12,0,1,1,12-12A12,12,0,0,1,180,188Z'/%3E%3C/svg%3E"); }
.icon--hourglass-medium { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M200,75.64V40a16,16,0,0,0-16-16H72A16,16,0,0,0,56,40V76a16.07,16.07,0,0,0,6.4,12.8L114.67,128,62.4,167.2A16.07,16.07,0,0,0,56,180v36a16,16,0,0,0,16,16H184a16,16,0,0,0,16-16V180.36a16.09,16.09,0,0,0-6.35-12.77L141.27,128l52.38-39.59A16.09,16.09,0,0,0,200,75.64ZM184,180.36V216H72V180l48-36v24a8,8,0,0,0,16,0V144.08Zm0-104.72L178.23,80H77.33L72,76V40H184Z'/%3E%3C/svg%3E"); }
.icon--map-pin-line { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M200,224H150.54A266.56,266.56,0,0,0,174,200.25c27.45-31.57,42-64.85,42-96.25a88,88,0,0,0-176,0c0,31.4,14.51,64.68,42,96.25A266.56,266.56,0,0,0,105.46,224H56a8,8,0,0,0,0,16H200a8,8,0,0,0,0-16ZM128,72a32,32,0,1,1-32,32A32,32,0,0,1,128,72Z'/%3E%3C/svg%3E"); }
.icon--money-wavy { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M244.24,60a8,8,0,0,0-7.75-.4c-42.93,21-73.59,11.16-106,.78C96.4,49.53,61.2,38.28,12.49,62.06A8,8,0,0,0,8,69.24V189.17a8,8,0,0,0,11.51,7.19c42.93-21,73.59-11.16,106.05-.78,19.24,6.15,38.84,12.42,61,12.42,17.09,0,35.73-3.72,56.91-14.06a8,8,0,0,0,4.49-7.18V66.83A8,8,0,0,0,244.24,60ZM48,152a8,8,0,0,1-16,0V88a8,8,0,0,1,16,0Zm80,8a32,32,0,1,1,32-32A32,32,0,0,1,128,160Zm96,8a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Z'/%3E%3C/svg%3E"); }
.icon--path { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M228,200a28,28,0,0,1-54.83,8H72a48,48,0,0,1,0-96h96a24,24,0,0,0,0-48H72a8,8,0,0,1,0-16h96a40,40,0,0,1,0,80H72a32,32,0,0,0,0,64H173.17A28,28,0,0,1,228,200Z'/%3E%3C/svg%3E"); }
.icon--prohibit { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M200,128a71.69,71.69,0,0,1-15.78,44.91L83.09,71.78A71.95,71.95,0,0,1,200,128ZM56,128a71.95,71.95,0,0,0,116.91,56.22L71.78,83.09A71.69,71.69,0,0,0,56,128Zm180,0A108,108,0,1,1,128,20,108.12,108.12,0,0,1,236,128Zm-20,0a88,88,0,1,0-88,88A88.1,88.1,0,0,0,216,128Z'/%3E%3C/svg%3E"); }
.icon--robot { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M200,48H136V16a8,8,0,0,0-16,0V48H56A32,32,0,0,0,24,80V192a32,32,0,0,0,32,32H200a32,32,0,0,0,32-32V80A32,32,0,0,0,200,48ZM172,96a12,12,0,1,1-12,12A12,12,0,0,1,172,96ZM96,184H80a16,16,0,0,1,0-32H96ZM84,120a12,12,0,1,1,12-12A12,12,0,0,1,84,120Zm60,64H112V152h32Zm32,0H160V152h16a16,16,0,0,1,0,32Z'/%3E%3C/svg%3E"); }
.icon--shield-warning { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M208,40H48A16,16,0,0,0,32,56v56c0,52.72,25.52,84.67,46.93,102.19,23.06,18.86,46,25.27,47,25.53a8,8,0,0,0,4.2,0c1-.26,23.91-6.67,47-25.53C198.48,196.67,224,164.72,224,112V56A16,16,0,0,0,208,40ZM120,96a8,8,0,0,1,16,0v40a8,8,0,0,1-16,0Zm8,88a12,12,0,1,1,12-12A12,12,0,0,1,128,184Z'/%3E%3C/svg%3E"); }
.icon--smiley-sad { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24ZM92,96a12,12,0,1,1-12,12A12,12,0,0,1,92,96Zm80,86.92A8,8,0,0,1,161.08,180c-7.47-12.91-19.21-20-33.08-20s-25.61,7.1-33.08,20a8,8,0,1,1-13.84-8c10.29-17.79,27.39-28,46.92-28s36.63,10.2,46.92,28A8,8,0,0,1,172,182.92ZM164,120a12,12,0,1,1,12-12A12,12,0,0,1,164,120Z'/%3E%3C/svg%3E"); }
.icon--target { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M221.87,83.16A104.1,104.1,0,1,1,195.67,49l22.67-22.68a8,8,0,0,1,11.32,11.32L167.6,99.71h0l-37.71,37.71-23.95,23.95a40,40,0,0,0,62-35.67,8,8,0,1,1,16-.9,56,56,0,0,1-95.5,42.79h0a56,56,0,0,1,73.13-84.43L184.3,60.39a87.88,87.88,0,1,0,23.13,29.67,8,8,0,0,1,14.44-6.9Z'/%3E%3C/svg%3E"); }
.icon--tree-structure { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M144,96V80H128a8,8,0,0,0-8,8v80a8,8,0,0,0,8,8h16V160a16,16,0,0,1,16-16h48a16,16,0,0,1,16,16v48a16,16,0,0,1-16,16H160a16,16,0,0,1-16-16V192H128a24,24,0,0,1-24-24V136H72v8a16,16,0,0,1-16,16H24A16,16,0,0,1,8,144V112A16,16,0,0,1,24,96H56a16,16,0,0,1,16,16v8h32V88a24,24,0,0,1,24-24h16V48a16,16,0,0,1,16-16h48a16,16,0,0,1,16,16V96a16,16,0,0,1-16,16H160A16,16,0,0,1,144,96Z'/%3E%3C/svg%3E"); }
.icon--trend-down { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M240,128v64a8,8,0,0,1-8,8H168a8,8,0,0,1-5.66-13.66L188.69,160,136,107.31l-34.34,34.35a8,8,0,0,1-11.32,0l-72-72A8,8,0,0,1,29.66,58.34L96,124.69l34.34-34.35a8,8,0,0,1,11.32,0L200,148.69l26.34-26.35A8,8,0,0,1,240,128Z'/%3E%3C/svg%3E"); }
.icon--trend-up { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M240,56v64a8,8,0,0,1-13.66,5.66L200,99.31l-58.34,58.35a8,8,0,0,1-11.32,0L96,123.31,29.66,189.66a8,8,0,0,1-11.32-11.32l72-72a8,8,0,0,1,11.32,0L136,140.69,188.69,88,162.34,61.66A8,8,0,0,1,168,48h64A8,8,0,0,1,240,56Z'/%3E%3C/svg%3E"); }
.icon--user-plus { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M256,136a8,8,0,0,1-8,8H232v16a8,8,0,0,1-16,0V144H200a8,8,0,0,1,0-16h16V112a8,8,0,0,1,16,0v16h16A8,8,0,0,1,256,136ZM144,157.68a68,68,0,1,0-71.9,0c-20.65,6.76-39.23,19.39-54.17,37.17A8,8,0,0,0,24,208H192a8,8,0,0,0,6.13-13.15C183.18,177.07,164.6,164.44,144,157.68Z'/%3E%3C/svg%3E"); }
.icon--users-three { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M64.12,147.8a4,4,0,0,1-4,4.2H16a8,8,0,0,1-7.8-6.17,8.35,8.35,0,0,1,1.62-6.93A67.79,67.79,0,0,1,37,117.51a40,40,0,1,1,66.46-35.8,3.94,3.94,0,0,1-2.27,4.18A64.08,64.08,0,0,0,64,144C64,145.28,64,146.54,64.12,147.8Zm182-8.91A67.76,67.76,0,0,0,219,117.51a40,40,0,1,0-66.46-35.8,3.94,3.94,0,0,0,2.27,4.18A64.08,64.08,0,0,1,192,144c0,1.28,0,2.54-.12,3.8a4,4,0,0,0,4,4.2H240a8,8,0,0,0,7.8-6.17A8.33,8.33,0,0,0,246.17,138.89Zm-89,43.18a48,48,0,1,0-58.37,0A72.13,72.13,0,0,0,65.07,212,8,8,0,0,0,72,224H184a8,8,0,0,0,6.93-12A72.15,72.15,0,0,0,157.19,182.07Z'/%3E%3C/svg%3E"); }

/* --- Utilities ---------------------------------------------------------- */

.notice {
    padding: calc(var(--step) * 2);
    background: var(--paper-alt);
    border-left: 3px solid var(--brand-accent);
    font-size: 15px;
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
    }
}
