/* ==========================================================================
   Tokens
   ========================================================================== */

:root {
    /* dark is the only palette — no light mode toggle */
    --bg: #14132b;
    --bg-rgb: 20, 19, 43;
    --bg-elevated: #1c1a3d;
    --bg-inset: #211f47;
    --text: #f4f1ea;
    --text-muted: #a9a4c9;
    --border: #322f5c;
    --accent: #ff5d4a;
    --accent-text: #14132b;

    --content-width: 720px;

    --font-display: var(--gh-font-heading, 'Anton'), Impact, 'Arial Narrow', sans-serif;
    --font-pixel: 'Silkscreen', ui-monospace, SFMono-Regular, Menlo, monospace;
    /* display-scale pixel font — Silkscreen's tiny grid breaks down on W/M
       at title sizes, Press Start 2P's 8x8 grid holds up */
    --font-pixel-display: 'Press Start 2P', 'Silkscreen', ui-monospace, monospace;
    --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace;
    --font-sans: var(--gh-font-body, 'Space Mono'), ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

html {
    background: var(--bg);
}

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font-family: var(--font-sans);
    line-height: 1.65;
    transition: background-color 0.15s ease, color 0.15s ease;
}

a {
    color: inherit;
}

.container {
    max-width: var(--content-width);
    margin: 0 auto;
    padding: 0 24px;
}

/* .site-main and .container are classes on the SAME <main> element
   (see default.hbs) — no descendant combinator here, or this never matches.
   Longhand left/right only, so this doesn't clobber .site-main's
   top/bottom padding below (a shorthand `padding` here did exactly that).

   Header and footer get the same left/right numbers UNCONDITIONALLY (no
   template gating) so the site title and the post feed always share one
   left edge, on every page — not just home/tag/author. */
.home-template .site-main,
.tag-template .site-main,
.author-template .site-main,
.site-header .container,
.site-footer .container {
    max-width: 2200px;
    padding-left: clamp(20px, 3vw, 48px);
    padding-right: clamp(20px, 3vw, 48px);
}

::selection {
    background: var(--accent);
    color: var(--accent-text);
}

/* ==========================================================================
   Type
   ========================================================================== */

h1, h2, h3, h4, h5, h6 {
    font-family: var(--font-display);
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: 0;
    line-height: 1.05;
}

.pixel {
    font-family: var(--font-pixel);
}

.eyebrow {
    font-family: var(--font-pixel);
    font-size: 0.7rem;
    font-weight: 400;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--accent);
}

/* ==========================================================================
   Header
   ========================================================================== */

.site-header {
    border-bottom: 2px solid var(--border);
    background: var(--bg);
    position: sticky;
    top: 0;
    z-index: 10;
}

.site-header .container {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-top: 20px;
    padding-bottom: 20px;
    gap: 24px;
}

.site-branding {
    display: flex;
    align-items: center;
    gap: 10px;
    text-decoration: none;
    /* set here, not on .site-title, so the heart's 1em (below) sizes
       off the same value instead of the link's inherited default.
       Floor is low enough that the title stays on one line on phones. */
    font-size: clamp(1rem, 0.5rem + 2.2vw, 2.2rem);
}

.site-title {
    font-family: var(--font-pixel);
    font-weight: 700;
    /* without this it inherits body's line-height: 1.65, which pads a much
       taller box above/below the glyphs than the text itself — the flex row's
       align-items: center then centers the heart against that oversized box
       instead of the visible caps, which is why it read as sitting low */
    line-height: 1;
    /* Silkscreen's caps render smaller than the heart at the same font-size
       (its glyphs fill less of the em box) — sized in em off .site-branding's
       font-size so it grows independently of the heart but still scales with
       it responsively, rather than pinning both to a fixed px relationship */
    font-size: 1.25em;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--text);
}

.site-branding-heart {
    /* Silkscreen's glyphs only fill part of the em box (typical of pixel
       fonts built for tiny sizes), so 1em renders much taller than the
       capital letters beside it — 0.8em approximates cap-height instead */
    height: 0.8em;
    width: auto;
    aspect-ratio: 8 / 7;
    color: var(--accent);
    flex-shrink: 0;
    /* optical overshoot: the heart's top row is just two thin "ear" points
       (see the viewBox rects in default.hbs), so centering the full bounding
       box reads as low — the eye anchors on row 2, where the wide body
       starts. Nudge down by one pixel-row (of 7) so the ears overshoot
       above cap-height instead, which is what actually looks aligned. */
    position: relative;
    top: calc(0.8em / 7);
    animation: heartbeat 2.4s ease-in-out infinite;
    transform-origin: center;
}

/* two quick thumps, then rest — reads as a pulse, not a throb */
@keyframes heartbeat {
    0%   { transform: scale(1); }
    10%  { transform: scale(1.12); }
    18%  { transform: scale(1); }
    28%  { transform: scale(1.12); }
    36%  { transform: scale(1); }
    100% { transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
    .site-branding-heart {
        animation: none;
    }
}

.site-header-right {
    display: flex;
    align-items: center;
    gap: 28px;
    flex-shrink: 0;
}

.site-nav .nav {
    display: flex;
    align-items: center;
    gap: 22px;
    list-style: none;
    margin: 0;
    padding: 0;
}

.site-nav a {
    font-family: var(--font-pixel);
    font-size: 1.05rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    text-decoration: none;
    color: var(--text-muted);
    border-bottom: 2px solid transparent;
    padding-bottom: 2px;
}

/* :not([href^="#"]) — Ghost flags hash links (e.g. Portal's "#/portal/")
   as nav-current on every page, since the hash resolves to the current
   URL; without this they'd sit permanently underlined */
.site-nav a:hover,
.site-nav .nav-current a:not([href^="#"]) {
    color: var(--text);
    border-bottom-color: var(--accent);
}

/* an unset secondary menu still renders an empty <ul> — drop it so the
   header flex gap doesn't leave a phantom space */
.site-nav:has(.nav:empty) {
    display: none;
}

/* Header links and the burger are mutually exclusive — exactly one shows
   at any width. Breakpoint lives in both this block and the drawer's
   primary-group rule below; keep the two numbers in sync. */
@media (max-width: 899px) {
    .site-nav {
        display: none;
    }
}

.menu-toggle {
    width: 34px;
    height: 34px;
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 5px;
    background: var(--bg);
    border: 2px solid var(--border);
    cursor: pointer;
    flex-shrink: 0;
    padding: 0;
}

/* must come AFTER .menu-toggle's display: inline-flex above — same
   specificity, so source order decides the winner */
@media (min-width: 900px) {
    .menu-toggle {
        display: none;
    }
}

.menu-toggle:hover {
    border-color: var(--accent);
}

.menu-toggle-bar {
    display: block;
    width: 16px;
    height: 2px;
    background: var(--text);
}

.menu-toggle:hover .menu-toggle-bar {
    background: var(--accent);
}

/* ==========================================================================
   Nav drawer
   ========================================================================== */

.site-drawer {
    position: fixed;
    inset: 0;
    z-index: 100;
    visibility: hidden;
}

.site-drawer.is-open {
    visibility: visible;
}

.site-drawer-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    opacity: 0;
    transition: opacity 0.25s ease;
}

.site-drawer.is-open .site-drawer-backdrop {
    opacity: 1;
}

.site-drawer-panel {
    position: absolute;
    top: 0;
    right: 0;
    height: 100%;
    width: min(400px, 86vw);
    background: var(--bg-elevated);
    border-left: 2px solid var(--border);
    display: flex;
    flex-direction: column;
    padding: 24px;
    transform: translateX(100%);
    transition: transform 0.3s ease;
}

.site-drawer.is-open .site-drawer-panel {
    transform: translateX(0);
}

.site-drawer-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-bottom: 20px;
    border-bottom: 1px solid var(--border);
}

.site-drawer-label {
    font-family: var(--font-pixel);
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
}

.drawer-close {
    width: 34px;
    height: 34px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--bg);
    border: 2px solid var(--border);
    color: var(--text);
    cursor: pointer;
    padding: 0;
}

.drawer-close:hover {
    border-color: var(--accent);
    color: var(--accent);
}

.site-drawer-nav .nav {
    list-style: none;
    margin: 32px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 24px;
}

/* no breakpoint rule needed here: the burger only exists below 900px, so
   the drawer is only ever reachable there and always shows both menus */

.site-drawer-nav .nav a {
    display: flex;
    align-items: center;
    gap: 10px;
    font-family: var(--font-pixel);
    font-size: 1.3rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    text-decoration: none;
    color: var(--accent);
}

.site-drawer-nav .nav a::before {
    content: "";
    width: 10px;
    height: 10px;
    background: var(--accent);
    flex-shrink: 0;
}

.site-drawer-nav .nav a:hover {
    color: var(--text);
}

.site-drawer-nav .nav a:hover::before {
    background: var(--text);
}

body.drawer-open {
    overflow: hidden;
}

@media (prefers-reduced-motion: reduce) {
    .site-drawer-panel,
    .site-drawer-backdrop {
        transition: none;
    }
}

/* ==========================================================================
   Main / layout
   ========================================================================== */

.site-main {
    /* longhand on purpose: shorthand `padding: 56px 0 80px` was zeroing the
       horizontal padding that .container provides on the same element
       (this rule comes later in the file, so its 0 was winning) */
    padding-top: 56px;
    padding-bottom: 80px;
}

/* ==========================================================================
   Post feed / cards
   ========================================================================== */

.post-feed {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 28px;
}

@media (min-width: 860px) {
    .post-feed {
        grid-template-columns: repeat(2, 1fr);
    }

    /* keep a lone trailing card from stretching into every column */
    .post-feed > li:last-child:nth-child(2n+1) {
        grid-column: 1 / -1;
    }
}

.post-card {
    border: 1px solid var(--border);
    /* lets title/padding below scale off the card's own rendered width
       (cqi) instead of the viewport (vw) — so the card looks right at
       any column count or container width, not just the ones we tested */
    container-type: inline-size;
    transition: border-color 0.2s ease;
}

.post-card:hover {
    border-color: var(--accent);
}

.post-card-frame {
    position: relative;
    display: flex;
    flex-direction: column;
    /* only .post-card-bottom lives here now (the top eyebrow was removed) —
       flex-end keeps it pinned to the bottom instead of space-between
       collapsing it to the top with a single child */
    justify-content: flex-end;
    aspect-ratio: 4 / 3;
    min-height: 260px;
    text-decoration: none;
    color: var(--text);
    overflow: hidden;
}

.post-card-media {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center;
    background-color: var(--bg-inset);
    filter: saturate(0.65) brightness(0.45);
    transform: scale(1);
    transition: filter 0.25s ease, transform 0.4s ease;
}

.post-card-media--empty {
    background-image:
        linear-gradient(var(--border) 1px, transparent 1px),
        linear-gradient(90deg, var(--border) 1px, transparent 1px);
    background-size: 22px 22px;
    filter: opacity(0.5);
}

.post-card-frame::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(var(--bg-rgb), 0.15) 0%, rgba(var(--bg-rgb), 0.55) 45%, rgba(var(--bg-rgb), 0.96) 100%);
}

.post-card:hover .post-card-media {
    filter: saturate(0.8) brightness(0.55);
    transform: scale(1.03);
}

.post-card-bottom {
    position: relative;
    z-index: 1;
    padding: clamp(18px, 4cqi, 40px);
}

.post-card-title {
    margin: 0 0 12px;
    /* Press Start 2P runs very wide and only ships weight 400 —
       sizes scaled down or long titles wrap into a wall of text */
    font-family: var(--font-pixel-display);
    font-size: clamp(1rem, 4.2cqi, 2rem);
    font-weight: 400;
    line-height: 1.35;
    color: var(--accent);
}

.post-card-meta-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
    padding-top: 14px;
    border-top: 1px solid var(--border);
}

.post-card-date {
    font-family: var(--font-pixel);
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--accent);
}

.post-card-tags {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.tag-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-family: var(--font-pixel);
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    text-decoration: none;
    color: var(--text-muted);
    border: 1px solid var(--border);
    padding: 5px 9px;
    background: rgba(var(--bg-rgb), 0.6);
}

.tag-pill:hover {
    color: var(--accent-text);
    background: var(--accent);
    border-color: var(--accent);
}

.tag-pill::before {
    content: "";
    width: 6px;
    height: 6px;
    background: var(--accent);
    flex-shrink: 0;
}

/* pagination */

.pagination {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 40px;
    padding-top: 24px;
    border-top: 2px solid var(--border);
    font-family: var(--font-pixel);
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.pagination a {
    text-decoration: none;
    border: 2px solid var(--border);
    padding: 8px 14px;
}

.pagination a:hover {
    border-color: var(--accent);
    color: var(--accent);
}

.pagination .page-number {
    color: var(--text-muted);
}

/* ==========================================================================
   Single post / page
   ========================================================================== */

.post-header {
    margin-bottom: 32px;
}

.post-header .eyebrow {
    display: block;
    margin-bottom: 12px;
}

.post-title {
    font-family: var(--font-pixel-display);
    font-size: clamp(1.2rem, 3vw, 2.2rem);
    font-weight: 400;
    line-height: 1.35;
    margin: 0 0 16px;
    color: var(--accent);
}

.post-meta {
    font-family: var(--font-pixel);
    color: var(--text-muted);
    font-size: 1rem;
    line-height: 1.6;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.post-meta .divider {
    color: var(--border);
    margin: 0 8px;
}

.post-feature-image {
    display: block;
    width: 100%;
    margin: 24px 0;
    border: 2px solid var(--border);
}

.post-content,
.post-content p,
.post-content li {
    /* Space Mono runs wide — a notch smaller than the old Inter size
       keeps line lengths and paragraph density comfortable */
    font-size: 1rem;
}

.post-content h1, .post-content h2, .post-content h3 {
    margin-top: 2em;
    color: var(--accent);
}

.post-content a {
    color: var(--accent);
    text-decoration-thickness: 2px;
    text-underline-offset: 3px;
}

.post-content img {
    max-width: 100%;
    height: auto;
    border: 2px solid var(--border);
}

.post-content blockquote {
    margin: 24px 0;
    padding: 4px 0 4px 20px;
    border-left: 3px solid var(--accent);
    color: var(--text-muted);
    font-style: normal;
}

.post-content code {
    font-family: var(--font-mono);
    background: var(--bg-inset);
    padding: 2px 6px;
    font-size: 0.9em;
}

.post-content pre {
    position: relative;
    background: var(--bg-inset);
    border: 1px solid var(--border);
    padding: 20px;
    overflow-x: auto;
    font-size: 0.85rem;
    line-height: 1.7;
    margin: 28px 0;
}

.post-content pre code {
    background: none;
    padding: 0;
    font-size: inherit;
}

/* pixel language chip in the top-right corner of each block */
.post-content pre[class*="language-"]::before {
    position: absolute;
    top: 0;
    right: 0;
    font-family: var(--font-pixel);
    font-size: 0.65rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--accent);
    border-left: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
    padding: 4px 8px;
    background: var(--bg);
}

.post-content pre.language-javascript::before { content: "js"; }
.post-content pre.language-jsx::before        { content: "jsx"; }
.post-content pre.language-typescript::before { content: "ts"; }
.post-content pre.language-python::before     { content: "py"; }
.post-content pre.language-css::before        { content: "css"; }
.post-content pre.language-html::before,
.post-content pre.language-markup::before     { content: "html"; }
.post-content pre.language-json::before       { content: "json"; }
.post-content pre.language-bash::before       { content: "sh"; }
.post-content pre.language-sql::before        { content: "sql"; }
.post-content pre.language-yaml::before       { content: "yaml"; }

/* ==========================================================================
   Syntax highlighting (Prism) — token colors derived from the site palette:
   coral for keywords, and satellites picked at similar lightness so no
   token shouts louder than the others on the inset navy background
   ========================================================================== */

:root {
    --code-comment: #7a749e;   /* dimmed lavender */
    --code-keyword: #ff7a69;   /* coral, lifted for contrast on inset bg */
    --code-string:  #8ee8a8;   /* mint */
    --code-function:#ffd166;   /* warm yellow */
    --code-number:  #ffa657;   /* orange */
    --code-type:    #7cd6ff;   /* sky */
    --code-punct:   #a9a4c9;   /* text-muted */
}

.token.comment, .token.prolog, .token.doctype, .token.cdata {
    color: var(--code-comment);
}

.token.punctuation, .token.operator, .token.combinator {
    color: var(--code-punct);
}

.token.keyword, .token.rule, .token.important, .token.atrule .token.rule,
.token.tag .token.tag, .token.selector {
    color: var(--code-keyword);
}

.token.string, .token.char, .token.attr-value, .token.template-string,
.token.inserted {
    color: var(--code-string);
}

.token.function, .token.function-name, .token.method {
    color: var(--code-function);
}

.token.number, .token.boolean, .token.constant, .token.symbol,
.token.deleted, .token.unit {
    color: var(--code-number);
}

.token.class-name, .token.builtin, .token.attr-name, .token.property,
.token.variable, .token.regex, .token.tag {
    color: var(--code-type);
}

.token.url {
    color: var(--code-string);
    text-decoration: underline;
}

.token.bold { font-weight: 700; }
.token.italic { font-style: italic; }

.post-content hr {
    border: none;
    border-top: 2px solid var(--border);
    margin: 40px 0;
}

/* Koenig editor card width classes */
.kg-width-wide {
    width: 100%;
    max-width: calc(var(--content-width) + 200px);
    margin-left: 50%;
    transform: translateX(-50%);
}

.kg-width-full {
    width: 100%;
    max-width: 1400px;
    margin-left: 50%;
    transform: translateX(-50%);
}

.post-footer {
    margin-top: 48px;
    padding-top: 20px;
    border-top: 2px solid var(--border);
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

/* page.hbs */
.page .post-content {
    margin-top: 8px;
}

/* ==========================================================================
   Footer
   ========================================================================== */

.site-footer {
    padding: 28px 0;
    border-top: 2px solid var(--border);
    color: var(--text-muted);
    font-family: var(--font-pixel);
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.site-footer-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    flex-wrap: wrap;
}

.social-links {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    gap: 10px;
}

/* same bordered-square + invert-on-hover component as .menu-toggle and
   .drawer-close, so these read as native controls rather than logos
   dropped into the footer */
.social-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    background: var(--bg);
    border: 2px solid var(--border);
    color: var(--text-muted);
}

.social-link:hover {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--accent-text);
}

.social-link svg {
    display: block;
    width: 18px;
    height: 18px;
}


/* ==========================================================================
   CV page (page-cv.hbs)
   ========================================================================== */

.cv-header {
    margin-bottom: 56px;
}

.cv-header .eyebrow {
    display: block;
    margin-bottom: 12px;
}

.cv-title {
    font-family: var(--font-pixel-display);
    font-size: clamp(1.8rem, 5vw, 3.4rem);
    font-weight: 400;
    line-height: 1.2;
    margin: 0 0 16px;
    color: var(--accent);
}

.cv-lede {
    color: var(--text-muted);
    max-width: 46ch;
    margin: 0;
}

/* the log: a left rail built from pixel squares */
.cv-log {
    list-style: none;
    margin: 0;
    padding: 0;
    position: relative;
}

.cv-log::before {
    content: "";
    position: absolute;
    left: 5px;
    top: 6px;
    bottom: 0;
    width: 2px;
    /* dashed pixel rail: 8px on, 6px off */
    background: repeating-linear-gradient(
        180deg,
        var(--border) 0 8px,
        transparent 8px 14px
    );
}

.cv-entry {
    position: relative;
    padding-left: 40px;
    padding-bottom: 48px;
}

/* square node sitting on the rail */
.cv-entry::before {
    content: "";
    position: absolute;
    left: 0;
    top: 6px;
    width: 12px;
    height: 12px;
    background: var(--accent);
}

.cv-entry-when {
    margin-bottom: 10px;
}

.cv-chip {
    display: inline-block;
    font-family: var(--font-pixel);
    font-size: 0.8rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--accent);
    border: 1px solid var(--border);
    padding: 5px 10px;
}

.cv-entry-role {
    font-size: clamp(1.6rem, 4vw, 2.6rem);
    line-height: 1;
    margin: 0 0 6px;
    color: var(--text);
}

.cv-entry-org {
    font-family: var(--font-pixel);
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--text-muted);
    margin: 0 0 12px;
}

.cv-entry-desc {
    max-width: 60ch;
    margin: 0 0 14px;
}

.cv-entry-tags {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.cv-entry-tags li {
    font-family: var(--font-pixel);
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--text-muted);
    border: 1px solid var(--border);
    padding: 4px 8px;
}

/* signature detail: the current role carries a blinking block cursor,
   terminal-style — "this line is still being written" */
.cv-cursor {
    display: inline-block;
    width: 0.5em;
    height: 0.85em;
    margin-left: 0.18em;
    background: var(--accent);
    animation: cv-blink 1.1s steps(1) infinite;
}

@keyframes cv-blink {
    0%, 55% { opacity: 1; }
    56%, 100% { opacity: 0; }
}

.cv-entry.is-current::before {
    /* current node echoes the heartbeat: slightly larger, coral */
    width: 14px;
    height: 14px;
    left: -1px;
}

.cv-footer {
    padding-left: 40px;
}

.cv-chip--end {
    color: var(--text-muted);
}

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

/* sub-entries: courses / committee roles / volunteering that happened
   during a role — indented, with a horizontal dashed connector branching
   in from the left, echoing the vertical rail's pixel-dash language */
.cv-subentries {
    list-style: none;
    margin: 20px 0 0;
    padding: 0;
}

.cv-subentry {
    position: relative;
    /* room for connector + marker + a real gap before the text */
    padding-left: 60px;
    padding-bottom: 26px;
}

.cv-subentry:last-child {
    padding-bottom: 0;
}

/* horizontal dashed connector entering from the left — stops short of
   the marker instead of running into it */
.cv-subentry::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.7em;
    width: 26px;
    height: 2px;
    background: repeating-linear-gradient(
        90deg,
        var(--border) 0 8px,
        transparent 8px 14px
    );
}

/* pixel chevron marker: a right-pointing arrow drawn from 3px blocks
   (one seed pixel + box-shadow copies), like a quest-log pointer

       X . .
       X X .
       X X X
       X X .
       X . .          */
.cv-subentry::after {
    content: "";
    position: absolute;
    left: 34px;
    top: calc(0.7em - 6px);
    width: 3px;
    height: 3px;
    background: var(--accent);
    box-shadow:
        0 3px   0 var(--accent),
        0 6px   0 var(--accent),
        0 9px   0 var(--accent),
        0 12px  0 var(--accent),
        3px 3px 0 var(--accent),
        3px 6px 0 var(--accent),
        3px 9px 0 var(--accent),
        6px 6px 0 var(--accent);
}

.cv-subentry-label {
    display: inline-block;
    font-family: var(--font-pixel);
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--accent);
    margin-bottom: 6px;
}

.cv-subentry-title {
    font-family: var(--font-sans);
    font-size: 1.05rem;
    /* Space Mono only ships 400/700 — 600 would be synthetic */
    font-weight: 700;
    text-transform: none;
    letter-spacing: 0;
    line-height: 1.3;
    margin: 0 0 2px;
    color: var(--text);
}

.cv-subentry-desc {
    font-size: 0.9rem;
    color: var(--text-muted);
    margin: 0;
    max-width: 55ch;
}

/* ==========================================================================
   Homepage intro
   ========================================================================== */

.intro {
    /* flow-root contains the float below */
    display: flow-root;
    max-width: 980px;
    padding: 40px 0 64px;
}

.intro-avatar {
    position: relative;
    float: left;
    /* the signature move: text wraps the circle's CURVE, not its box —
       lines get shorter as they pass the circle's widest point and
       lengthen again below it */
    shape-outside: circle(50%);
    shape-margin: 32px;
    width: clamp(150px, 24vw, 240px);
    margin: 8px 40px 12px 0;
}

.intro-avatar-img {
    display: block;
    width: 100%;
    aspect-ratio: 1;
    border-radius: 50%;
    object-fit: cover;
    border: 3px solid var(--accent);
    /* no offset shadow here: on a circle it reads as a second
       misaligned disc (eclipse effect), not a print-style drop */
}

.intro-avatar-img--empty {
    background:
        repeating-conic-gradient(var(--bg-inset) 0% 25%, var(--bg-elevated) 0% 50%)
        0 0 / 24px 24px;
}


.intro-headline {
    font-family: var(--font-pixel-display);
    font-size: clamp(1.3rem, 3.4vw, 2.4rem);
    line-height: 1.45;
    text-transform: uppercase;
    color: var(--text);
    margin: 0 0 20px;
}

.intro-name {
    color: var(--accent);
}

.intro-bio {
    font-size: clamp(1rem, 1.4vw, 1.2rem);
    line-height: 1.75;
    color: var(--text-muted);
    margin: 0;
}

@media (max-width: 560px) {
    .intro-avatar {
        shape-margin: 20px;
        margin-right: 24px;
    }
}

/* ==========================================================================
   Section rule: label fused into a pixel-dash line, squares at the joins
   ========================================================================== */

.section-rule {
    display: flex;
    align-items: center;
    gap: 18px;
    margin: 0 0 36px;
}

.section-rule::before,
.section-rule::after {
    content: "";
    flex: 1;
    height: 2px;
    background: repeating-linear-gradient(
        90deg,
        var(--border) 0 8px,
        transparent 8px 14px
    );
}

.section-rule-label {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    font-family: var(--font-pixel-display);
    font-size: 0.9rem;
    font-weight: 400;
    text-transform: uppercase;
    color: var(--text);
    line-height: 1;
}

/* coral squares where the label meets the dashes */
.section-rule-label::before,
.section-rule-label::after {
    content: "";
    width: 8px;
    height: 8px;
    background: var(--accent);
    flex-shrink: 0;
}

/* ==========================================================================
   Subscribe (native members form — replaces Portal modal as primary entry)
   ========================================================================== */

.subscribe {
    border-top: 2px solid var(--border);
    background: var(--bg-elevated);
}

.subscribe-inner {
    max-width: 2200px;
    padding: 48px clamp(20px, 3vw, 48px);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 40px;
    flex-wrap: wrap;
}

.subscribe-title {
    font-family: var(--font-pixel-display);
    font-size: 1.1rem;
    font-weight: 400;
    color: var(--accent);
    margin: 0 0 8px;
}

.subscribe-lede {
    margin: 0;
    color: var(--text-muted);
    max-width: 44ch;
}

.subscribe-form {
    flex: 1;
    min-width: 280px;
    max-width: 520px;
}

.subscribe-row {
    display: flex;
}

.subscribe-input {
    flex: 1;
    min-width: 0;
    font-family: var(--font-sans);
    font-size: 0.95rem;
    color: var(--text);
    background: var(--bg);
    border: 2px solid var(--border);
    border-right: none;
    padding: 12px 14px;
    outline: none;
}

.subscribe-input::placeholder {
    color: var(--text-muted);
    opacity: 0.7;
}

.subscribe-input:focus {
    border-color: var(--accent);
}

.subscribe-button {
    font-family: var(--font-pixel);
    font-size: 0.85rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--accent-text);
    background: var(--accent);
    border: 2px solid var(--accent);
    padding: 12px 20px;
    cursor: pointer;
}

.subscribe-button:hover {
    background: var(--bg);
    color: var(--accent);
}

/* form states: Ghost's members script toggles these classes on the form */
.subscribe-msg {
    display: none;
    font-family: var(--font-pixel);
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    margin: 12px 0 0;
}

.subscribe-form.success .subscribe-msg--success {
    display: block;
    color: var(--accent);
}

.subscribe-form.error .subscribe-msg--error {
    display: block;
    color: #ffa657;
}

.subscribe-form.loading .subscribe-button {
    opacity: 0.6;
    pointer-events: none;
}

.subscribe-form.success .subscribe-row {
    display: none;
}

/* ==========================================================================
   Buttons — native Ghost button card + pixel-btn HTML snippet with icons
   ========================================================================== */

/* shared button look: native editor button card and .pixel-btn both get it */
.kg-button-card .kg-btn,
.pixel-btn {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    font-family: var(--font-pixel);
    font-size: 0.9rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    text-decoration: none;
    color: var(--accent-text);
    background: var(--accent);
    border: 2px solid var(--accent);
    border-radius: 0;
    padding: 12px 20px;
    height: auto;
    line-height: 1;
    transition: none;
}

.kg-button-card .kg-btn:hover,
.pixel-btn:hover {
    color: var(--accent);
    background: var(--bg);
    opacity: 1;
}

/* post-content link styling must not bleed into buttons */
.post-content .pixel-btn,
.post-content .kg-btn {
    color: var(--accent-text);
    text-decoration: none;
}

.post-content .pixel-btn:hover,
.post-content .kg-btn:hover {
    color: var(--accent);
}

/* outline variant: <a class="pixel-btn pixel-btn--ghost" ...> */
.pixel-btn--ghost {
    color: var(--accent);
    background: transparent;
}

.post-content .pixel-btn--ghost {
    color: var(--accent);
}

.pixel-btn--ghost:hover {
    color: var(--accent-text);
    background: var(--accent);
}

.post-content .pixel-btn--ghost:hover {
    color: var(--accent-text);
}

/* centered row wrapper: <p class="pixel-btn-row">…buttons…</p> */
.pixel-btn-row {
    display: flex;
    justify-content: center;
    gap: 14px;
    flex-wrap: wrap;
}

/* ---- pixel icons: 8x8 SVGs as masks, colored by currentColor ---------- */

.pixel-btn[data-icon]::before {
    content: "";
    width: 1.05em;
    height: 1.05em;
    flex-shrink: 0;
    background: currentColor;
    -webkit-mask: var(--icon) no-repeat center / contain;
    mask: var(--icon) no-repeat center / contain;
}

/* arrow right */
.pixel-btn[data-icon="arrow"] {
    --icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8"><path d="M4 1h1v1H4zM5 2h1v1H5zM0 3h6v1H0zM0 4h8v1H0zM0 3h6v1H0zM5 5h1v1H5zM4 6h1v1H4zM6 3h1v2H6z"/></svg>');
}

/* external link: box with arrow leaving the corner */
.pixel-btn[data-icon="external"] {
    --icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8"><path d="M4 0h4v4H7V2H5V1H4zM6 1v1H5v1H4v1H3V3h1V2h1V1zM0 2h2v1H1v4h4V6h1v2H0z"/></svg>');
}

/* download: arrow into tray */
.pixel-btn[data-icon="download"] {
    --icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8"><path d="M3 0h2v3h1v1H5v1H3V4H2V3h1zM1 4h1v1h1v1h2V5h1V4h1v2H1zM0 6h1v2H0zM7 6h1v2H7zM1 7h6v1H1z"/></svg>');
}

/* mail envelope */
.pixel-btn[data-icon="mail"] {
    --icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8"><path d="M0 1h8v6H0zM1 2v1h1v1h1v1h2V4h1V3h1V2H6v1H5v1H3V3H2V2z" fill-rule="evenodd"/></svg>');
}

/* github-ish pixel cat */
.pixel-btn[data-icon="github"] {
    --icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8"><path d="M1 0h1v1H1zM6 0h1v1H6zM1 1h6v3H1zM2 4h4v1H2zM2 2v1h1V2zM5 2v1h1V2z M1 5h1v1H1zM6 5h1v1H6zM2 5h4v3H2zM3 7v1h2V7z" fill-rule="evenodd"/><path d="M2 2h1v1H2zM5 2h1v1H5z" fill="black" fill-opacity="0"/></svg>');
}

/* pixel heart (matches the site mark) */
.pixel-btn[data-icon="heart"] {
    --icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 7"><path d="M1 0h2v1H1zM5 0h2v1H5zM0 1h8v3H0zM1 4h6v1H1zM2 5h4v1H2zM3 6h2v1H3z"/></svg>');
}

/* code brackets */
.pixel-btn[data-icon="code"] {
    --icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8"><path d="M2 1h1v1H2zM1 2h1v1H1zM0 3h1v2H0zM1 5h1v1H1zM2 6h1v1H2zM5 1h1v1H5zM6 2h1v1H6zM7 3h1v2H7zM6 5h1v1H6zM5 6h1v1H5z"/></svg>');
}

/* ==========================================================================
   404 page
   ========================================================================== */

.error-page {
    text-align: center;
    padding: 40px 0 64px;
}

/* broken heart — same mark as the header, cracked */
.error-heart {
    width: clamp(64px, 12vw, 104px);
    height: auto;
    aspect-ratio: 8 / 7;
    color: var(--accent);
    margin-bottom: 28px;
}

.error-code {
    font-family: var(--font-pixel-display);
    font-size: clamp(2.6rem, 9vw, 5rem);
    line-height: 1;
    color: var(--accent);
    margin: 0 0 20px;
}

.error-title {
    font-family: var(--font-pixel);
    font-size: clamp(1rem, 2.6vw, 1.5rem);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    line-height: 1.4;
    color: var(--text);
    margin: 0 0 14px;
}

.error-message {
    color: var(--text-muted);
    max-width: 46ch;
    margin: 0 auto 32px;
}

.error-actions {
    margin: 0;
}
