/* Inter, self-hosted. Served from this template's own assets rather than
   Google Fonts: an @import there costs a DNS lookup and TLS handshake to
   fonts.googleapis.com, a stylesheet round trip, then a second handshake to
   fonts.gstatic.com for the file itself — three sequential hops before any
   text can paint. From here the browser finds the face as it parses this
   sheet, on a connection it already has open.

   One variable file per subset carries every weight and the optical-size
   axis, so there is no per-weight download. The browser fetches only the
   subsets the page actually needs: latin for English copy, the italic only
   once something on the page is italic. font-display: swap paints in the
   fallback immediately and swaps Inter in when it lands, so text is never
   invisible while the font loads. */
@font-face {
    font-family: "Inter";
    font-style: normal;
    font-weight: 300 800;
    font-display: swap;
    src: url("../fonts/inter-latin-normal.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: "Inter";
    font-style: normal;
    font-weight: 300 800;
    font-display: swap;
    src: url("../fonts/inter-latin-ext-normal.woff2") format("woff2");
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: "Inter";
    font-style: italic;
    font-weight: 300 800;
    font-display: swap;
    src: url("../fonts/inter-latin-italic.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: "Inter";
    font-style: italic;
    font-weight: 300 800;
    font-display: swap;
    src: url("../fonts/inter-latin-ext-italic.woff2") format("woff2");
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Your stylesheet. Everything here is yours to change.
   Files in assets/ load themselves, so there is nothing to register.

   Three parts: the tokens and page chrome, then the listing pages, then the
   post page. The widget styles in css/widgets/ read the variables below. */

/* Shared by every page: tokens, navigation, buttons, footer. */
:root {
    /* One warm grey scale — Aave's — for the whole site. Three text levels,
       two border levels: strong rules on furniture, soft fills on chips. */
    --ink: #272228;
    --ink-soft: rgba(39, 34, 40, 0.65);
    --ink-faint: rgba(39, 34, 40, 0.45);
    --paper: #ffffff;
    --paper-soft: #f7f6f6;
    --line: rgba(38, 34, 40, 0.1);
    --line-soft: rgba(38, 34, 40, 0.05);
    --accent: #272228;

    /* Inter throughout. font-optical-sizing below is what turns the big
       sizes into Inter Display rather than blown-up body Inter. */
    --sans: "Inter", ui-sans-serif, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    /* Only decorative glyphs — the pull-quote mark. Echoes the serif of the
       Pocket logotype without shipping another webfont. */
    --serif: "Iowan Old Style", Georgia, "Times New Roman", serif;

    --measure: 40rem;
    /* The Pocket header is 1072px, so every listing runs to the same. */
    --wide: 67rem;
    --shell: 67rem;
    --pad: 2rem;
    --radius: 0.5rem;
    --radius-small: 0.375rem;
    /* Quiet corners read as more expensive than round ones. */
    --radius-large: 0.625rem;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

/* Jumping to a contents entry glides instead of cutting, so you can see where
   in the article you landed. Native and CSS-only — no scroll hijacking, no
   library, nothing on the main thread.

   Behind no-preference because smooth scrolling is a real trigger for people
   with vestibular disorders, and the OS setting is how they say so. */
@media (prefers-reduced-motion: no-preference) {
    html { scroll-behavior: smooth; }
}
body {
    margin: 0;
    background: var(--paper);
    color: var(--ink);
    font-family: var(--sans);
    font-size: 1rem;
    line-height: 1.65;
    font-optical-sizing: auto;
    letter-spacing: -0.006em;
    -webkit-font-smoothing: antialiased;
}
a { color: inherit; }

/* ── Navigation ─────────────────────────────────────────────── */
.nav {
    border-bottom: 1px solid var(--line);
    background: var(--paper);
}

/* The dashboard's sticky-navigation setting. */
.nav-fixed {
    position: sticky;
    top: 0;
    z-index: 40;
}
.nav-inner {
    max-width: var(--shell);
    margin: 0 auto;
    padding: 1.125rem 1.5rem;
    display: flex;
    align-items: center;
    gap: 2.5rem;
}
.brand {
    font-family: var(--sans);
    font-weight: 800;
    letter-spacing: -0.02em;
    font-size: 1.0625rem;
    text-decoration: none;
}
.nav-links { display: flex; gap: 1.75rem; }
.nav-links a {
    font-size: 0.9375rem;
    color: var(--ink-soft);
    text-decoration: none;
}
.nav-links a:hover { color: var(--ink); }
.nav-end { margin-left: auto; display: flex; align-items: center; gap: 1.25rem; }
.button {
    display: inline-flex;
    align-items: center;
    padding: 0.5rem 1rem;
    border-radius: var(--radius);
    background: var(--accent);
    color: var(--paper);
    font-size: 0.9375rem;
    font-weight: 500;
    text-decoration: none;
    border: 0;
    cursor: pointer;
}
.button:hover { opacity: 0.88; }

/* ── Footer ─────────────────────────────────────────────────── */
.footer {
    margin-top: 5rem;
    background: #111214;
    color: #d7d8da;
}
.footer-inner {
    max-width: var(--shell);
    margin: 0 auto;
    padding: 3.5rem 1.5rem 2rem;
    display: grid;
    grid-template-columns: 1.4fr 1fr 1fr auto;
    gap: 2.5rem;
}
.footer .brand { color: #fff; }
.footer h3 {
    margin: 0 0 0.875rem;
    font-size: 0.75rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: #85888e;
    font-weight: 500;
}
.footer ul { list-style: none; margin: 0; padding: 0; }
.footer li + li { margin-top: 0.5rem; }
.footer a { font-size: 0.9375rem; text-decoration: none; color: #d7d8da; }
.footer a:hover { color: #fff; }
.to-top {
    display: inline-flex; align-items: center; justify-content: center;
    width: 2.25rem; height: 2.25rem;
    border-radius: var(--radius);
    background: #212327;
    color: #d7d8da;
    text-decoration: none;
}
.colophon {
    max-width: var(--shell);
    margin: 0 auto;
    padding: 2rem 1.5rem 3rem;
    font-size: 0.8125rem;
    color: #85888e;
}

@media (max-width: 720px) {
    .nav-links { display: none; }
    .footer-inner { grid-template-columns: 1fr 1fr; }
}


/* ══ Listings ══ */

/* The listing: homepage, category, tag, author, search results. */

/* Centred, like the post header. The two measures below still hold the line
   lengths down — they just need auto margins to sit in the middle, since a
   max-width block stays left on its own. */
.hero {
    max-width: var(--wide);
    margin: 0 auto;
    padding: 5rem var(--pad) 3rem;
    text-align: center;
}
.hero h1 {
    font-family: var(--sans);
    font-weight: 600;
    font-size: clamp(2.25rem, 5.2vw, 3.25rem);
    line-height: 1.1;
    letter-spacing: -0.042em;
    margin: 0 auto;
    max-width: 18ch;
}
.hero p {
    margin: 1.125rem auto 0;
    max-width: 46ch;
    font-size: 1.0625rem;
    line-height: 1.55;
    color: var(--ink-soft);
}
.hero .button { margin-top: 1.75rem; }

/* An eyebrow above the title, for the pages that are about something:
   a category, a tag, an author, a search term. */
.hero .eyebrow {
display: block;
margin-bottom: 0.875rem;
font-size: 0.75rem;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--ink-faint);
}

/* ── The lead ───────────────────────────────────────────────────
   The newest post, wide, picture beside the copy. Two even columns:
   the image is the anchor, so it gets the same weight as the words
   rather than being a thumbnail with a paragraph next to it. */
.lead {
    max-width: var(--wide);
    margin: 0 auto;
    padding: 0 var(--pad) 3.5rem;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: center;
    column-gap: 3.5rem;
    text-decoration: none;
}
.lead-image, .lead-image-empty {
    display: block;
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    border-radius: var(--radius-large);
    background: var(--paper-soft);
}
.lead-image-empty { border: 1px solid var(--line); background: none; }

.lead-body { min-width: 0; }
.lead h2 {
    margin: 1rem 0 0;
    font-weight: 600;
    font-size: clamp(1.5rem, 2.4vw, 2rem);
    line-height: 1.2;
    letter-spacing: -0.034em;
}
.lead:hover h2 { color: var(--ink-soft); }
.lead-excerpt {
    margin: 0.875rem 0 0;
    max-width: 42ch;
    font-size: 1rem;
    line-height: 1.55;
    color: var(--ink-soft);

    /* Three on the lead: it is twice the width, so two would leave the column
       looking short next to the picture. */
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    overflow: hidden;
}

/* Reads as a button, but the whole card is the link — so this is a span,
   not a nested anchor. */
.lead-cta {
    display: inline-flex;
    align-items: center;
    gap: 0.75rem;
    margin-top: 2rem;
    padding: 0.375rem 0.375rem 0.375rem 1.125rem;
    border-radius: 999px;
    background: var(--paper-soft);
    font-size: 0.9375rem;
    font-weight: 500;
}
.lead-cta-arrow {
    display: inline-flex; align-items: center; justify-content: center;
    width: 2rem; height: 2rem;
    border-radius: 999px;
    background: var(--ink);
    color: var(--paper);
}
.lead-cta-arrow svg { width: 1rem; height: 1rem; }
.lead:hover .lead-cta { background: rgba(38, 34, 40, 0.08); }

/* A rule under the lead, so it reads as its own band above the grid. */
.lead + .posts { border-top: 1px solid var(--line); padding-top: 3.5rem; }

/* ── The grid ───────────────────────────────────────────────────
   Three across under the lead. */
.posts {
    max-width: var(--wide);
    margin: 0 auto;
    /* The gap before the footer. Without it the last row of cards sits
       almost against the footer's top rule. */
    padding: 0 var(--pad) 6rem;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    column-gap: 2rem;
    row-gap: 3.5rem;
}

.card a { text-decoration: none; display: block; }

.card-image {
    display: block;
    width: 100%;
    aspect-ratio: 16 / 10;
    object-fit: cover;
    border-radius: var(--radius-large);
    background: var(--paper-soft);
}

/* A post with no image keeps its place in the grid rather than sliding
   up and breaking the rows. The rule is a hairline, not a grey slab —
   an empty box draws more attention than the absence deserves. */
.card-image-empty {
    display: block;
    aspect-ratio: 16 / 10;
    border: 1px solid var(--line);
    border-radius: var(--radius-large);
    background: none;
}

/* Two lines each, reserved whether or not the text fills them. Clamping alone
   would still leave the row ragged — a one-line title pulls its excerpt up and
   nothing lines up across the row — so the height is held as well as capped.
   The full title is always on the post itself. */
.card h2 {
    font-weight: 600;
    font-size: 1.1875rem;
    line-height: 1.3;
    letter-spacing: -0.03em;
    margin: 0.5rem 0 0;

    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
    min-height: calc(2 * 1.3em);
}
.card a:hover h2 { color: var(--ink-soft); }

.card-excerpt {
    margin: 0.5rem 0 0;
    font-size: 0.9375rem;
    line-height: 1.55;
    color: var(--ink-soft);

    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
    min-height: calc(2 * 1.55em);
}

/* The meta line, above the title on every card. Category, then when it ran
   and how long it takes — one quiet row rather than a date adrift at the
   bottom of the card. */
.card-meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    /* Tight, because the separator carries the join. At a wider gap the dot
       stops reading as punctuation between two facts and the date looks like
       it is floating on its own. */
    gap: 0.3125rem;
    margin-top: 0.875rem;
    font-size: 0.8125rem;
    letter-spacing: -0.005em;
    color: var(--ink-faint);
}
/* Muted, but not so faint it disappears and leaves an unexplained hole —
   which is what it was doing at the hairline colour. */
.card-meta .dot { color: var(--ink-faint); opacity: 0.65; }
/* The chip sits alone on the right, opposite the date and read time —
   margin-left: auto is what opens the gap between the two groups. */
.card-meta .chip { margin-left: auto; }
.lead .card-meta { margin-top: 0; }

/* ── Pagination ─────────────────────────────────────────────── */
.pager {
    max-width: var(--wide);
    margin: 0 auto;
    padding: 0 var(--pad) 6rem;
display: flex;
align-items: center;
justify-content: center;
gap: 1.25rem;
}
.pager-count {
font-size: 0.875rem;
color: var(--ink-faint);
}
.pager a {
font-size: 0.9375rem;
text-decoration: none;
color: var(--ink-soft);
}
.pager a:hover { color: var(--ink); }

/* ── Empty ──────────────────────────────────────────────────── */
.empty {
    max-width: var(--wide);
    margin: 0 auto;
    padding: 1rem var(--pad) 6rem;
color: var(--ink-soft);
}

/* Three across needs the room; below that the grid steps down before the
   lead does, because the lead only has two columns to lose. */
@media (max-width: 1023px) {
    .posts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 767px) {
    :root { --pad: 1.25rem; }
    .posts {
        grid-template-columns: minmax(0, 1fr);
        row-gap: 2.75rem;
        padding-bottom: 4rem;
    }
    /* The lead stacks: picture over copy, same as a card but larger. */
    .lead {
        grid-template-columns: minmax(0, 1fr);
        row-gap: 1.25rem;
        padding-bottom: 2.5rem;
    }
    .lead-image, .lead-image-empty { aspect-ratio: 16 / 10; }
    .lead h2 { margin-top: 0.625rem; }
    .lead-cta { margin-top: 1.5rem; }
    .lead + .posts { padding-top: 2.5rem; }
    .hero { padding: 3.5rem var(--pad) 2.5rem; }
    .pager { padding-bottom: 4rem; }
}


/* ══ The post page ══ */

/* Modelled on the Aave blog post page. Their measurements: a 986px inner with
   a 258px contents column, a 48px gutter and a 680px reading column; a details
   row under the title carrying the date, the share links and the category
   chip; and the cover inside the reading column rather than spanning the
   shell, so the picture lines up with the copy beneath it.

   Ours runs to 1072px to match the Pocket header, which leaves 1008px inside
   the gutters. Their 680px reading column and 48px gutter are kept exactly;
   the contents column takes the extra 22px.

   Aave opens the header at 152px because their navigation floats over it.
   Ours is sticky and about 6.5rem tall, so 5.5rem here lands in the same
   place. Their greys are warm — rgba(39,34,40,…) — and are used throughout;
   the one colour kept from before is the Pocket blue on the contents list. */
.article {
    --post-shell: 67rem;
    --post-pad: 2rem;
    --post-read: 42.5rem;
    --post-toc: 17.5rem;
    --post-gap: 3rem;
    /* Clears the sticky header for anchored headings and pinned columns. */
    --post-stick: 7.5rem;

    --post-accent: rgb(1, 113, 228);
    --post-ink: #272228;
    --post-body: rgba(39, 34, 40, 0.9);
    --post-mute: rgba(39, 34, 40, 0.65);
    --post-faint: rgba(39, 34, 40, 0.5);
    --post-line: rgba(38, 34, 40, 0.1);
    --post-line-soft: rgba(38, 34, 40, 0.05);

    font-family: var(--sans);
    color: var(--post-body);
    font-size: 1rem;
    line-height: 1.5;
}
.post-shell {
    width: 100%;
    max-width: var(--post-shell);
    margin: 0 auto;
    padding: 0 var(--post-pad);
}

/* ── Header ─────────────────────────────────────────────────── */
.post-header { padding: 5.5rem 0 0; }

.post-back {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
    color: var(--post-faint);
    font-size: 1rem;
    font-weight: 400;
    line-height: 1.45;
    letter-spacing: -0.01rem;
    text-decoration: none;
    transition: color 0.2s ease-in-out;
}
.post-back:hover { color: #000; }
.post-back svg { width: 1.125rem; height: 1.125rem; }

.post-title {
    margin: 0;
    color: var(--post-ink);
    font-size: 2.5rem;
    font-weight: 500;
    line-height: 1.3;
    letter-spacing: -0.12rem;
}

/* Date and sharing at one end, the chip at the other. The rule above it is
   what separates the title from the furniture without a heavy divider. */
.post-details {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    column-gap: 7.5rem;
    row-gap: 0.5rem;
    margin-top: 0.625rem;
    /* Ruled above and below: the row reads as a band of furniture between the
       title and the article, rather than a line with text hanging off it.
       A shallow band — the rules sit close on the text. */
    padding: 0.5rem 0;
    border-top: 1px solid var(--post-line);
    border-bottom: 1px solid var(--post-line);
}
.post-details__meta {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    color: var(--post-mute);
    font-size: 0.9375rem;
    letter-spacing: -0.01rem;
}
.post-details__sep {
    width: 1px;
    height: 1rem;
    background: var(--post-line);
}
.post-share { display: inline-flex; gap: 0.125rem; }

.post-chip {
    display: inline-flex;
    align-items: center;
    padding: 0.5rem 0.75rem;
    border-radius: 50px;
    background: var(--post-line-soft);
    color: var(--post-mute);
    font-size: 0.875rem;
    font-weight: 400;
    line-height: 1.05;
    letter-spacing: -0.18px;
    text-decoration: none;
    white-space: nowrap;
}
.post-chip:hover { background: var(--post-line); color: var(--post-ink); }

.icon-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 2rem; height: 2rem;
    border-radius: 999px;
    color: var(--post-mute);
    text-decoration: none;
}
.icon-btn:hover { color: var(--post-ink); background: var(--post-line-soft); }
.icon-btn svg { width: 1.0625rem; height: 1.0625rem; }

/* ── Body grid ──────────────────────────────────────────────── */
.post-grid {
    display: grid;
    grid-template-columns: var(--post-toc) minmax(0, var(--post-read));
    column-gap: var(--post-gap);
    align-items: start;
    padding: 3.5rem 0 6rem;
}
.post-toc { grid-column: 1; grid-row: 1; }
.post-main { grid-column: 2; grid-row: 1; min-width: 0; }

/* A post with no contents list has nothing to put in the first column, so the
   reading column centres in the shell instead of sitting against an empty
   gutter. The view sets this class — :has() would express the same thing, but
   Superblog's deploy pipeline drops any rule that uses it. */
.post-grid.is-solo {
    grid-template-columns: minmax(0, var(--post-read));
    justify-content: center;
}
.post-grid.is-solo .post-main { grid-column: 1; }

/* ── Cover ──────────────────────────────────────────────────── */
/* Inside the reading column, at Aave's 1200:628 box. A padded ratio rather
   than a bare image, so the space is reserved before it loads. */
.post-cover {
    position: relative;
    width: 100%;
    aspect-ratio: 1200 / 628;
    margin-bottom: 2.5rem;
    border-radius: 1.25rem;
    overflow: hidden;
}
/* The hairline as a ring on top of the image rather than an outline on it: an
   outline is drawn outside the box that clips the image, so on a rounded
   cover it would cut the corners square again. */
.post-cover::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    box-shadow: inset 0 0 0 1px var(--post-line);
    pointer-events: none;
}
.post-cover img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    background: #fcfcfc;
}

/* ── Contents ───────────────────────────────────────────────── */
.post-toc {
    position: sticky;
    top: var(--post-stick);
    padding-right: 2rem;
    /* A long post has a long contents list. Without a ceiling it runs past the
       bottom of the screen, and a sticky element does not scroll with the
       page — so the last entries would be unreachable. */
    max-height: 80svh;
    overflow-y: auto;
}
.post-toc ol { list-style: none; margin: 0; padding: 0; }
.post-toc li + li { margin-top: 1rem; }
.post-toc a {
    display: block;
    color: #646161;
    font-size: 1rem;
    font-weight: 400;
    line-height: 1.45;
    letter-spacing: -0.01rem;
    text-decoration: none;
    transition: color 0.1s ease-in-out;
}
.post-toc a:hover { color: var(--post-ink); }
.post-toc .depth-3 { padding-left: 1rem; }

/* The section you are reading. Set from site.js; without JavaScript the index
   is still a working list of links, just not a position indicator. */
.post-toc a.is-current {
    color: var(--post-accent);
    font-weight: 500;
}

/* ── Body copy ──────────────────────────────────────────────── */
.prose { min-width: 0; }
.prose > :first-child { margin-top: 0; }
.prose p {
    margin: 0 0 1rem;
    font-size: 1rem;
    line-height: 1.5;
    letter-spacing: -0.01rem;
}
.prose h2 {
    margin: 2.5rem 0 0.875rem;
    color: var(--post-ink);
    font-weight: 450;
    font-size: 1.5rem;
    line-height: 1.35;
    letter-spacing: -0.03rem;
}
.prose h3 {
    margin: 2rem 0 0.75rem;
    color: var(--post-ink);
    font-weight: 500;
    font-size: 1.25rem;
    line-height: 1.4;
    letter-spacing: -0.02rem;
}
.prose h4 {
    margin: 1.75rem 0 0.75rem;
    color: var(--post-ink);
    font-weight: 500;
    font-size: 1.0625rem;
    line-height: 1.45;
}
/* The contents links land here, so every heading has to clear the sticky
   header before it comes to rest. */
.prose :is(h2, h3, h4, h5, h6) { scroll-margin-top: var(--post-stick); }

.prose :is(ul, ol) { margin: 0 0 1.5rem; padding-left: 1.25rem; }
.prose li { margin: 0.375rem 0; }
/* Pull quotes, the Medium way: no box. A large serif quotation mark in the
   post accent hangs in the left gutter, the quote itself is italic and a
   step larger than body text, and an attribution in its own trailing
   paragraph drops back to small upright type. Older quotes that keep the
   attribution on a <br> line inside one paragraph still read fine — they
   just stay italic throughout. */
.prose blockquote {
    position: relative;
    margin: 2.75rem 0;
    padding: 0.125rem 0 0.125rem 3rem;
    color: var(--post-ink);
}
.prose blockquote::before {
    content: "\201C";
    position: absolute;
    left: 0;
    top: -0.375rem;
    font-family: var(--serif);
    font-size: 3.5rem;
    line-height: 1;
    color: var(--post-accent);
}
.prose blockquote p {
    font-size: 1.1875rem;
    line-height: 1.6;
    font-style: italic;
    letter-spacing: -0.015rem;
    margin: 0 0 0.625rem;
}
.prose blockquote p:last-child { margin-bottom: 0; }
.prose blockquote p + p {
    font-size: 0.875rem;
    font-style: normal;
    letter-spacing: -0.006em;
    color: var(--post-mute);
}

/* Images arrive from the editor as bare <img> with no width, so without a cap
   they lay out at their intrinsic size and hang off the side of the reading
   column. Embeds and code blocks do the same. */
.prose :is(img, video, iframe, table, pre) { max-width: 100%; }
/* No hairline ring on body images. Many of the assets are PNGs with rounded
   corners baked into their own alpha channel, and a ring drawn on the CSS box
   floats across those transparent corners with a sliver of page between it
   and the picture — a false double border. The radius clip alone is clean:
   at 10px it swallows the baked ~8px corner cut. The cover keeps its ring,
   because object-fit: cover always fills that box edge to edge. */
.prose img {
    height: auto;
    border-radius: 0.625rem;
}
.prose pre { overflow-x: auto; }
.prose strong { color: var(--post-ink); font-weight: 500; }

/* Underlines that sit off the text and only darken on hover, rather than a
   coloured link. */
.prose a {
    color: inherit;
    text-decoration: underline;
    text-decoration-color: var(--post-line);
    text-underline-offset: 0.25em;
    transition: text-decoration-color 0.1s linear;
}
.prose a:hover { text-decoration-color: var(--post-mute); }

figure { margin: 2rem 0; }
.prose > figure:first-child { margin-top: 0; }
figure img { width: 100%; display: block; }
figcaption {
    margin-top: 0.75rem;
    color: var(--post-faint);
    font-size: 0.875rem;
    line-height: 1.5;
}

.tags {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 2.5rem 0 0;
    padding-top: 2rem;
    border-top: 1px solid var(--post-line);
}
.tags a {
    padding: 0.5rem 0.75rem;
    border-radius: 50px;
    background: var(--post-line-soft);
    color: var(--post-mute);
    font-size: 0.875rem;
    line-height: 1.05;
    letter-spacing: -0.18px;
    text-decoration: none;
}
.tags a:hover { background: var(--post-line); color: var(--post-ink); }

/* Aave drops the contents column below their desktop breakpoint and the post
   runs as one column. */
@media (max-width: 1023px) {
    .post-grid {
        grid-template-columns: minmax(0, 1fr);
        justify-content: stretch;
        padding-top: 3rem;
    }
    .post-toc { display: none; }
    .post-main { grid-column: 1; }
}

@media (max-width: 767px) {
    .article { --post-pad: 1.25rem; }
    .post-header { padding-top: 3rem; }
    .post-title { font-size: 2rem; line-height: 1.2; letter-spacing: -0.095rem; }
    .post-details { column-gap: 1.5rem; }
    .post-cover { border-radius: 0.875rem; margin-bottom: 2rem; }
    .post-grid { padding: 2rem 0 4rem; }
}


/* ── Lead form ──────────────────────────────────────────────── */
.leadform {
    max-width: calc(42.5rem + 4rem);
    margin: 0 auto 6rem;
    padding: 2.5rem 2rem;
    border-top: 1px solid #e5e5e5;
    text-align: center;
}
.leadform h2 {
    font-weight: 600;
    font-size: 1.5rem;
    margin: 0;
    color: #171717;
    letter-spacing: -0.01em;
}
.leadform p { margin: 0.5rem 0 0; color: var(--ink-soft); font-size: 0.9375rem; }
.leadform form {
    display: flex;
    gap: 0.5rem;
    margin: 1.5rem auto 0;
    max-width: 26rem;
}
.leadform input {
    flex: 1;
    min-width: 0;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    font: inherit;
    font-size: 0.9375rem;
    background: var(--paper);
    color: var(--ink);
}
.leadform input:focus { outline: 2px solid var(--ink); outline-offset: -1px; }

@media (max-width: 720px) {
.leadform form { flex-direction: column; }
}


/* ══ Navigation extras ══ */

/* The category pill on a listing card. The post page has its own, .badge. */
/* The category pill on a listing card, matching the post page's .post-chip. */
.chip {
    display: inline-flex;
    align-items: center;
    padding: 0.3125rem 0.625rem;
    border-radius: 50px;
    background: rgba(38, 34, 40, 0.05);
    color: rgba(39, 34, 40, 0.65);
    font-size: 0.8125rem;
    line-height: 1.05;
    letter-spacing: -0.18px;
    text-decoration: none;
}
.chip:hover { background: rgba(38, 34, 40, 0.1); color: #272228; }

.brand-logo { height: 1.75rem; width: auto; display: block; }

.nav-dropdown { position: relative; }
.nav-dropdown summary {
  cursor: pointer;
  font-size: 0.9375rem;
  color: var(--ink-soft);
  list-style: none;
}
.nav-dropdown summary::-webkit-details-marker { display: none; }
.nav-dropdown summary::after { content: " ⌄"; }
.nav-dropdown summary:hover { color: var(--ink); }
.nav-dropdown-menu {
  position: absolute;
  top: 1.9rem;
  left: -0.75rem;
  z-index: 30;
  min-width: 11rem;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 0.5rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper);
  box-shadow: 0 8px 24px rgb(0 0 0 / 8%);
}
.nav-dropdown-menu a { font-size: 0.9375rem; padding: 0.25rem 0.5rem; }


/* ══ Categories, tags ══ */

/* A quiet list rather than cards: these pages are a way through to somewhere
   else, and a grid of boxes would give them more weight than they carry. */
.tiles {
  max-width: var(--wide);
  margin: 0 auto;
  padding: 0 1.5rem;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: 0.25rem 2.5rem;
}
.tile {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.625rem 0;
  border-bottom: 1px solid var(--line);
  text-decoration: none;
}
.tile:hover .tile-name { color: var(--ink-soft); }
.tile-name { font-family: var(--sans); font-size: 1.0625rem; }
.tile-count { margin-left: auto; font-size: 0.8125rem; color: var(--ink-faint); }


/* ══ Search ══ */

.search-page { max-width: var(--wide); margin: 0 auto; padding: 0 1.5rem; }

.search { max-width: 32rem; }
.search input {
  width: 100%;
  padding: 0.625rem 0.875rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  font-size: 1rem;
}
.search input:focus { outline: 2px solid var(--ink); outline-offset: -1px; }

.search-results { list-style: none; margin: 2rem 0 0; padding: 0; max-width: 40rem; }
.search-results li { padding: 0.875rem 0; border-bottom: 1px solid var(--line); }
.search-results a { font-family: var(--sans); font-size: 1.0625rem; text-decoration: none; }
.search-results a:hover { color: var(--ink-soft); }
.search-results p { margin: 0.25rem 0 0; font-size: 0.875rem; color: var(--ink-faint); }

.search-empty { margin: 2rem 0 0; color: var(--ink-soft); }

.search-page .eyebrow {
  display: block;
  margin: 3.5rem 0 1rem;
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* The lead form's result line, written by assets/site.js. */
.leadform .message { margin: 0.75rem 0 0; font-size: 0.875rem; color: var(--ink-soft); }

/* Read by screen readers, invisible to everyone else. */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* The offer banner dropped into post bodies as raw HTML. Superblog's
   sanitizer strips class and style attributes from post content, so nothing
   in the markup can be targeted by name. The selectors instead recognize the
   banner by its shape — a div holding a media div (img) next to a body div
   whose paragraphs carry the heypocket.com CTA link — because href, src and
   alt do survive sanitization. The markup keeps its pkt-offer-* classes for
   readability, but they never reach the page. */
/* Flat selectors only: the upload pipeline's minifier drops nested rules. */
.prose div:has(> div > img):has(> div > p > a[href^="https://heypocket.com/"]) {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    overflow: hidden;
    margin: 2.5rem 0;
    border-radius: 1rem;
    background: var(--ink);
}
/* Media half. */
.prose div:has(> div > p > a[href^="https://heypocket.com/"]) > div:has(> img) {
    flex: 1 1 260px;
    min-width: 240px;
}
.prose div:has(> div > p > a[href^="https://heypocket.com/"]) > div > img {
    display: block;
    width: 100%;
    height: 100%;
    min-height: 220px;
    object-fit: cover;
    margin: 0;
    border-radius: 0;
}
/* Copy half: eyebrow, title, note, CTA, stock chip — in that order. */
.prose div:has(> div > img) > div:has(> p > a[href^="https://heypocket.com/"]) {
    flex: 1 1 320px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 0.75rem;
    box-sizing: border-box;
    padding: 2.25rem 2rem;
}
.prose div:has(> div > img) > div:has(> p > a[href^="https://heypocket.com/"]) > p {
    margin: 0;
}
.prose div:has(> div > img) > div:has(> p > a[href^="https://heypocket.com/"]) > p:nth-of-type(1) {
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.6);
}
.prose div:has(> div > img) > div:has(> p > a[href^="https://heypocket.com/"]) > p:nth-of-type(2) {
    font-size: 1.65rem;
    line-height: 1.25;
    font-weight: 700;
    color: #fff;
}
.prose div:has(> div > img) > div:has(> p > a[href^="https://heypocket.com/"]) > p:nth-of-type(2) span {
    color: #6db1ff;
}
.prose div:has(> div > img) > div:has(> p > a[href^="https://heypocket.com/"]) > p:nth-of-type(3) {
    font-size: 0.95rem;
    color: rgba(255, 255, 255, 0.75);
}
.prose div:has(> div > img) > div > p > a[href^="https://heypocket.com/"] {
    display: inline-block;
    margin-top: 0.5rem;
    padding: 0.85rem 1.75rem;
    border-radius: 999px;
    background: var(--post-accent);
    color: #fff;
    font-weight: 600;
    text-decoration: none;
    transition: filter 0.1s linear;
}
.prose div:has(> div > img) > div > p > a[href^="https://heypocket.com/"]:hover {
    filter: brightness(1.15);
}
.prose div:has(> div > img) > div:has(> p > a[href^="https://heypocket.com/"]) > p:last-of-type {
    font-size: 0.8rem;
    color: rgba(255, 255, 255, 0.55);
}
.prose div:has(> div > img) > div:has(> p > a[href^="https://heypocket.com/"]) > p:last-of-type strong {
    color: #fff;
    font-weight: 600;
}