/* ==========================================================================
   preview.css — self-contained styling for the Simplex Publications index
   preview page. Font stacks and neutral tokens are copied (not @imported) from
   the site's style.css so later homepage CSS changes can't shift this preview.
   ========================================================================== */

:root {
    /* neutral palette (copied from style.css) */
    --color-bg: #ffffff;
    /* Ink ramp (Loren, 2026-08-31): a geometric contrast ramp against the
       white ground, anchored at the accessibility floor — faint 5:1, muted
       10:1, text ~20:1 (each tier twice the contrast of the one below).
       Opaque hexes replace the old alpha blacks so the tiers hold on any
       background. */
    --color-text: #080808;
    --color-text-muted: #424242;
    --color-text-faint: #6f6f6f;

    /* font stacks (copied from style.css) */
    --font-display: "Cardo", Georgia, "Times New Roman", serif; /* Loren 2026-08-17; Cardo has no 600 face — 600 renders via 700 */
    --font-body: "STIX Two Text", Georgia, "Times New Roman", serif; /* Loren 2026-09-01 (captions tether to body) */
    --font-ui: "Source Sans 3", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --font-mono: "Commit Mono", ui-monospace, "SF Mono", Menlo, Monaco, monospace;
    --font-wordmark: "Cardo", Georgia, "Times New Roman", serif;
    --font-display-weight: 600;

    /* text sizes (driven live by size-lab.js on localhost) */
    --size-wordmark: 20px;
    --size-logomark: 25px; /* lockup base; single-line styles use 33 (lab-applied) */
    /* Shipped wordmark: the "from Simplex" lockup (Loren, 2026-08-31). Only
       the tokens whose var() fallbacks differ need declaring: tagline shown,
       line 1 fully upright, mark scaled to span both lines. */
    --wordmark-tagline: block;
    --wordmark-em-style: normal;
    --wordmark-logo-scale: 1.56; /* 25px base x 1.56 = 39px — integer, no half-pixel borders */
    /* declared (at their fallback values) so the drift panel can read every
       masthead token's shipped value from :root */
    --wordmark-style: normal;
    --wordmark-prefix: none;
    --wordmark-conn-from: inline;
    --wordmark-conn-by: none;
    --wordmark-simplex-weight: 400;
    --wordmark-simplex-style: normal;
    --size-intro: 18px;
    --size-title-major: 22px;
    --size-title-minor: 20px;
    --size-abstract: 16px;
    --size-meta: 12px;
    --size-date: 12px;

    /* gutter-date font — its own token, driven by the size-lab's Date picker */
    --font-date: var(--font-mono);

    /* preview-local layout tokens */
    --content-width: 710px;
    --col-left: 315px;
    --col-gap: 38px;
    --year-gutter: 104px;
    --list-top: 90px; /* gap between the intro block and the post list (layout-lab-tunable) */
    --minor-pad: 16px; /* minor entry top/bottom padding (layout-lab-tunable) */
    --minor-gap: 8px; /* minor entry internal gaps — desc/meta (layout-lab-tunable) */
    --venue-gold: #b8860b;      /* legacy venue gold — default is now ink (Loren 2026-08-28) */
}

* { box-sizing: border-box; }

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

body {
    margin: 0;
    font-family: var(--font-body);
    color: var(--color-text);
    background: var(--color-bg);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

/* --------------------------------------------------------------------------
   Header — logo mark + serif wordmark, no rule, no nav (per mockup)
   -------------------------------------------------------------------------- */
.site-header { width: 100%; }

.site-header-inner {
    max-width: var(--content-width);
    margin: 0 auto;
    padding: 42px 0 0; /* integer px — parity with style.css's masthead snap */
}

.site-header .logo {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    font-family: var(--font-wordmark);
    font-size: var(--size-wordmark);
    font-weight: 400;
    color: var(--color-text);
    text-decoration: none;
    letter-spacing: -0.01em;
}

.site-header .logo-mark {
    width: calc(var(--size-logomark) * var(--wordmark-logo-scale, 1));
    height: calc(var(--size-logomark) * var(--wordmark-logo-scale, 1));
    display: block;
    flex-shrink: 0;
}

/* logo.js / logo-lab.js replace the .logo-mark span with a fixed-size canvas;
   force the display size so --size-logomark keeps working after the swap
   (drag = raster-scaled; re-renders crisp once the canvas is next rebuilt). */
.site-header .logo canvas {
    width: calc(var(--size-logomark) * var(--wordmark-logo-scale, 1)) !important;
    height: calc(var(--size-logomark) * var(--wordmark-logo-scale, 1)) !important;
}

.site-header .logo-text { line-height: 1; font-style: var(--wordmark-style, normal); }
/* "Simplex" prefix — shown only in the wordmark's simplex mode; always
   upright even when the rest of the wordmark is italic. */
.logo-text .wm-prefix { display: var(--wordmark-prefix, none); font-style: normal; }

.site-header .logo-text em { font-style: var(--wordmark-em-style, italic); }

/* --------------------------------------------------------------------------
   Main column
   -------------------------------------------------------------------------- */
.preview {
    max-width: var(--content-width);
    margin: 0 auto;
    padding: 0 0 8rem;
}

/* Inline body links — underlined, faint (copied from style.css `a`) */
.preview a {
    color: inherit;
    text-decoration: underline;
    text-decoration-style: dotted;
    text-decoration-color: rgba(0, 0, 0, 0.28);
    text-underline-offset: 3px;
    text-decoration-thickness: 1px;
    transition: text-decoration-color 0.15s ease;
}
.preview a:hover { text-decoration-color: var(--color-text); }

/* --------------------------------------------------------------------------
   Intro
   -------------------------------------------------------------------------- */
.intro {
    margin-top: 5.5rem;
}

.intro p {
    font-family: var(--font-body);
    font-size: var(--size-intro);
    line-height: 1.15;
    color: var(--color-text);
    margin: 0 0 1.15rem;
}
.intro p:last-child { margin-bottom: 0; }
.intro em { font-style: italic; }

/* --------------------------------------------------------------------------
   Post list — two-column grid with a left year gutter
   -------------------------------------------------------------------------- */
.post-list {
    margin-top: var(--list-top);
}

/* Every entry carries its date in the left gutter: right-aligned against the
   content frame (24px clear of it), top flush with the entry's inner box —
   8px down on minors, 16px on majors. Absolutely positioned, so it stays out
   of the entry's grid and lifts with the spine on hover. */
.entry-date {
    position: absolute;
    right: calc(100% + 4px); /* card box already extends 20px past the frame */
    font-family: var(--font-date);
    font-size: var(--size-date);
    letter-spacing: 0.04em;
    color: var(--color-text-faint);
    line-height: 1.5;
    white-space: nowrap;
    text-align: right;
}
.entry.major .entry-date { top: 16px; }
/* follows the minor entry's own top padding — this offset was defined as "the
   top of the inner box", so it tracks --minor-pad rather than a fixed 16px */
.entry.minor .entry-date { top: var(--minor-pad); }

.group-entries {
    display: flex;
    flex-direction: column;
    gap: 0; /* entry top/bottom padding is the sole vertical rhythm */
}

/* --------------------------------------------------------------------------
   Month groups — the Layout Lab's "Month year" date mode. Consecutive
   same-month entries are wrapped in a .month-group carrying one gutter label;
   the entries themselves render no date. The label is a SIBLING of the entry
   anchors, so an entry's hover transform cannot carry it along (a per-entry
   .entry-date does lift with its spine — that difference is the point of this
   grouping). A plain flex column, matching .group-entries, so entries keep
   stacking exactly as they do in the flat "full dates" DOM.
   -------------------------------------------------------------------------- */
.month-group {
    position: relative;
    display: flex;
    flex-direction: column;
}
/* The group box spans the content frame (it is a plain child of
   .group-entries, and the entries' -20px side margins overhang it), so
   right: calc(100% + 24px) lands the label 24px clear of the frame edge — the
   same gutter position the alt-gutter dates use. Typography is .entry-date's.
   --label-top is emitted per group by layout-lab.js from the FIRST entry's
   kind: 16px on majors, var(--minor-pad) on minors. It is only the starting
   point: layout-lab.js then measures and overrides `top` inline so the label's
   baseline sits on that first entry's title's first-line baseline (the
   alignment the in-title full dates get for free), using the .month-probe
   below as the reference. Without that pass — no JS, no probe, or nothing
   measurable — this top-of-inner-box value is what stands. */
.month-label {
    position: absolute;
    right: calc(100% + 24px);
    top: var(--label-top, 16px);
    font-family: var(--font-date);
    font-size: var(--size-date);
    letter-spacing: 0.04em;
    color: var(--color-text-faint);
    line-height: 1.5;
    white-space: nowrap;
    text-align: right;
}

/* Baseline reference for the label. layout-lab.js injects one of these as the
   FIRST inline child of each group's first entry's title — the very slot the
   alt1-gutter-title full date occupies, minus the gutter transform. It is
   IN-FLOW inline, so inline layout drops its baseline onto the title's
   first-line baseline; it is zero-width and invisible, so it contributes
   nothing to the title's layout or paint. Its typography is .month-label's
   exactly, which is the whole point: two text rects in the same font share
   ascent and descent, so making the label's rect bottom meet the probe's rect
   bottom IS making their baselines meet. (Comparing the label's rect to the
   TITLE's rect instead aligns descender boxes, and the title's much deeper
   descender then pushes the label below the baseline — the bug this replaces.)
   font-weight/font-style are reset so the h2's display weight and the minor
   title's italic can't leak in and change the metrics.
   Like the alt1-gutter-title date it shares this slot with, the probe would
   grow the title's line box if --size-date × 1.5 ever exceeded the title's own
   line box; at the default 12px/22px there is ample headroom. */
.month-probe {
    display: inline-block;
    width: 0;
    white-space: nowrap;
    visibility: hidden;
    font-family: var(--font-date);
    font-size: var(--size-date);
    letter-spacing: 0.04em;
    line-height: 1.5;
    font-weight: 400;
    font-style: normal;
}
/* inline-block, so the outer zero-width box takes ITS baseline (and thus the
   probe text's) as its own — the same nesting the gutter dates use */
.month-probe > span {
    display: inline-block;
}

/* Each entry is one block-level link — a book spine in the stack. On hover
   it lifts out of the page: slight scale + soft shadow whose edges read as
   the seams between spines. The negative margin/padding pair widens the card
   box without moving the content, so the lift has breathing room.
   (.preview a outranks .entry alone, hence the compound selector.) */
.preview a.entry {
    display: grid;
    grid-template-columns: var(--col-left) 1fr;
    column-gap: var(--col-gap);
    color: inherit;
    text-decoration: none;
    position: relative;
    margin-left: -20px;
    margin-right: -20px;
    padding-left: 20px;
    padding-right: 20px;
    background: var(--color-bg);
    transition: transform 180ms ease-out, box-shadow 180ms ease-out,
        border-color 180ms ease-out, background-color 180ms ease-out;
}
.preview a.entry:focus-visible {
    outline: 1.5px solid var(--color-text);
    outline-offset: 2px;
}

/* ---- hover variants (hover-lab.js sets data-hover on <body>) ----------- */

/* Lift — scale + shadow; the shadow edge makes the seams (option one). */
body:not([data-hover]) .preview a.entry:hover,
body:not([data-hover]) .preview a.entry:focus-visible,
body[data-hover="lift"] .preview a.entry:hover,
body[data-hover="lift"] .preview a.entry:focus-visible {
    transform: scale(1.012) translateY(-1px);
    box-shadow:
        0 1px 2px rgba(0, 0, 0, 0.06),
        0 6px 22px rgba(0, 0, 0, 0.09);
    z-index: 1;
}

/* Seams — resting hairlines between spines; the hovered entry lifts free,
   taking no seam with it: its own seam and the one below both fade out. */
body[data-hover="seams"] .preview a.entry + a.entry {
    border-top: 1px solid rgba(0, 0, 0, 0.12);
}
/* In month-year date mode the .month-group wrappers break that a.entry +
   a.entry adjacency at every group boundary, so the first entry of each group
   after the first carries the seam itself. :first-of-type is the first `a`
   child — the .month-label span before it is a different element type, so it
   doesn't take the seam. The wrapper part sits in :where() to contribute no
   specificity, which leaves this rule level with the :hover/:focus-visible
   fades below; those come later in source order and so still win. */
body[data-hover="seams"] .preview :where(.month-group + .month-group) a.entry:first-of-type {
    border-top: 1px solid rgba(0, 0, 0, 0.12);
}
body[data-hover="seams"] .preview a.entry:hover,
body[data-hover="seams"] .preview a.entry:focus-visible {
    transform: scale(1.012) translateY(-1px);
    box-shadow:
        0 1px 2px rgba(0, 0, 0, 0.06),
        0 6px 22px rgba(0, 0, 0, 0.09);
    z-index: 1;
    border-top-color: transparent;
}
body[data-hover="seams"] .preview a.entry:hover + a.entry,
body[data-hover="seams"] .preview a.entry:focus-visible + a.entry {
    border-top-color: transparent;
}
/* …and the same fade across a group boundary: when the LAST entry of a group
   is the hovered one, the seam it must not take with it belongs to the first
   entry of the NEXT group, with no + a.entry relationship to key on. :has()
   supplies it. Scoped to :last-of-type so hovering an earlier entry in the
   group doesn't clear a seam it isn't touching. */
body[data-hover="seams"] .preview .month-group:has(a.entry:last-of-type:hover) + .month-group a.entry:first-of-type,
body[data-hover="seams"] .preview .month-group:has(a.entry:last-of-type:focus-visible) + .month-group a.entry:first-of-type {
    border-top-color: transparent;
}

/* Lines — permanent hairlines between spines; the hovered entry lifts over
   them, seams stay put (they belong to the shelf, not the book). */
body[data-hover="lines"] .preview a.entry + a.entry {
    border-top: 1px solid rgba(0, 0, 0, 0.12);
}
/* group boundaries, as in Seams above (no hover fade in this mode) */
body[data-hover="lines"] .preview :where(.month-group + .month-group) a.entry:first-of-type {
    border-top: 1px solid rgba(0, 0, 0, 0.12);
}
body[data-hover="lines"] .preview a.entry:hover,
body[data-hover="lines"] .preview a.entry:focus-visible {
    transform: scale(1.012) translateY(-1px);
    box-shadow:
        0 1px 2px rgba(0, 0, 0, 0.06),
        0 6px 22px rgba(0, 0, 0, 0.09);
    z-index: 1;
}

/* Book — 3D pull-out: shared perspective on the stack; the hovered entry
   pivots from its right edge, left side swinging toward the reader, with a
   deeper shadow falling down-left. */
body[data-hover="book"] .group-entries {
    perspective: 1100px;
    perspective-origin: 50% 50%;
}
/* month-year mode puts a .month-group between the perspective element and the
   entries; preserve-3d stops that wrapper flattening them, so the pull-out
   keeps reading as depth rather than a flat rotate. */
body[data-hover="book"] .month-group { transform-style: preserve-3d; }
body[data-hover="book"] .preview a.entry {
    transform-origin: right center;
    transition-duration: 240ms;
}
body[data-hover="book"] .preview a.entry:hover,
body[data-hover="book"] .preview a.entry:focus-visible {
    transform: translateZ(26px) rotateY(4deg) rotateX(0.6deg);
    box-shadow:
        -2px 2px 4px rgba(0, 0, 0, 0.08),
        -14px 18px 38px rgba(0, 0, 0, 0.16);
    z-index: 1;
}

/* Prism — Eric's axonometric extrusion (style.css prism system, hover-only):
   flat at rest; on hover the entry extrudes into a rectangular solid. Depth
   is a registered property so the faces grow smoothly. Faces: bottom
   (skewX 45°) + right (skewY 45°); top face slides up-left by the depth. */
@property --pd {
    syntax: "<length>";
    inherits: true; /* the ::before/::after faces read the depth by inheritance */
    initial-value: 0px;
}
/* Shared prism geometry — the ::before/::after faces, transitions and opacity
   fade are identical across every prism* variant, so they key on the attribute
   PREFIX (^="prism"): prism, prism-ink, prism-wire, prism-hatch, prism-drive,
   prism-redline. Values that differ per variant (face fills, edge colors,
   hover depth, timing, card invert) live in the exact-match rules below, which
   share this block's specificity and therefore win by coming later in source
   order. Classic body[data-hover="prism"] takes the shared defaults unchanged. */
body[data-hover^="prism"] .preview a.entry {
    --pd: 0px;
    /* Face fill alphas, held as tokens so the recede-behind mode can swap them
       without restating `background` (which would clobber the per-variant
       Ink/Wire/Hatch/Redline fills). --pf-h = the horizontal face (::before),
       --pf-v = the vertical right face (::after). */
    --pf-h: 0.13;
    --pf-v: 0.22;
    border: 1px solid rgba(0, 0, 0, 0); /* reserved so hover adds no layout shift */
    transition: --pd 140ms ease-out, border-color 140ms ease-out,
        transform 140ms ease-out;
    transform: translate(calc(-1 * var(--pd)), calc(-1 * var(--pd)));
}
/* The suppressed sides are set via border-*-style (not `border-x: none`) so the
   shorthand's border-color survives on every side — Redline overrides
   border-color wholesale. */
body[data-hover^="prism"] .preview a.entry::before { /* bottom face */
    content: "";
    position: absolute;
    box-sizing: border-box;
    left: -1px; top: calc(100% + 1px); width: calc(100% + 2px); height: var(--pd);
    background: rgba(26, 24, 20, var(--pf-h, 0.13));
    border: 1px solid rgba(0, 0, 0, 0.5); border-top-style: none;
    transform: skewX(45deg);
    transform-origin: top left;
    opacity: 0; /* zero-size boxes still paint their borders — hide at rest */
    transition: opacity 140ms ease-out;
}
body[data-hover^="prism"] .preview a.entry::after { /* right face */
    content: "";
    position: absolute;
    box-sizing: border-box;
    top: -1px; left: calc(100% + 1px); height: calc(100% + 2px); width: var(--pd);
    background: rgba(26, 24, 20, var(--pf-v, 0.22));
    border: 1px solid rgba(0, 0, 0, 0.5);
    border-left-style: none; border-bottom-style: none;
    transform: skewY(45deg);
    transform-origin: top left;
    opacity: 0;
    transition: opacity 140ms ease-out;
}
body[data-hover^="prism"] .preview a.entry:hover::before,
body[data-hover^="prism"] .preview a.entry:hover::after,
body[data-hover^="prism"] .preview a.entry:focus-visible::before,
body[data-hover^="prism"] .preview a.entry:focus-visible::after {
    opacity: 1;
}
/* Hover depth = the lab-tunable base depth (--prism-depth, Hover Lab slider,
   12px when unset) times the entry's own weight (--pw, emitted per entry by
   layout-lab.js: 1 on majors, var(--pw-minor, 1) on minors, so the Hover Lab's
   "Minor depth ×" slider reaches minors without the lab knowing the markup). */
body[data-hover^="prism"] .preview a.entry:hover,
body[data-hover^="prism"] .preview a.entry:focus-visible {
    --pd: calc(var(--prism-depth, 12px) * var(--pw, 1));
    border-color: rgba(0, 0, 0, 0.5);
    z-index: 1;
}

/* Prism · Ink — solid black wedge; the card inverts to black at full hover. */
body[data-hover="prism-ink"] .preview a.entry {
    /* add background-color/color to the shared prism transition so the invert
       fades at the same 140ms ease-out as the extrusion */
    transition: --pd 140ms ease-out, border-color 140ms ease-out,
        transform 140ms ease-out, background-color 140ms ease-out,
        color 140ms ease-out;
}
body[data-hover="prism-ink"] .preview a.entry::before,
body[data-hover="prism-ink"] .preview a.entry::after {
    background: var(--color-text); /* solid fills; edges stay black as shared */
}
body[data-hover="prism-ink"] .preview a.entry:hover,
body[data-hover="prism-ink"] .preview a.entry:focus-visible {
    background: var(--color-text);
    color: #fff;
}
body[data-hover="prism-ink"] .preview a.entry:hover .title,
body[data-hover="prism-ink"] .preview a.entry:hover .minor-title,
body[data-hover="prism-ink"] .preview a.entry:hover .abstract,
body[data-hover="prism-ink"] .preview a.entry:hover .minor-desc,
body[data-hover="prism-ink"] .preview a.entry:hover .meta .author,
body[data-hover="prism-ink"] .preview a.entry:focus-visible .title,
body[data-hover="prism-ink"] .preview a.entry:focus-visible .minor-title,
body[data-hover="prism-ink"] .preview a.entry:focus-visible .abstract,
body[data-hover="prism-ink"] .preview a.entry:focus-visible .minor-desc,
body[data-hover="prism-ink"] .preview a.entry:focus-visible .meta .author {
    color: #fff; /* these set their own colors, so force them light on the dark card */
}
body[data-hover="prism-ink"] .preview a.entry:hover .meta .date,
body[data-hover="prism-ink"] .preview a.entry:focus-visible .meta .date {
    color: rgba(255, 255, 255, 0.6);
}

/* Prism · Wire — edges only; skeletal blueprint, card keeps its white bg. */
body[data-hover="prism-wire"] .preview a.entry::before,
body[data-hover="prism-wire"] .preview a.entry::after {
    background: transparent;
}

/* Prism · Hatch — engraved diagonal hatching on the faces. The gradients skew
   with their element, so pre-skew angles are chosen to land as consistent "\"
   hatching: the bottom face (skewX 45°) uses vertical lines (90deg gradient) —
   a vertical stripe direction (0,1) maps to (1,1); the right face (skewY 45°)
   uses horizontal lines (0deg gradient) — a horizontal stripe direction (1,0)
   also maps to (1,1). Both faces' final lines run the same way. */
body[data-hover="prism-hatch"] .preview a.entry::before {
    background: repeating-linear-gradient(90deg,
        rgba(0, 0, 0, 0.45) 0 1px, transparent 1px 4px);
}
body[data-hover="prism-hatch"] .preview a.entry::after {
    background: repeating-linear-gradient(0deg,
        rgba(0, 0, 0, 0.45) 0 1px, transparent 1px 4px);
}

/* Prism · Overdrive — twice the base depth, snappier (120ms), lands with an
   overshoot easing on depth and transform so it overshoots then settles. */
body[data-hover="prism-drive"] .preview a.entry {
    transition: --pd 120ms cubic-bezier(0.34, 1.56, 0.64, 1),
        border-color 120ms ease-out,
        transform 120ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
body[data-hover="prism-drive"] .preview a.entry::before,
body[data-hover="prism-drive"] .preview a.entry::after {
    transition: opacity 120ms ease-out; /* keep the face fade at the faster duration */
}
body[data-hover="prism-drive"] .preview a.entry:hover,
body[data-hover="prism-drive"] .preview a.entry:focus-visible {
    --pd: calc(var(--prism-depth, 12px) * 2 * var(--pw, 1));
}

/* Hard shadow — flat offset black slab, zine style. NOT prism geometry (the
   key deliberately does not start with "prism"): no faces. */
body[data-hover="hardshadow"] .preview a.entry {
    border: 1px solid transparent; /* reserved so hover adds no layout shift */
}
body[data-hover="hardshadow"] .preview a.entry:hover,
body[data-hover="hardshadow"] .preview a.entry:focus-visible {
    border: 1px solid var(--color-text);
    box-shadow: 8px 8px 0 0 var(--color-text);
    transform: translate(-4px, -4px);
    z-index: 1;
}

/* Prism · Redline — edges (card border + face borders) in the post's tag color
   via a per-entry --accent (set in layout-lab.js), with light accent tints on
   the faces. --accent falls back to --color-text on the standalone alt pages. */
body[data-hover="prism-redline"] .preview a.entry::before {
    background: color-mix(in srgb, var(--accent, var(--color-text)) 12%, white);
    border-color: var(--accent, var(--color-text));
}
body[data-hover="prism-redline"] .preview a.entry::after {
    background: color-mix(in srgb, var(--accent, var(--color-text)) 20%, white);
    border-color: var(--accent, var(--color-text));
}
body[data-hover="prism-redline"] .preview a.entry:hover,
body[data-hover="prism-redline"] .preview a.entry:focus-visible {
    border-color: var(--accent, var(--color-text));
}

/* Prism · recede behind (Hover Lab "Recede behind" → body.prism-behind). Keys on
   the attribute PREFIX, so it retargets every prism* variant at once. The solid
   extrudes DOWN-RIGHT off the bottom and right edges — the same direction as
   pop-out — and the difference is that the card itself does NOT translate: the
   depth grows away from a card that stays put, so the body reads as sinking
   back into the page instead of lifting off it.

   Because the direction matches, the FACE GEOMETRY IS THE SHARED GEOMETRY: the
   ::before bottom face at the card's bottom edge sheering down-right, the
   ::after right face sheering down, and the single-stroked shared diagonal off
   the bottom-right corner (::before keeps border-right, ::after drops
   border-bottom) all come from body[data-hover^="prism"] untouched. Nothing
   here repositions, re-skews or re-borders the faces; overriding any of that
   would be the up-right variant, which review rejected.

   So this block is only the two things that are actually mode-specific:
     transform: none — cancels the shared hover translate(-d, -d). This IS the
       recede; with the faces fixed to the card's bottom/right edges the solid
       grows down-right out of a stationary card. z-index/border-color on hover
       and the ::before/::after opacity fade all still come from the shared
       rules.
     the swapped fill alphas — pop-out lights the vertical right face darker
       (--pf-v 0.22) and the horizontal face lighter (--pf-h 0.13); receding
       swaps them, so the two modes stay visually distinct even though they
       share a silhouette. Held as tokens precisely so the swap doesn't restate
       `background` and clobber the Ink/Wire/Hatch/Redline fills. */
body.prism-behind[data-hover^="prism"] .preview a.entry {
    --pf-h: 0.22; /* horizontal bottom face — pop-out has 0.13 */
    --pf-v: 0.13; /* right face — pop-out has 0.22 */
    transform: none; /* card stays put; the hover z-index/border still apply */
}

/* Tint — flat background wash, no motion. */
body[data-hover="tint"] .preview a.entry:hover,
body[data-hover="tint"] .preview a.entry:focus-visible {
    background: rgba(0, 0, 0, 0.035);
}

/* minor: metadata baseline sits on the first-line baseline of the title.
   Top/bottom only — the horizontal 20px card bleed comes from .preview a.entry
   and must survive, so these are longhands rather than a padding shorthand. */
.entry.minor {
    align-items: baseline;
    padding-top: var(--minor-pad);
    padding-bottom: var(--minor-pad);
}

/* major: figures and title tops flush */
.entry.major {
    align-items: start;
    padding: 16px 0;
}

/* pin the meta line to the row bottom so the last text line ends flush with
   the image bottom; the abstract→meta gap grows past 20px only when the
   image is the taller column */
.entry.major .col-right {
    align-self: stretch;
    display: flex;
    flex-direction: column;
}
.entry.major .meta { margin-top: auto; }

.col-left {
    text-align: right;
    min-width: 0;
}

.col-right { min-width: 0; }

/* --------------------------------------------------------------------------
   Minor entries
   -------------------------------------------------------------------------- */
.minor-title {
    font-family: var(--font-display);
    font-style: italic;
    font-weight: 400;
    font-size: var(--size-title-minor);
    line-height: 1.4;
    color: var(--color-text);
}

/* --------------------------------------------------------------------------
   Major entries
   -------------------------------------------------------------------------- */
.figures {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 12px;
}
.figures img, .figures video {
    display: block;
    width: 305px;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    border-radius: 4px;
}
/* Layout Lab "Outline figures" toggle */
body.img-outline .figures img, body.img-outline .figures video {
    outline: 1px solid var(--color-text);
    outline-offset: -1px;
}
/* Layout Lab "Figures: card" — white plate with inset content, per the
   outline-reference screenshot */
body.img-card .figures img, body.img-card .figures video {
    box-sizing: border-box;
    padding: 12px;
    background: var(--color-bg);
    border-radius: 4px;
    box-shadow:
        inset -1px 0 0 0 #000,          /* right inside keyline */
        inset 0 -1px 0 0 #000,          /* bottom inside keyline */
        2px 2px 4px 0 rgba(0, 0, 0, 0.25); /* Figma drop shadow */
}

.title {
    font-family: var(--font-display);
    font-weight: var(--font-display-weight);
    font-size: var(--size-title-major);
    line-height: 1.2;
    color: var(--color-text);
    margin: 0 0 12px;
    /* trim the line-box headroom so the visual top of the letters (cap
       height) is the box top — keeps figure tops flush with title tops */
    text-box-trim: trim-start;
    text-box-edge: cap alphabetic;
}
.abstract {
    font-family: var(--font-body);
    font-size: var(--size-abstract);
    line-height: 1.1;
    color: var(--color-text);
    margin: 0 0 20px;
    max-width: 33em;
}

/* --------------------------------------------------------------------------
   Meta line — mono; author bold, tag colored, date faint gray
   -------------------------------------------------------------------------- */
.meta {
    font-family: var(--font-mono);
    font-size: var(--size-meta);
    line-height: 1.5;
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    column-gap: 16px;
    row-gap: 8px;
}
.meta .author {
    font-weight: 700;
    color: var(--color-text);
}
.meta .tag { font-weight: 700; }


.venue {
    font-weight: 700;
    color: var(--venue-color, var(--color-text));
}

/* Venue style variants (Layout Lab "Venue" picker). Keyed on .venue itself so
   they work both in the meta flex row (preview.css) and inside the .venue-line
   wrapper (alt.css). --accent is the per-entry tag color set on each entry
   anchor by layout-lab.js; gold fallback covers pages that don't set it.
   --venue-color is the Layout Lab color-picker override: when set it wins for
   every variant, when unset each variant falls back to its usual color logic. */
.venue-italic .venue {
    font-style: italic;
    font-weight: 400;
}

/* Box family — one shared look (accent-colored 1px sharp box, currentColor
   border so the text color drives the border), with per-variant overrides for
   rounding, small-caps and fixed 10px sizing below. */
.venue-box .venue,
.venue-box-round .venue,
.venue-box-sc .venue,
.venue-box-10 .venue,
.venue-box-round-10 .venue {
    font-weight: 400;
    color: var(--venue-color, var(--color-text));
    border: 0.75px solid currentColor;
    padding: 1px 6px;
    border-radius: 0;
    line-height: 1.2;
}
.venue-box-round .venue,
.venue-box-round-10 .venue { border-radius: 2px; }
/* box-sc: the box look plus venue-smallcaps' uppercase treatment. */
.venue-box-sc .venue {
    text-transform: uppercase;
    font-size: 0.85em;
    letter-spacing: 0.08em;
}
.venue-box-10 .venue,
.venue-box-round-10 .venue { font-size: 10px; }
/* Mono meta line lacks reliable small-caps glyphs, so render via uppercase +
   0.85em rather than trusting font-variant-caps. */
.venue-smallcaps .venue {
    font-weight: 400;
    color: var(--venue-color, var(--color-text));
    text-transform: uppercase;
    font-size: 0.85em;
    letter-spacing: 0.08em;
}
.venue-tint .venue {
    font-weight: 400;
    color: var(--venue-color, var(--color-text));
    background: color-mix(in srgb, var(--venue-color, var(--color-text)) 12%, white);
    padding: 1px 6px;
    border-radius: 2px;
    line-height: 1.2;
}

/* --------------------------------------------------------------------------
   Narrow viewports — keep it usable without changing the desktop design intent
   -------------------------------------------------------------------------- */
@media (max-width: 1140px) {
    .site-header-inner,
    .preview { padding-left: 24px; padding-right: 24px; }
    /* no gutter to live in: month labels come back into the flow as section
       headings — clear air above (separating from the previous month's last
       entry) and a hairline underneath to mark entering the section */
    .month-label {
        position: static;
        text-align: left;
        margin: 0 0 0.9rem;
        padding-bottom: 0.35rem;
        border-bottom: 1px solid rgba(0, 0, 0, 0.12);
    }
    .month-group + .month-group .month-label { margin-top: 2.4rem; }
    /* dates survive the gutter's death inline: a small faint line above each
       entry's title (full grid row, so the two-column entry grid is intact) */
    .entry-date {
        position: static;
        grid-column: 1 / -1;
        text-align: left;
        margin-bottom: 0.1rem;
    }
    .post-list { margin-top: 7rem; }
}

@media (max-width: 720px) {
    .preview a.entry {
        grid-template-columns: 1fr;
        row-gap: 0.9rem;
    }
    .col-left { text-align: left; }
    .figures { justify-content: flex-start; }
}

/* ------------------------------------------------------------------
   Conditioned wordmark (wordmark.js) — ported verbatim from style.css
   so the index masthead shares the posts' prism letter hover.
   ------------------------------------------------------------------ */
/* The conditioned wordmark (wordmark.js): hovering the home link turns
   "Simplex" into a categorical distribution — each letter fronts a prism in
   the index's projection (same recipe: edge 0.5, faces 0.13/0.22,
   extrusion down-right) whose depth follows the pointer. Letters are static
   and unspread; only the faces behind them grow. The transparent border is
   compensated by a negative margin so wrapping the letters never widens the
   masthead. */
.logo-text .wm {
    display: inline-flex;
    gap: 0;
    transition: gap 260ms cubic-bezier(.25, .6, .25, 1);
}
/* 4px gap minus the slabs' -1px border-compensation margins = 2px of real
   air between open slabs. At 2px the adjacent 1px borders TOUCHED (net 0),
   landing on fractional positions, so every seam rendered differently —
   doubled lines, slivers, "edges that don't line up". */
.logo-text .wm.open { gap: 4px; }
.logo-text .wm-lt {
    --d: 0px;
    position: relative;
    /* a slab, not an outlined glyph: the box is taller than the type with the
       letter centered in it (identity-page proportions, slightly tightened) */
    display: inline-flex; align-items: center; justify-content: center;
    height: 1.3em;
    /* transparent at rest: with the boxes stacked right-over-left (for the
       down-right view), an opaque box would shave the previous glyph's
       overhang (Cardo's S). Backgrounds are only needed while the slabs have
       volume — .solid, managed by wordmark.js — when the open-state spread
       gives every glyph room anyway. */
    background: transparent;
    border: 1px solid transparent;
    margin: -1px;
    /* the slab's side air arrives with the spread — at rest the letters keep
       normal text spacing */
    transition: border-color 160ms, padding 260ms cubic-bezier(.25, .6, .25, 1);
}
.logo-text .wm.open .wm-lt { padding: 0 1px; } /* integer px: em padding (1.2px at 20px) put borders on half-pixels */
.logo-text .wm.open .wm-lt { border-color: rgba(0, 0, 0, 0.5); }
.logo-text .wm.solid .wm-lt { background: var(--color-bg); }
.logo-text .wm-lt::before, .logo-text .wm-lt::after {
    content: ""; position: absolute; pointer-events: none;
    /* explicit: preview.css's universal box-sizing rule is bare `*`, which
       never matches pseudo-elements — content-box faces grow 2px past the
       stated size from their own borders and protrude past the seam */
    box-sizing: border-box;
}
/* Faces anchor to the BORDER box: percentage offsets on abspos children
   resolve against the padding box, which sits 1px inside the slab's border —
   that shifted each face a pixel down/right of the front face's outer edges
   (the right face visibly "too low"). The 1px terms below are the border. */
.logo-text .wm-lt::before {   /* bottom face */
    left: -1px; top: calc(100% + 1px); width: calc(100% + 2px); height: var(--d);
    background: rgba(26, 24, 20, 0.13);
    border: 1px solid rgba(0, 0, 0, 0.5); border-top: none;
    transform: skewX(45deg); transform-origin: top left;
}
.logo-text .wm-lt::after {    /* right face */
    left: calc(100% + 1px); top: -1px; width: var(--d); height: calc(100% + 2px);
    background: rgba(26, 24, 20, 0.22);
    border: 1px solid rgba(0, 0, 0, 0.5); border-left: none;
    transform: skewY(45deg); transform-origin: top left;
}
.logo-text .wm-lt.flat::before, .logo-text .wm-lt.flat::after { display: none; }

/* Venue style "hidden" (Layout Lab) — with the type chips retired, entries can
   run even quieter: author · date only. Hides both the meta-row span and the
   alt layouts' own-line wrapper. */
body.venue-hidden .venue,
body.venue-hidden .venue-line { display: none; }

/* --------------------------------------------------------------------------
   Masthead lockup (Loren, 2026-08-30). The logo is a CONTAINER with two
   links — mark + "Belief Updates" go home; the tagline's "Simplex" goes to
   simplexaisafety.com (anchors can't nest, hence the structure). The tagline
   ("from/by Simplex") shows only in the lockup wordmark styles:
     --wordmark-tagline        none | block (shipped default)
     --wordmark-conn-from/-by  which connective shows (italic)
     --wordmark-simplex-weight 400 | 700
   Line 1 keeps the single-line styles' tokens, so all previous wordmark
   options are untouched.
   -------------------------------------------------------------------------- */
.site-header .logo .logo-home,
.site-header .logo .wm-line1 {
    color: inherit;
    text-decoration: none;
}
.site-header .logo .logo-text {
    display: flex;
    flex-direction: column;
    justify-content: center;
}
.site-header .wm-tagline {
    display: var(--wordmark-tagline, none);
    font-family: var(--font-wordmark);
    font-size: 0.62em;
    line-height: 1.35;
    color: var(--color-text);
}
.site-header .wm-tagline .wm-conn { font-style: italic; }
.site-header .wm-tagline .wm-conn-from { display: var(--wordmark-conn-from, inline); }
.site-header .wm-tagline .wm-conn-by { display: var(--wordmark-conn-by, none); }
.site-header .wm-tagline .wm-simplex {
    color: inherit;
    text-decoration: none;
    font-weight: var(--wordmark-simplex-weight, 400); font-style: var(--wordmark-simplex-style, normal);
    margin-left: 0.28em;
}
/* .wm-simplex-active: applied by logo.js while the hovered mark sits at the
   true geometry — the tagline echoes the hover it is momentarily linked to */
.site-header .wm-tagline .wm-simplex:hover,
.site-header .wm-tagline .wm-simplex.wm-simplex-active { text-decoration: underline dotted; text-underline-offset: 3px; text-decoration-thickness: 1px; }


/* --------------------------------------------------------------------------
   Mobile: dev chrome (labs + drift badge) is desktop tooling — on a phone the
   fixed buttons sit on top of content and there's no room to use the panels
   anyway. !important outranks the labs' injected styles. Also: comfortable
   nav tap targets.
   -------------------------------------------------------------------------- */
@media (max-width: 720px) {
    #fontlab, #sizelab, #hoverlab, #layoutlab, #logolab, #captionlab, #labdrift, #postfontlab, #postsizelab, #postcolorlab, #postlayoutlab { display: none !important; }
    .site-header nav a { padding: 6px 0; }
}
