/* ------------------------------------------------------------------
   Paper and moths
   Layout after fjzzq2002.github.io. Warm paper, navy ink, clay / amber /
   sage accents. The drawings are ASCII scenes made by assets/js/ascii-fx.js.
------------------------------------------------------------------ */
:root {
    --bg: #FEFDFB;
    --bg-card: #FFFFFE;
    --bg-side: #F9F7F2;
    --rule: #E3DED2;
    --rule-strong: #CFC8B8;

    --ink: #1E2A3F;
    --ink-soft: #47506A;
    --ink-dim: #7E8290;

    --navy: #1B2A41;
    --midblue: #5E84B9;
    --pale: #C9D5E3;
    --sage: #5B7F6E;
    --clay: #C8623A;
    --amber: #DE934D;
    --peach: #E3AE84;
    --pink: #CD8F7C;

    --link: #4F6FA3;
    --link-hov: #2C4A8A;

    --dot-0: var(--clay);
    --dot-1: var(--clay);
    --dot-2: var(--clay);
    --dot-3: var(--clay);

    --serif: "Spectral", "Iowan Old Style", Palatino, Georgia, serif;
    --sans: "Source Sans 3", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;

    --sidebar-w: 316.2px;
    --page-max: 1097.4px;
    --page-pad: 66.96px;
    --text: clamp(14.42px, 0.55vw + 9.77px, 16.28px);
}

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
/* the whole site is sized as the browser shows it at 93%: px values were scaled by 0.93, and rem follows */
html { font-size: 93%; }

body {
    background: var(--bg);
    color: var(--ink);
    font-family: var(--serif);
    font-size: 15.81px;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
    position: relative;
    overflow-x: hidden;
}

/* paper grain over everything, multiplied in very lightly */
body::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 60;
    pointer-events: none;
    opacity: 0.07;
    mix-blend-mode: multiply;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* selected text goes negative: paper on ink */
::selection { background: var(--ink); color: var(--bg); }
::-moz-selection { background: var(--ink); color: var(--bg); }
a::selection, strong::selection, em::selection, code::selection { background: var(--ink); color: var(--bg); }

a { color: var(--link); text-decoration: none; transition: color 0.15s, border-color 0.15s; }
a:hover { color: var(--link-hov); }
img { max-width: 100%; height: auto; display: block; }
strong { font-weight: 600; color: var(--ink); }

/* ------------------------------------------------------------------
   Ambient scatter
------------------------------------------------------------------ */
/* cosmic rays: a layer over everything, blended in difference so the ray
   inverts what it crosses */
.ray-layer {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 70;
    pointer-events: none;
    mix-blend-mode: difference;
}

.bg-drift {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 0;
    pointer-events: none;
    display: block;
    transition: opacity 1.6s ease;
}
/* the effects switch is off: the field fades, the hint and the flux dial step back */
.fx-off .bg-drift { opacity: 0; }
.fx-off .sidebar-hint { opacity: 0; }
.sidebar-fx {
    margin: 0.5rem 0 0;
    font-family: var(--sans);
    font-size: 0.78rem;
    line-height: 1.5;
    color: var(--ink-dim);
}
.fx-btn {
    appearance: none;
    background: none;
    border: 0;
    padding: 0 1px;
    margin: 0;
    font: inherit;
    color: var(--ink-dim);
    cursor: pointer;
    text-underline-offset: 2.79px;
}
.fx-btn:hover { color: var(--ink); }
.fx-btn:focus-visible { outline: 2px solid rgba(200, 98, 58, 0.5); outline-offset: 2px; border-radius: 2px; }
.fx-sep { margin: 0 0.35em; }
html:not(.fx-off) .fx-btn[data-fx="on"], html.fx-off .fx-btn[data-fx="off"] { color: var(--ink); text-decoration: underline; }

.fx-off .flux { opacity: 0.35; pointer-events: none; }
.flux { transition: opacity 0.6s ease; }

/* ------------------------------------------------------------------
   Shell: fixed sidebar + main column
------------------------------------------------------------------ */
.shell { display: flex; min-height: 100vh; }
.sidebar {
    width: var(--sidebar-w);
    flex: 0 0 var(--sidebar-w);
    position: fixed;
    top: 0; left: 0; bottom: 0;
    overflow-y: auto;
    padding: 3.2rem 2rem 1.5rem;
    background: rgba(245, 245, 243, 0.92);
    border-right: 1px solid rgba(27, 42, 65, 0.12);
    z-index: 30;
}
.sidebar-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;    min-height: 100%;                   /* so the hint can sit at the bottom */
}
/* a line at the foot of the pane saying how the page plays */
.sidebar-hint {
    margin: auto 0 0;
    padding-top: 1.6rem;
    font-family: var(--sans);
    font-size: 0.78rem;
    line-height: 1.5;
    color: var(--ink-soft);
    opacity: 0.75;
    transition: opacity 0.6s ease;
    max-width: 186px;
}
.sidebar-name {
    font-family: var(--serif);
    font-weight: 600;
    font-size: 2.01rem;                 /* sized so the name spans the photo's width */
    letter-spacing: -0.015em;
    line-height: 1.15;
    color: var(--ink);
    margin: 1.6rem 0 1.1rem;
}
.sidebar-nav {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    font-family: var(--serif);
    font-style: italic;
    font-size: 1.2rem;
}
.sidebar-nav a { color: var(--ink-soft); padding: 0.2rem 0; }
.sidebar-nav a:hover { color: var(--ink); }
.sidebar-nav a.active { color: var(--ink); font-weight: 500; }
.sidebar-email {
    display: inline-block;
    margin: 1.3rem 0 0;
    font-family: var(--sans);
    font-size: 0.86rem;
    color: var(--ink-soft);
    white-space: nowrap;
    transition: color 0.15s;
}
.sidebar-email:hover, .sidebar-email:focus-visible { color: var(--link); }
.sidebar-social {
    list-style: none;
    padding: 0;
    margin: 0.9rem 0 0;
    display: flex;
    gap: 0.6rem;
}
.sidebar-social a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 35.34px;
    height: 35.34px;
    border-radius: 50%;
    color: var(--ink-soft);
    background: rgba(27, 42, 65, 0.05);
    transition: background 0.2s, color 0.2s;
}
.sidebar-social a:hover { background: rgba(200, 98, 58, 0.14); color: var(--clay); }
.sidebar-social svg { width: 17.67px; height: 17.67px; }
.main-col {
    flex: 1;
    margin-left: var(--sidebar-w);
    min-width: 0;
    display: flex;
    flex-direction: column;
}

/* ------------------------------------------------------------------
   Page wrapper and shared accents
------------------------------------------------------------------ */
.page {
    position: relative;
    z-index: 5;
    width: 100%;
    max-width: var(--page-max);
    margin: 0 auto;
    padding: 37.2px var(--page-pad) 0;
    flex: 1;
}

.rule-and-dot {
    display: flex;
    align-items: center;
    gap: 7.44px;
    margin: 0 0 26.04px 0;
}
.rule-and-dot .rule { display: block; width: 74.4px; height: 1px; background: var(--clay); }
.rule-and-dot .dot { display: block; width: 5.58px; height: 5.58px; border-radius: 50%; background: var(--clay); }
.rule-and-dot.small { margin-bottom: 16.74px; }
.rule-and-dot.small .rule { width: 48.36px; }
.rule-and-dot.small .dot { width: 4.65px; height: 4.65px; }

.sw-terra-fg { color: var(--clay); }
.sw-blue-fg  { color: var(--midblue); }
.sw-sage-fg  { color: var(--sage); }


/* ------------------------------------------------------------------
   Hero
------------------------------------------------------------------ */
.hero {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 37.2px;
    align-items: center;
    padding: 7.44px 0 0 0;
}
.hero-art {
    position: relative;
    width: 100%;
    aspect-ratio: 720 / 700;
}
/* the home intro: three paragraphs beside the loss landscape */
.intro-card {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 372px;
    gap: 52.08px;
    align-items: stretch;
    padding: 26.04px 0 7.44px 0;
}
.intro-text .bio a { color: var(--link); border-bottom: 1px solid rgba(79, 111, 163, 0.45); padding-bottom: 1px; }
.intro-text .bio a:hover { color: var(--link-hov); border-bottom-color: var(--link-hov); }
/* the figure fills the height of the text beside it */
.intro-art { display: flex; flex-direction: column; padding-top: 5.58px; }
.intro-art .card-art-ascii { flex: 1; aspect-ratio: auto; min-height: 297.6px; }
.intro-art .card-art-hint { grid-column: auto; text-align: right; }
@media (max-width: 1100px) { .intro-card { grid-template-columns: minmax(0, 1fr) 316.2px; } }
@media (max-width: 900px) {
    .intro-card { grid-template-columns: minmax(0, 1fr); gap: 14.88px; }
    .intro-art { max-width: 334.8px; }
    .intro-art .card-art-ascii { aspect-ratio: 420 / 340; min-height: 0; }
    .intro-art .card-art-hint { text-align: left; }
}
.card-art-ascii .ascii-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
}
.plate-canvas, .footer-canvas, .thumb-ascii { display: block; }
.card-art-ascii { position: relative; min-height: 0; aspect-ratio: 420 / 340; cursor: crosshair; touch-action: none; }
.card-art-hint {
    grid-column: 2;
    margin: 5.58px 0 0 0;
    font-family: var(--sans);
    font-size: 10.7px;
    letter-spacing: 0.04em;
    color: var(--ink-dim);
    text-align: right;
}
.info-card-landscape { grid-template-rows: auto auto; align-items: center; }
.info-card-landscape .card-body { grid-row: 1 / span 2; }
.info-card-landscape .card-art { align-self: end; }
.info-card-landscape .card-art-hint { align-self: start; }
@media (max-width: 820px) {
    .card-art-hint { grid-column: 1; text-align: left; order: -1; }
}

/* headings decode from glyphs; keep the width stable while they do */
.decoding { white-space: nowrap; }
.display-name.decoding { white-space: normal; }   /* long titles may wrap while they decode */
.decoding::after {
    content: "\258C";
    margin-left: 0.08em;
    color: var(--clay);
    animation: blink 0.5s steps(1) infinite;
}
@keyframes blink { 50% { opacity: 0; } }

.hero-scene, .scene-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
}
/* The photo sits at the top of the sidebar, graded a little warm so its sky
   sits with the paper. The filter is on the link so the reveal, the photo
   and the wave tiles all take the same grade. */
.ascii-photo-link {
    position: relative;
    width: 213.9px;
    aspect-ratio: 1;
    display: block;
    border-radius: 2.79px;
    filter: sepia(0.3) saturate(1.05) contrast(1.02) brightness(1.03);
}
.ascii-photo-wrap {
    position: relative;
    display: block;
    width: 100%;
    height: 100%;
    border-radius: 2.79px;
    overflow: hidden;
    background: var(--navy);
    box-shadow: 0 0 0 1px rgba(27, 42, 65, 0.12);
}
.ascii-photo-video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    pointer-events: none;
    z-index: 2;
    opacity: 0;
}
.ascii-photo-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 1;
    display: block;
}
.ascii-photo {
    position: relative;
    width: 100%;
    height: 100%;
    object-fit: cover;
    margin: 0;
    z-index: 0;
}
/* With JS the static photo stays hidden until the reveal script decides it
   is the intended state; without JS it is the fallback. */
.js .ascii-photo:not(.is-shown) { opacity: 0; visibility: hidden; }
.ascii-photo.is-hidden { opacity: 0; visibility: hidden; }
/* the band of the photo a ripple is crossing, drawn as glyphs */
/* overhangs the photo so a wave can bend its rim; keep PAD in sync with ascii-fx.js */
.ascii-photo-ripple {
    position: absolute;
    inset: -14%;
    width: 128%;
    height: 128%;
    z-index: 3;
    pointer-events: none;
}
/* a glitching letter keeps its own width in the line; the glyph is painted over it */
.glitch-run .g { position: relative; color: transparent; }
.glitch-run .g::after {
    content: attr(data-g);
    position: absolute;
    left: 0;
    top: 0;
    color: var(--gc, var(--ink));
    pointer-events: none;
}
/* a stuck bit: the glyph in paper on a bar of ink, held for seconds; it blinks
   in, glows, and stutters out */
.glitch-run .g.stuck::after {
    inset: -1px -1px -2px;
    text-align: center;
    font-weight: 700;
    color: var(--bg);
    background: var(--gc, var(--ink));
    box-shadow: 0 0 0 1px var(--gc, var(--ink)), 0 0 9.3px 1px var(--gc, var(--ink));
    animation: stuck-bit var(--life, 5s) steps(1, end) both;
    z-index: 1;
}
@keyframes stuck-bit {
    0%, 2%, 4% { background: var(--bg); color: var(--gc, var(--ink)); box-shadow: 0 0 0 2px var(--gc, var(--ink)); }
    1%, 3%, 5% { background: var(--gc, var(--ink)); color: var(--bg); }
    86%, 90%, 95% { background: var(--bg); color: var(--gc, var(--ink)); box-shadow: 0 0 0 2px var(--gc, var(--ink)); }
    88%, 93%, 97%, 100% { background: var(--gc, var(--ink)); color: var(--bg); }
}
/* the effects switch going off: a stuck letter lets go early */
.glitch-run .g.stuck.fading::after { animation: none; transition: opacity 0.5s ease; opacity: 0; }
@media (prefers-reduced-motion: reduce) {
    .glitch-run .g.stuck::after { animation: none; }
}

.hero-text { position: relative; }
.display-name {
    font-family: var(--serif);
    font-weight: 600;
    font-size: clamp(39.06px, 4.8vw, 55.8px);
    line-height: 1;
    letter-spacing: -0.022em;
    margin: 0 0 20.46px 0;
    color: var(--ink);
}
.bio {
    margin: 0 0 14.88px 0;
    font-size: var(--text);
    line-height: 1.7;
    color: var(--ink);
    overflow-wrap: break-word;
}
.bio a, .card-body a, .post-body a {
    color: var(--link);
    border-bottom: 1px solid rgba(79, 111, 163, 0.45);
    padding-bottom: 1px;
}
.bio a:hover, .card-body a:hover, .post-body a:hover { color: var(--link-hov); border-bottom-color: var(--link-hov); }
.bio-note {
    margin-top: 3.72px;
    padding: 9.3px 13.02px;
    border-left: 2.79px solid var(--clay);
    font-style: italic;
    font-size: var(--text);
    color: var(--ink);
}

/* ------------------------------------------------------------------
   Research card
------------------------------------------------------------------ */
.card-row {
    margin-top: 26.04px;
    padding-top: 7.44px;
    border-top: 1px solid var(--rule);
}
.info-card {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 353.4px;
    gap: 40.92px;
    align-items: center;
}
.card-body { padding: 29.76px 0 26.04px 0; }
.card-title {
    font-family: var(--serif);
    font-weight: 500;
    font-size: 26.04px;
    line-height: 1.2;
    letter-spacing: -0.012em;
    margin: 0 0 13.02px 0;
    color: var(--ink);
}
.card-body p, .card-body ul {
    margin: 0;
    font-size: var(--text);
    line-height: 1.65;
    color: var(--ink);
}
.card-body p + p, .card-body p + ul, .card-body ul + p { margin-top: 13.02px; }
.card-body ul { padding-left: 18.6px; }
.card-body ul li { margin: 8.37px 0; }
.card-art { position: relative; min-height: 223.2px; }
.card-art .card-svg { width: 130%; max-width: none; margin-right: -30%; aspect-ratio: 420 / 340; }

/* ------------------------------------------------------------------
   Social pill row
------------------------------------------------------------------ */
.social-row {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    border-top: 1px solid var(--rule);
    border-bottom: 1px solid var(--rule);
}
.social-pill {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 13.02px;
    padding: 20.46px 11.16px;
    color: var(--ink);
    border-right: 1px solid var(--rule);
    transition: background 0.18s;
}
.social-pill:last-child { border-right: none; }
.social-pill:hover { background: var(--bg-card); color: var(--ink); }
.social-pill .circle {
    width: 40.92px;
    height: 40.92px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    color: var(--ink);
    transition: transform 0.18s;
}
.social-pill:hover .circle { transform: translateY(-2px); }
.social-pill .circle svg { width: 18.6px; height: 18.6px; }
.circle.sw-bronze  { background: rgba(184, 168, 144, 0.35); }
.circle.sw-mustard { background: rgba(227, 182, 88, 0.22); }
.circle.sw-terra   { background: rgba(200, 98, 58, 0.18); }
.social-pill .label { font-weight: 500; font-size: 15.81px; letter-spacing: -0.005em; }
.social-pill .arrow { color: var(--link); font-size: 16.74px; transition: transform 0.18s; }
.social-pill:hover .arrow { transform: translateX(3.72px); }

/* ------------------------------------------------------------------
   Sections
------------------------------------------------------------------ */
.lower, .news-sec { padding-top: 7.44px; }
.section-head { margin: 52.08px 0 16.74px 0; }
.section-title {
    font-family: var(--serif);
    font-weight: 500;
    font-size: 27.9px;
    letter-spacing: -0.012em;
    color: var(--ink);
    margin: 0 0 5.58px 0;
}

/* ------------------------------------------------------------------
   Featured cards (publications and projects)
------------------------------------------------------------------ */
.feat-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 52.08px;
}
.feat-card {
    border-top: 1px solid var(--rule);
    padding: 24.18px 0 27.9px 0;
    display: grid;
    grid-template-columns: minmax(0, 1fr) 159.96px;
    column-gap: 22.32px;
    grid-template-areas:
        "venue   thumb"
        "title   thumb"
        "desc    thumb"
        "authors thumb"
        "pills   thumb";
    align-content: start;
    color: var(--ink);
}
.feat-card-link:hover { color: var(--ink); }
.feat-card-link:hover .feat-title { color: var(--link-hov); }
.feat-venue {
    grid-area: venue;
    margin-bottom: 9.3px;
    font-family: var(--sans);
    font-size: 10.7px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    font-weight: 600;
}
.feat-title {
    grid-area: title;
    font-family: var(--serif);
    font-weight: 500;
    font-size: 18.14px;
    line-height: 1.32;
    letter-spacing: -0.005em;
    color: var(--ink);
    margin: 0;
    overflow-wrap: break-word;
    transition: color 0.15s;
}
.feat-desc {
    grid-area: desc;
    margin: 8.37px 0 0 0;
    font-size: 14.42px;
    line-height: 1.55;
    color: var(--ink);
}
.feat-authors {
    grid-area: authors;
    margin: 7.44px 0 0 0;
    font-style: italic;
    font-size: 13.02px;
    line-height: 1.5;
    color: var(--ink-soft);
}
.feat-pills {
    grid-area: pills;
    display: flex;
    flex-wrap: wrap;
    gap: 5.58px 7.44px;
    margin-top: 14.88px;
    align-self: end;
}
.feat-thumb {
    grid-area: thumb;
    position: relative;
    align-self: stretch;
    min-height: 176.7px;
    margin-top: 3.72px;
}
.feat-thumb img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    border: 1px solid var(--rule);
    border-radius: 2px;
    background: var(--bg-card);
}
/* the hover canvas covers the thumbnail and fades in */
.feat-thumb .thumb-ascii {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    background: var(--bg-card);
    border: 1px solid var(--rule);
    border-radius: 2px;
    opacity: 0;
    transition: opacity 0.35s ease;
    pointer-events: none;
}
.feat-card-link.ascii-on .thumb-ascii { opacity: 1; }
/* thin offset frame and a satellite dot in the card's colour */
.feat-thumb::before {
    content: "";
    position: absolute;
    inset: -7.44px 7.44px 7.44px -7.44px;
    border: 1px solid currentColor;
    border-radius: 2px;
    opacity: 0.45;
    pointer-events: none;
}
.feat-thumb::after {
    content: "";
    position: absolute;
    top: -10.23px;
    left: -10.23px;
    width: 6.51px;
    height: 6.51px;
    border-radius: 50%;
    background: currentColor;
}
.feat-card .feat-thumb { color: inherit; }

/* ------------------------------------------------------------------
   Publication rows: numbered, with two-tone badges
------------------------------------------------------------------ */
.pub-list {
    list-style: none;
    counter-reset: pub;
    margin: 0;
    padding: 0;
    border-top: 1px solid var(--rule);
}
.pub-row {
    counter-increment: pub;
    display: grid;
    grid-template-columns: 27.9px minmax(0, 1fr);
    column-gap: 9.3px;
    padding: 16.74px 0;
    border-bottom: 1px solid var(--rule);
}
.pub-row::before {
    content: counter(pub) ".";
    font-family: var(--serif);
    font-weight: 500;
    font-size: 16.74px;
    line-height: 1.35;
    color: var(--clay);
}
.pub-main { display: flex; flex-direction: column; gap: 5.58px; min-width: 0; }
.pub-title {
    font-family: var(--serif);
    font-weight: 600;
    font-size: 17.21px;
    line-height: 1.35;
    color: var(--ink);
    margin: 0;
}
.pub-authors {
    font-size: 14.42px;
    line-height: 1.5;
    color: var(--ink-soft);
    font-style: italic;
}
.pub-me { font-style: normal; font-weight: 600; color: var(--ink); text-decoration: underline; text-underline-offset: 2.79px; text-decoration-thickness: 1.5px; text-decoration-color: var(--ink); }
.pub-authors sup, .feat-authors sup {
    font-family: var(--sans);
    font-size: 1.05em;
    font-style: normal;
    font-weight: 800;
    line-height: 0;
    vertical-align: baseline;
    position: relative;
    top: -0.4em;
    margin-left: 2px;
    color: var(--clay);
    -webkit-text-stroke: 0.4px var(--clay);
}
.pub-badges { display: flex; flex-wrap: wrap; gap: 5.58px 6.51px; margin-top: 3.72px; }
.badge {
    display: inline-flex;
    align-items: stretch;
    font-family: var(--sans);
    font-size: 11.16px;
    font-weight: 600;
    line-height: 1;
    border-radius: 2.79px;
    overflow: hidden;
    color: #fff;
    text-decoration: none;
    box-shadow: 0 1px 0 rgba(27, 42, 65, 0.15);
    transition: transform 0.15s, box-shadow 0.15s;
}
a.badge:hover { transform: translateY(-1px); box-shadow: 0 2.79px 7.44px -2px rgba(27, 42, 65, 0.35); color: #fff; }
.badge .bl, .badge .bv { padding: 4.65px 6.51px; display: inline-flex; align-items: center; gap: 3.72px; }
.badge .bl { background: var(--navy); }
.badge .bl svg { width: 11.16px; height: 11.16px; }
/* the marks are dark on navy: set each on a small paper chip */
.badge .venue-mark {
    height: 13.95px;
    width: auto;
    display: block;
    padding: 2px;
    box-sizing: content-box;
    background: var(--bg);
    border-radius: 2.79px;
    margin: -2px 1px -2px -2px;
}
/* each kind of badge carries its own colour on the right-hand chip */
.badge-venue .bv { background: var(--clay); }
.badge-v-preprint .bv { background: #B31B1B; }   /* arXiv red */
.badge-v-iclr .bv { background: #1F7A8C; }       /* teal */
.badge-v-neurips .bv { background: #6B4E9B; }    /* NeurIPS purple */
.badge-paper .bv { background: #C0392B; }
.badge-forum .bv { background: #D08A3E; }
.badge-view  .bv { background: #5E84B9; }
.badge-code  .bv { background: #3E8E5E; }
.pub-note {
    margin: 11.16px 0 0 0;
    font-size: 13.49px;
    font-style: italic;
    color: var(--ink-soft);
}
.pub-note .dag { color: var(--clay); font-family: var(--sans); font-weight: 800; font-style: normal; font-size: 1.2em; margin-right: 2.79px; -webkit-text-stroke: 0.4px var(--clay); }

/* ------------------------------------------------------------------
   News ledger
------------------------------------------------------------------ */
.nw-list {
    list-style: none;
    margin: 0 0 0 3.72px;
    padding: 0 0 0 24.18px;
    border-left: 1px solid var(--rule-strong);
}
.nw-list li {
    position: relative;
    display: grid;
    grid-template-columns: 96.72px minmax(0, 1fr);
    padding: 7.44px 0;
    font-size: var(--text);
    line-height: 1.6;
}
.nw-list li::before {
    content: "";
    position: absolute;
    left: -27.9px;
    top: 13.02px;
    width: 6.51px;
    height: 6.51px;
    border-radius: 50%;
    background: var(--dot-c, var(--link));
    box-shadow: 0 0 0 2.79px var(--bg);
}
.nw-d {
    font-family: var(--sans);
    font-size: 11.62px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    font-weight: 700;
    color: var(--ink-dim);
    padding-top: 3.72px;
}
.nw-t { color: var(--ink); }
.nw-t a { color: inherit; }                     /* reads like the other items; the curious will click */
.nw-t a:hover { color: var(--link-hov); }
.news-logo {
    display: inline-block;
    width: auto;
    height: 1.05em;
    margin: 0 0.4em 0 0;
    vertical-align: -0.16em;
}

/* ------------------------------------------------------------------
   Latest: news and writing beside the ASCII cloudscape
------------------------------------------------------------------ */
.latest-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 40%;
    column-gap: 44.64px;
    align-items: start;
}
.latest-main { min-width: 0; }
.latest-main .compact-grid { grid-template-columns: minmax(0, 1fr); column-gap: 0; }
.cloud-art {
    position: sticky;
    top: 0;
    height: min(100vh, 725.4px);
    margin-top: 52.08px;
    pointer-events: none;
}
/* the canvas runs from its column to the right edge of the viewport */
.cloud-art canvas {
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    width: calc(100% + max(0px, (100vw - var(--sidebar-w) - var(--page-max)) / 2) + var(--page-pad));
    display: block;
}
@media (max-width: 1024px) {
    .latest-layout { grid-template-columns: minmax(0, 1fr); }
    .cloud-art { display: none; }
    .latest-main .compact-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 33.48px; }
}
@media (max-width: 820px) {
    .latest-main .compact-grid { grid-template-columns: minmax(0, 1fr); column-gap: 0; }
}

.pub-service {
    margin-top: 11.16px;
    font-style: normal;
    font-size: var(--text);
    line-height: 1.6;
    color: var(--ink);
}

/* ------------------------------------------------------------------
   Compact cards (writing list)
------------------------------------------------------------------ */
.compact-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: 33.48px;
    border-top: 1px solid var(--rule);
}
.compact-card {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 13.02px;
    align-items: center;
    padding: 16.74px 0;
    border-bottom: 1px solid var(--rule);
    color: var(--ink);
}
.compact-card:hover { color: var(--ink); }
.compact-card:hover .compact-title { color: var(--link-hov); }
.compact-title {
    font-family: var(--serif);
    font-weight: 500;
    font-size: 16.74px;
    line-height: 1.35;
    transition: color 0.15s;
}
.compact-meta {
    font-size: 13.49px;
    line-height: 1.5;
    color: var(--ink-soft);
    margin-top: 2.79px;
    font-style: italic;
}
.compact-meta .tag {
    font-family: var(--sans);
    font-style: normal;
    font-size: 10.23px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    font-weight: 600;
    color: var(--clay);
}
.compact-link {
    font-size: 20.46px;
    color: var(--link);
    padding: 3.72px 5.58px;
    transition: transform 0.18s;
}
.compact-card:hover .compact-link { transform: translateX(2.79px); }

/* ------------------------------------------------------------------
   Sub-page hero (Writing, Projects)
------------------------------------------------------------------ */
.page-hero {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 334.8px;
    gap: 37.2px;
    align-items: center;
    padding: 37.2px 0 7.44px 0;
    border-bottom: 1px solid var(--rule);
}
/* the list below a hero brings its own top rule, so the hero drops its
   rule there and the two are kept apart by some air */
.page-hero:has(+ .lower) { border-bottom: 0; }
.page-hero + .lower { padding-top: 74.4px; }
.page-hero .rule-and-dot { margin-bottom: 16.74px; }
.page-hero .bio { margin-bottom: 18.6px; color: var(--ink-soft); font-style: italic; }
.page-hero-art { display: flex; flex-direction: column; }
.scene-box { position: relative; aspect-ratio: 420 / 340; }
/* the murmuration has no box: its canvas covers the whole hero and the
   flock roams the region behind the title, with the caption at the corner */
.page-hero-wide { grid-template-columns: minmax(279px, 1fr) minmax(334.8px, 47%); position: relative; min-height: 334.8px; }
.page-hero-wide .hero-text, .page-hero-wide .art-caption { position: relative; z-index: 1; }
.page-hero-wide .page-hero-art { align-self: end; position: static; }
.page-hero-wide .scene-box { position: absolute; inset: 0 0 7.44px 0; aspect-ratio: auto; z-index: 0; pointer-events: none; }
/* the storm is a panorama: a wider, shorter box so the list below starts higher */
.page-hero-storm { grid-template-columns: minmax(0, 1fr) min(427.8px, 50%); padding-top: 26.04px; }
.page-hero-storm .scene-box { aspect-ratio: 460 / 215; }
.scene-canvas[data-scene="chaos"] { cursor: pointer; }
/* a line under each figure saying what it is */
.art-caption {
    margin: 7.44px 0 0 0;
    font-family: var(--sans);
    font-size: 10.7px;
    line-height: 1.5;
    letter-spacing: 0.04em;
    color: var(--ink-dim);
    text-align: right;
}
.art-caption a {
    color: inherit;
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
    text-decoration-color: rgba(126, 130, 144, 0.7);
}
.art-caption a:hover { color: var(--ink); text-decoration-color: currentColor; }
@media (max-width: 900px) { .art-caption { text-align: left; } }
.page-hero-plain { grid-template-columns: minmax(0, 1fr); padding-bottom: 22.32px; }
.page-hero-plain .bio { margin-bottom: 7.44px; }

/* ------------------------------------------------------------------
   Posts
------------------------------------------------------------------ */
.post {
    max-width: 688.2px;
    margin: 0 auto;
    padding: 37.2px 0 59.52px 0;
}
.post-kicker {
    font-family: var(--sans);
    font-size: 10.7px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    font-weight: 600;
    color: var(--clay);
    margin: 0 0 13.02px 0;
}
.post-kicker-sep { margin: 0 0.5em; color: var(--ink-dim); }
.post-title {
    font-family: var(--serif);
    font-weight: 600;
    font-size: clamp(27.9px, 3.4vw, 39.06px);
    line-height: 1.12;
    letter-spacing: -0.018em;
    margin: 0 0 93px 0;                /* air between the title and the first line; no rule here */
    color: var(--ink);
}
.post-body { font-size: var(--text); line-height: 1.75; position: relative; }
/* a wave's band of ASCII tiles, laid over an image in a post */
.ascii-img-ripple { position: absolute; pointer-events: none; z-index: 2; border-radius: 2.79px; }
/* the faint streaks cosmic rays leave on photos, in negative like the rays; JS places the one over a post image */
.ray-tracks { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 2; mix-blend-mode: difference; }
.post-body > :first-child { margin-top: 0; }
.post-body p, .post-body ul, .post-body ol { margin: 0 0 1.1em 0; }
.post-body h1, .post-body h2, .post-body h3, .post-body h4 {
    font-family: var(--serif);
    font-weight: 500;
    color: var(--ink);
    line-height: 1.25;
    letter-spacing: -0.01em;
    margin: 2em 0 0.6em 0;
}
.post-body h1 { font-size: 1.7em; }
.post-body h2 { font-size: 1.45em; }
.post-body h3 { font-size: 1.2em; }
.post-body h4 { font-size: 1.05em; }
.post-body hr { border: 0; height: 1px; background: var(--rule); margin: 2em 0; }
.post-body img { margin: 1.75rem auto; border-radius: 2.79px; }
.post-body .news-logo { margin: 0 0.35em 0 0; }
/* post.js marks a paragraph that is only an <em> as a caption, and one that
   opens with an <em> followed by text as a run-in heading */
.post-body p.caption {
    text-align: center;
    color: var(--ink-dim);
    font-size: 0.9em;
    margin: -0.9rem auto 1.5rem;
}
.post-body p.runin > em:first-child {
    font-style: normal;
    font-weight: 600;
    color: var(--ink);
    margin-right: 0.45em;
}
/* a quotation: upright, full ink, a clay bar; the bar says it is a quote,
   so a paragraph the author wrapped whole in *italics* is set upright */
.post-body blockquote {
    border-left: 2px solid var(--clay);
    margin: 1.7rem 0;
    padding: 0.2rem 0 0.2rem 1.2rem;
    color: var(--ink);
    font-style: normal;
    font-size: 1.04em;
    line-height: 1.7;
    text-align: left;
}
.post-body blockquote p { margin: 0 0 0.6em; }
.post-body blockquote p:last-child { margin-bottom: 0; }
.post-body blockquote > p > em:only-child { font-style: normal; }
/* a short closing line (an attribution such as "~Thucydides") sits apart, small and quiet */
.post-body blockquote > p:last-child:not(:first-child) {
    margin-top: 0.7em;
    font-family: var(--sans);
    font-size: 0.8em;
    letter-spacing: 0.04em;
    color: var(--ink-soft);
}
.post-body blockquote > p:last-child:not(:first-child) > em:only-child { font-style: normal; }
.post-body table { border-collapse: collapse; margin: 1.5rem 0; font-size: 0.95em; }
.post-body th, .post-body td { border: 1px solid var(--rule); padding: 0.4em 0.7em; text-align: left; }
.post-body th { background: var(--bg-card); font-family: var(--sans); font-weight: 600; }

/* code */
.post-body pre {
    position: relative;
    background: #fff;
    border: 1px solid var(--rule);
    border-radius: 3.72px;
    padding: 1rem 1.1rem;
    margin: 1.5rem 0;
    overflow: auto;
}
.post-body pre code {
    display: block;
    font-family: var(--mono);
    font-size: 12.56px;
    line-height: 1.55;
    color: var(--ink);
    background: transparent;
    padding: 0;
}
.post-body code {
    font-family: var(--mono);
    font-size: 0.9em;
    background: rgba(27, 42, 65, 0.06);
    color: var(--ink);
    padding: 0.08em 0.35em;
    border-radius: 2.79px;
}
.copy-button {
    position: absolute;
    top: 7.44px;
    right: 7.44px;
    padding: 3.72px 7.44px;
    font-size: 11.16px;
    font-family: var(--sans);
    color: var(--ink-soft);
    background: var(--bg-card);
    border: 1px solid var(--rule);
    border-radius: 2.79px;
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.2s;
}
pre:hover .copy-button { opacity: 1; }
.copy-button:hover { color: var(--ink); border-color: var(--ink); }

/* tweets */
.twitter-tweet { max-width: 390.6px !important; margin: 2rem auto !important; }

/* ------------------------------------------------------------------
   Footer
------------------------------------------------------------------ */
.site-footer {
    position: relative;
    z-index: 5;
    width: 100%;
    max-width: var(--page-max);
    margin: 59.52px auto 0;
    padding: 0 var(--page-pad) 44.64px;
}
/* without the hills (sub-pages) the dial sits a little further from the content */
.site-footer > .flux:first-child { margin-top: 22.32px; }
.footer-art { position: relative; height: clamp(111.6px, 16vw, 204.6px); cursor: crosshair; }
.footer-canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.footer-note {
    margin: 0 0 33.48px 0;
    padding-top: 37.2px;
    border-top: 1px solid var(--rule);
    font-size: 13.49px;
    line-height: 1.65;
    color: var(--ink-soft);
}
.footer-note p { margin: 0; }
.footer-note a { color: var(--link); border-bottom: 1px solid rgba(79, 111, 163, 0.45); }
.footer-note a:hover { color: var(--link-hov); border-bottom-color: var(--link-hov); }
.footer-note code {
    font-family: var(--mono);
    font-size: 0.9em;
    background: rgba(27, 42, 65, 0.06);
    padding: 0.05em 0.3em;
    border-radius: 2.79px;
    color: var(--ink);
}
/* the flux dial: an ASCII instrument for the cosmic-ray cadence */
.flux {
    margin: 0 0 29.76px 0;
    padding: 16.74px 18.6px 13.02px;
    border: 1px solid var(--rule);
    border-radius: 2.79px;
    background: var(--bg-card);
    font-family: var(--mono);
    color: var(--ink-soft);
}
.flux-head { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 5.58px 11.16px; font-size: 10.23px; letter-spacing: 0.16em; margin-bottom: 9.3px; }
.flux-label { flex: 1 1 auto; min-width: 0; }   /* so the sentence wraps on a phone instead of overflowing */
.flux-count { white-space: nowrap; }
.flux-count { color: var(--ink-dim); }
.flux-count span { color: var(--clay); }
.flux { position: relative; }
.flux-meter {
    margin: 2px 0 5.58px;
    padding: 11.16px 0;                 /* a comfortable touch target */
    font-size: 10.23px;
    line-height: 1.25;
    white-space: pre;
    overflow: hidden;
    color: var(--ink);
    cursor: ew-resize;
    user-select: none;
    touch-action: none;
    outline: none;
}
.flux-meter:focus-visible { box-shadow: 0 0 0 2px rgba(200, 98, 58, 0.35); border-radius: 2px; }
.flux-note { margin: 0; font-size: 11.16px; letter-spacing: 0.04em; color: var(--ink-soft); }
.flux-note.hot { color: var(--clay); }

.footer-inner {
    display: flex;
    justify-content: space-between;
    gap: 14.88px;
    flex-wrap: wrap;
    padding-top: 20.46px;
    border-top: 1px solid var(--rule);
    font-family: var(--sans);
    font-size: 12.09px;
    color: var(--ink-soft);
}
.footer-inner p { margin: 0; }

/* ------------------------------------------------------------------
   Responsive
------------------------------------------------------------------ */
@media (max-width: 1100px) {
    :root { --page-pad: 33.48px; }
    .feat-grid { grid-template-columns: minmax(0, 1fr); }
    .info-card { grid-template-columns: minmax(0, 1fr) 279px; }
    .latest-layout { grid-template-columns: minmax(0, 1fr); }
    .cloud-art { display: none; }
    .latest-main .compact-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 33.48px; }
}
@media (max-width: 900px) {
    :root { --page-pad: 26.04px; }
    .shell { flex-direction: column; }
    .sidebar {
        position: static;
        width: 100%;
        flex: none;
        padding: 1.8rem 1.25rem 1.3rem;
        border-right: none;
        border-bottom: 1px solid var(--rule);
    }
    .ascii-photo-link { width: 159.96px; }   /* the name's width at this size */
    .sidebar-name { margin: 1rem 0 0.6rem; font-size: 1.5rem; }
    .sidebar-nav { flex-direction: row; gap: 1.2rem; }
    .sidebar-social { margin-top: 1rem; }
    .main-col { margin-left: 0; }
    .hero { grid-template-columns: minmax(0, 1fr); gap: 18.6px; }
    .hero-art { order: -1; max-width: 446.4px; margin: 0 auto; }
    .info-card { grid-template-columns: minmax(0, 1fr); gap: 7.44px; }
    .card-art { order: -1; max-width: 334.8px; min-height: 0; }
    .card-art .card-svg { width: 100%; margin-right: 0; }
    .card-body { padding-top: 7.44px; }
    .page-hero { grid-template-columns: minmax(0, 1fr); gap: 11.16px; }
    .page-hero-art { max-width: 297.6px; }
    .page-hero-wide .page-hero-art { max-width: 520.8px; }
    .page-hero-storm .page-hero-art { max-width: 427.8px; }
    .latest-main .compact-grid { grid-template-columns: minmax(0, 1fr); column-gap: 0; }
}
@media (max-width: 600px) {
    .page-hero-wide { min-height: 0; }
    .page-hero-wide .scene-box { position: relative; inset: auto; aspect-ratio: 460 / 340; pointer-events: auto; }
    .page-hero-wide .page-hero-art { align-self: auto; }
    .nw-list { padding-left: 18.6px; }
    .nw-list li { grid-template-columns: minmax(0, 1fr); padding: 7.44px 0; }
    .nw-list li::before { left: -22.32px; top: 11.16px; }
    .nw-d { padding-top: 0; margin-bottom: 2px; }
}
@media (max-width: 520px) {
    /* phones keep the reading size and gutter they had before the scale-down */
    :root { --page-pad: 18px; --text: 15.5px; }
    body { font-size: 17px; }
    .flux { padding: 13.02px 13.02px 11.16px; }
    .flux-head { flex-direction: column; gap: 3.72px; }
    .footer-art { height: 102.3px; }
    .feat-card {
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas: "venue" "thumb" "title" "desc" "authors" "pills";
    }
    .feat-thumb { width: 100%; min-height: 0; aspect-ratio: 2 / 1; margin: 5.58px 0 14.88px; }
    .pub-title { font-size: 15.81px; }
}
.footer-caption { margin: 5.58px 0 14.88px; }
