/* ============ TOKENS ============ */
:root{
  --parchment:#F7F1E1;
  --parchment-2:#EFE5C7;
  --parchment-3:#E4D6AC;
  /* blush = the current parchment tinted with red, not an independently
     sampled gray — keeps the foldable sections tied to whatever the base
     background is instead of drifting out of sync with it. Hex is a static
     fallback for browsers without color-mix(); the color-mix() line below
     overrides it and stays correct if --parchment ever changes again. */
  --blush:#E3C2B3;
  --blush: color-mix(in srgb, var(--parchment) 75%, var(--maroon-bright) 25%);
  --blush-2:#DBB0A1;
  --blush-2: color-mix(in srgb, var(--parchment) 65%, var(--maroon-bright) 35%);
  --blush-border:#B96A57;
  --photo-border: var(--maroon-bright);
  --maroon:#7A241D;
  --maroon-bright:#A6362A;
  --maroon-deep:#43110F;
  --rust:#A8571E;
  --rust-bright:#C96A2E;
  --ink:#2B1D14;
  --ink-muted:#5B4A3A;
  --ink-faint:#6E5A47;
  --line: rgba(122,36,29,0.30);
  --line-strong: rgba(122,36,29,0.58);

  --font-display:'Cinzel','Trajan Pro',Georgia,serif;
  --font-body:'Source Serif 4',Georgia,'Times New Roman',serif;
  --font-mono:'JetBrains Mono','Courier New',monospace;

  --measure:66ch;
  --wide:1180px;
}

/* ============ RESET ============ */
*,*::before,*::after{box-sizing:border-box;}
html{scroll-behavior:smooth;}
@media (prefers-reduced-motion: reduce){ html{scroll-behavior:auto;} }
body{
  margin:0;
  background:var(--parchment);
  color:var(--ink);
  font-family:var(--font-body);
  font-size:1.05rem;
  line-height:1.65;
  -webkit-font-smoothing:antialiased;
}
img,svg{max-width:100%;display:block;}
a{color:var(--maroon);}
a:focus-visible, button:focus-visible, .navlink:focus-visible, summary:focus-visible{
  outline:2px solid var(--maroon-bright);
  outline-offset:3px;
}
h1,h2,h3,h4{
  font-family:var(--font-display);
  font-weight:700;
  color:var(--ink);
  text-wrap:balance;
  margin:0;
}
p{margin:0 0 1.1em 0;}
ul{margin:0;padding:0;list-style:none;}
.container{max-width:var(--wide);margin:0 auto;padding:0 clamp(1.25rem,4vw,3rem);}
.prose{max-width:var(--measure);}

/* subtle background texture: faint diagonal grain across whole page, like aged paper */
.grain{
  position:fixed; inset:0; pointer-events:none; z-index:0; opacity:.045; mix-blend-mode:multiply;
  background-image:repeating-linear-gradient(135deg, var(--ink-faint) 0 1px, transparent 1px 3px);
}

/* ============ RIBBON DIVIDER (castellated red band, used between major sections) ============ */
.hero, .page-hero, section.plate:not(:last-of-type){ position:relative; }
.hero::after, .page-hero::after, section.plate:not(:last-of-type)::after{
  content:''; position:absolute; left:0; right:0; bottom:0; height:16px;
  background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2222%22%20height%3D%2216%22%3E%3Crect%20x%3D%220%22%20y%3D%229%22%20width%3D%2222%22%20height%3D%227%22%20fill%3D%22%237A241D%22/%3E%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%2211%22%20height%3D%2216%22%20fill%3D%22%237A241D%22/%3E%3C/svg%3E");
  background-repeat: repeat-x;
  background-size: 22px 16px;
  background-position: left bottom;
}

/* ============ NAV ============ */
header.site-nav{
  position:sticky; top:0; z-index:50;
  background:rgba(247,241,225,0.94);
  backdrop-filter:blur(6px);
  border-bottom:1px solid var(--line-strong);
}
.nav-row{
  display:flex; align-items:center; justify-content:space-between;
  padding:0.85rem clamp(1.25rem,4vw,3rem);
  gap:1rem; flex-wrap:wrap;
}
.brand{
  display:flex; align-items:center; gap:.6rem;
  font-family:var(--font-mono); font-size:.85rem; letter-spacing:.12em;
  color:var(--ink); text-decoration:none;
}
.brand .gear-icon{width:1.1rem;height:1.1rem;color:var(--maroon);}
.navlinks{display:flex; gap:1.4rem; flex-wrap:wrap; margin:0; padding:0;}
.navlink{
  font-family:var(--font-mono); font-size:.78rem; letter-spacing:.1em; text-transform:uppercase;
  color:var(--ink-muted); text-decoration:none; padding-bottom:3px; border-bottom:1px solid transparent;
  transition:color .2s ease, border-color .2s ease;
}
.navlink:hover, .navlink.active{ color:var(--maroon); border-color:var(--maroon); }

/* ============ HERO ============ */
.hero{
  position:relative; overflow:hidden;
  padding:clamp(4rem,10vw,7rem) 0 clamp(3rem,7vw,5rem);
}
.hero-grid{
  display:grid; grid-template-columns: 1.3fr 0.9fr; gap:2.5rem; align-items:center;
}
@media (max-width:860px){ .hero-grid{ grid-template-columns:1fr; } .hero-gear-wrap{ order:-1; height:220px; } }
.eyebrow{
  font-family:var(--font-mono); font-size:.78rem; letter-spacing:.16em; text-transform:uppercase;
  color:var(--maroon); margin:0 0 1rem 0; display:flex; align-items:center; gap:.6rem;
}
.eyebrow::before{content:''; width:1.4rem; height:1px; background:var(--maroon);}
.hero h1{
  font-size:clamp(2.6rem,6.5vw,4.6rem); line-height:1.02; letter-spacing:.01em;
}
.hero .subhead{
  font-family:var(--font-body); font-style:italic; color:var(--maroon-bright);
  font-size:clamp(1.1rem,2.2vw,1.35rem); margin:1.1rem 0 1.3rem 0; max-width:42ch; line-height:1.4;
}
.hero .lede{margin-top:1.3rem; max-width:56ch; color:var(--ink); font-size:1.05rem;}
.hero-ctas{display:flex; gap:1rem; flex-wrap:wrap; margin-top:1.6rem;}
.btn{
  font-family:var(--font-mono); font-size:.8rem; letter-spacing:.08em; text-transform:uppercase;
  padding:.85rem 1.4rem; text-decoration:none; border:1px solid var(--maroon); color:var(--ink);
  display:inline-flex; align-items:center; gap:.5rem; transition:all .2s ease; background:transparent;
  cursor:pointer;
}
.btn:hover{ background:var(--maroon); color:var(--parchment); }
.btn.ghost{ border-color:var(--line-strong); color:var(--ink-muted); }
.btn.ghost:hover{ border-color:var(--maroon-bright); color:var(--maroon-bright); background:transparent; }
.hero-note{
  margin-top:1.4rem; font-family:var(--font-mono); font-size:.78rem; color:var(--ink-faint);
  letter-spacing:.03em;
}
.hero-gear-wrap{ position:relative; display:flex; align-items:center; justify-content:center; height:340px; }
.hero-photo-frame{
  position:relative; width:100%; max-width:300px; aspect-ratio: 3 / 3.4;
}
.hero-photo-frame img{
  width:100%; height:100%; object-fit:cover; object-position:center 22%; display:block;
  border:2px solid var(--photo-border);
}
/* thin red frame applied to every real photo on the site (not placeholder
   media-slots, not video) */
.photo-border{ border:2px solid var(--photo-border); }
.status-strip{
  margin-top:clamp(2.5rem,5vw,4rem);
  border-top:1px solid var(--line); padding-top:.9rem;
  font-family:var(--font-mono); font-size:.72rem; letter-spacing:.1em; text-transform:uppercase;
  color:var(--ink-faint); display:flex; flex-wrap:wrap; gap:.4rem 1.6rem;
}
.status-strip span b{color:var(--maroon); font-weight:600;}
.doc-strip{
  margin-top:clamp(2.5rem,5vw,4rem); border-top:1px solid var(--line); padding-top:1.1rem;
  display:flex; flex-wrap:wrap; gap:.7rem;
}
.doc-strip a{
  display:inline-flex; align-items:center; gap:.45rem;
  font-family:var(--font-mono); font-size:.74rem; letter-spacing:.08em; text-transform:uppercase;
  color:var(--maroon); border:1px solid var(--line-strong); padding:.55rem .9rem; text-decoration:none;
  transition:background .15s, color .15s, border-color .15s;
}
.doc-strip a:hover, .doc-strip a:focus-visible{ background:var(--maroon); color:var(--parchment); border-color:var(--maroon); }
.doc-strip a:last-child{ text-transform:none; letter-spacing:.02em; }

/* ============ PAGE HEADER (for non-home pages) ============ */
.page-hero{
  padding:clamp(3rem,7vw,5rem) 0 clamp(2rem,5vw,3rem);
}
.page-hero h1{ font-size:clamp(2.2rem,5.5vw,3.4rem); }
.page-hero .plate-intro{ margin-top:1rem; }
.back-link{
  display:inline-flex; align-items:center; gap:.4rem; font-family:var(--font-mono); font-size:.76rem;
  letter-spacing:.08em; text-transform:uppercase; color:var(--ink-faint); text-decoration:none; margin-bottom:1.4rem;
}
.back-link:hover{ color:var(--maroon); }

/* ============ GEAR (generated) ============ */
.gear{ position:relative; }
.gear svg{ width:100%; height:100%; overflow:visible; }
.gear .gear-rotor{ transform-origin:100px 100px; }
@media (prefers-reduced-motion: no-preference){
  .gear.spin .gear-rotor{ animation:spin 70s linear infinite; }
  .gear.spin-rev .gear-rotor{ animation:spin-rev 54s linear infinite; }
}
@keyframes spin{ to{ transform:rotate(360deg); } }
@keyframes spin-rev{ to{ transform:rotate(-360deg); } }
.gear-poly{ fill:none; stroke:var(--maroon); stroke-width:2; opacity:.6; }
.gear-hub{ fill:none; stroke:var(--maroon); stroke-width:1.4; opacity:.75; }
.gear-hub-hole{ fill:var(--parchment); stroke:var(--maroon); stroke-width:1; opacity:.75;}

/* ============ SECTIONS / PLATES ============ */
section.plate{
  padding:clamp(3.5rem,8vw,6rem) 0; position:relative;
}
.plate-head{ margin-bottom:2.6rem; }
.plate-head h2{ font-size:clamp(1.9rem,4vw,2.6rem); }
.plate-intro{ color:var(--ink-muted); max-width:60ch; margin-top:.8rem; }

/* ============ STORY ============ */
.story-body p{ font-size:1.08rem; }
.story-body a{ text-decoration:underline; text-decoration-color:var(--line-strong); text-underline-offset:3px; }
.story-body a:hover{ text-decoration-color:var(--maroon-bright); }
.support-grid.single{ grid-template-columns:1fr; }
.story-timeline .tl-entry > div:last-child{ max-width:var(--measure); }
.story-timeline .tl-entry p + p{ margin-top:1rem; }
.story-close{ max-width:var(--measure); margin-top:2.4rem; }
.story-summary{ display:none; }
.story-timeline.collapsed .story-summary{ display:block; color:var(--ink-muted); }
.story-timeline.collapsed .story-full{ display:none; }
.story-timeline.collapsed .tl-entry{ padding:1.3rem 0; }
.story-toggle{
  margin-top:1.4rem; background:none; border:1px solid var(--line-strong); color:var(--ink-muted);
  font-family:var(--font-mono); font-size:.74rem; letter-spacing:.1em; text-transform:uppercase;
  padding:.6rem 1rem; cursor:pointer;
}
.story-toggle:hover, .story-toggle:focus-visible{ border-color:var(--maroon-bright); color:var(--maroon-bright); }
blockquote.thesis{
  margin:2rem 0; padding:1.4rem 1.6rem; background:var(--maroon-deep);
  border-left:5px solid var(--maroon-bright);
  font-family:var(--font-display); font-size:1.15rem; color:var(--parchment); font-weight:600;
}

/* ============ WORK TIMELINE ============ */
.timeline{ display:flex; flex-direction:column; gap:0; border-top:1px solid var(--line); }
.tl-entry{ display:grid; grid-template-columns:220px 1fr; gap:2rem; padding:2rem 0; border-bottom:1px solid var(--line); }
@media (max-width:700px){ .tl-entry{ grid-template-columns:1fr; gap:.6rem; } }
.tl-meta{ font-family:var(--font-mono); font-size:.78rem; color:var(--ink-faint); letter-spacing:.03em; }
.tl-meta .tl-dates{ color:var(--maroon); display:block; margin-bottom:.35rem; }
.tl-role{ font-family:var(--font-display); font-size:1.3rem; margin-bottom:.2rem; }
.tl-org{ color:var(--ink-muted); font-style:italic; margin-bottom:.9rem; font-family:var(--font-body); }
.tl-list{ display:flex; flex-direction:column; gap:.5rem; }
.tl-list li{ position:relative; padding-left:1.1rem; color:var(--ink); }
.tl-list li::before{ content:'—'; position:absolute; left:0; color:var(--maroon); }

/* ============ STAT ROW ============ */
.stat-row{ display:grid; grid-template-columns:repeat(auto-fit,minmax(180px,1fr)); gap:1px; background:var(--line-strong); border:1px solid var(--line-strong); margin:2.2rem 0; }
.stat{ background:var(--parchment-2); padding:1.3rem 1.4rem; }
.stat .stat-num{ font-family:var(--font-mono); font-variant-numeric:tabular-nums; font-size:1.9rem; color:var(--maroon); font-weight:700; line-height:1; }
.stat .stat-label{ font-family:var(--font-mono); font-size:.68rem; letter-spacing:.1em; text-transform:uppercase; color:var(--ink-faint); margin-top:.5rem; }
.stat .stat-sub{ font-size:.8rem; color:var(--ink-muted); margin-top:.3rem; font-family:var(--font-body); }

/* ============ MEDIA SLOT ============ */
.media-slot{
  border:1px dashed var(--line-strong);
  background:
    repeating-linear-gradient(135deg, rgba(122,36,29,0.055) 0 10px, transparent 10px 20px),
    var(--parchment-3);
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:.5rem;
  padding:1.4rem 1rem; min-height:120px; text-align:center;
}
.media-slot .icon{ width:1.6rem; height:1.6rem; color:var(--maroon); opacity:.85; }
.media-slot .slot-type{ font-family:var(--font-mono); font-size:.68rem; letter-spacing:.12em; text-transform:uppercase; color:var(--maroon); }
.media-slot .slot-desc{ font-family:var(--font-mono); font-size:.72rem; color:var(--ink-faint); max-width:22ch; }
.media-grid{ display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:.9rem; margin:1.3rem 0 2rem; }

/* ============ INLINE FIGURES (real evidence, placed in the phase-body
   next to the claim it backs) ============
   Distinct from .media-slot above: those are placeholders for media not
   yet acquired. These are the real photo/video, dropped directly under or
   beside the specific sentence it proves, textbook/figure style, rather
   than bundled into an end-of-phase gallery. Photos get the site's red
   photo-border; video does not (see the .photo-border comment above --
   the border marks a still photo specifically), so it reads as motion
   against a plain frame instead. */
.inline-figure{ margin:1.3rem 0; max-width:520px; }
.inline-figure img,
.inline-figure video{ width:100%; height:auto; display:block; }
.inline-figure img{ border:2px solid var(--photo-border); }
.inline-figure video{ border:1px solid var(--line-strong); }
.inline-figure figcaption{
  margin-top:.5rem; font-family:var(--font-mono); font-size:.72rem; line-height:1.5;
  color:var(--ink-faint); letter-spacing:.01em;
}
/* floated variant -- text reflows beside it, same mechanism as
   .gen-cover-drawing-float on the generation covers above. For a figure
   that should run alongside a couple of paragraphs rather than break the
   column (an establishing shot, a small supporting thumbnail). */
.inline-figure.float-right{ float:right; clear:right; margin:.2rem 0 1rem 1.4rem; }
.inline-figure.float-right.small{ max-width:200px; }
@media (max-width:640px){
  .inline-figure.float-right{ float:none; max-width:380px; margin:1.3rem auto; }
}
/* wide variant -- for a figure that needs to breathe more than the
   default text-column width allows (a multi-panel comparison image, an
   iteration filmstrip). Not floated -- it's meant to sit full-width in
   its own block, same as a plain .inline-figure but wider. */
.inline-figure.wide{ max-width:100%; }
/* interactive 3D render -- an iframe of a drag-to-rotate turntable, kept
   at the render's 16:9 so the frames fill it without letterboxing. */
.inline-figure .render-frame{
  width:100%; aspect-ratio:16/9; display:block; border:1px solid var(--line-strong); background:#000;
}
.render-actions{ margin-top:.7rem; }
.render-actions .btn{ padding:.55rem 1rem; font-size:.85rem; }
/* two small figures side by side -- a fit-check pair, a before/after --
   collapsing to one column on narrow screens rather than squeezing. */
.dual-figure{ display:grid; grid-template-columns:1fr 1fr; gap:1.1rem; margin:1.3rem 0; }
.dual-figure .inline-figure{ max-width:none; margin:0; }
@media (max-width:640px){
  .dual-figure{ grid-template-columns:1fr; }
}
/* a two-video comparison where the clips don't share an aspect ratio (e.g.
   one landscape, one portrait) -- .dual-figure's equal-width grid would
   squash one clip's height way down relative to the other, so this matches
   HEIGHT instead and lets width follow each clip's own aspect. Falls back
   to width-matched/stacked on narrow screens where a shared height would
   make the wider clip overflow. */
.video-compare{
  display:flex; align-items:flex-start; justify-content:center;
  gap:1.4rem; flex-wrap:wrap; margin:1.3rem 0;
}
.video-compare-item{ display:flex; flex-direction:column; align-items:center; gap:.55rem; }
.video-compare-item video{
  height:clamp(230px,34vw,400px); width:auto; max-width:100%;
  border:2px solid var(--photo-border); display:block;
}
.video-compare-label{
  font-family:var(--font-mono); font-size:.7rem; letter-spacing:.07em; text-transform:uppercase;
  color:var(--maroon); text-align:center; margin:0;
}
.video-compare-note{
  font-family:var(--font-mono); font-size:.78rem; line-height:1.5; color:var(--ink-faint);
  text-align:center; max-width:62ch; margin:.9rem auto 0;
}
@media (max-width:640px){
  .video-compare{ flex-direction:column; align-items:center; }
  .video-compare-item video{ height:auto; width:100%; max-width:320px; }
}

/* ============ BADGES ============ */
.badge{
  display:inline-flex; align-items:center; gap:.4rem; font-family:var(--font-mono); font-size:.68rem;
  letter-spacing:.1em; text-transform:uppercase; padding:.3rem .6rem; border:1px solid currentColor;
}
.badge.active{ color:var(--maroon); background:rgba(122,36,29,0.09); }
.badge.archived{ color:var(--ink-faint); }
.badge.ongoing{ color:var(--rust-bright); background:rgba(168,87,30,0.12); }
.badge-dot{ width:.4rem; height:.4rem; border-radius:50%; background:currentColor; }

/* ============ FLAGSHIP PROJECT ============ */
.flagship{ border:1px solid var(--line-strong); background:var(--parchment-2); padding:clamp(1.6rem,4vw,2.6rem); }
.flagship-head{ display:flex; flex-wrap:wrap; align-items:baseline; gap:.9rem 1.2rem; margin-bottom:.6rem; }
.flagship-head h3{ font-size:clamp(1.6rem,3vw,2.1rem); }
.flagship-role{ font-family:var(--font-mono); font-size:.82rem; color:var(--ink-muted); margin-bottom:1.6rem; }
/* the question that opens the whole flagship section — same italic/
   maroon-bright treatment as .closing-note below, deliberately, so the
   two read as a matched pair: the question up here, the answer down
   there once Mark III's cover has been read. */
.flagship-thesis{
  font-family:var(--font-body); font-style:italic; color:var(--maroon-bright);
  font-size:clamp(1.05rem,2vw,1.22rem); max-width:64ch; line-height:1.5; margin:0 0 1.7rem 0;
}
.context-line{ font-style:italic; color:var(--ink-faint); font-size:.92rem; border-left:2px solid var(--line-strong); padding-left:.9rem; margin:0 0 2rem 0; }
/* names the wrong-guess-then-real-cause pattern once, up top, so the reader
   is primed to notice it in the cards below rather than needing every card
   to spell it out. Deliberately quieter than .flagship-thesis -- it's a
   reading hint, not a second claim competing with the research question. */
.flagship-pattern{
  font-family:var(--font-mono); font-size:.78rem; color:var(--ink-faint);
  letter-spacing:.01em; max-width:60ch; line-height:1.6; margin:-.9rem 0 1.7rem 0;
}

.phase{ padding:2rem 0; border-top:1px solid var(--line); }
.phase-head{ display:flex; align-items:center; gap:1rem; margin-bottom:.9rem; }
.phase-num{
  font-family:var(--font-display); font-size:1rem; color:var(--maroon); border:1px solid var(--maroon);
  width:2.2rem; height:2.2rem; display:flex; align-items:center; justify-content:center; flex-shrink:0;
}
.phase-head h4{ font-size:1.25rem; }
.phase-body{ color:var(--ink); }
.phase-body .sub{ margin:1.1rem 0 .5rem; font-family:var(--font-mono); font-size:.75rem; letter-spacing:.06em; text-transform:uppercase; color:var(--maroon); }
.credit-note{ font-size:.88rem; color:var(--ink-muted); font-style:italic; margin-top:.6rem; }

.support-module{ margin-top:1rem; border-top:1px solid var(--line); padding-top:2rem; }
.support-module h4{ font-size:1.05rem; font-family:var(--font-mono); text-transform:uppercase; letter-spacing:.08em; color:var(--maroon); margin-bottom:1.2rem; }
.support-grid{ display:grid; grid-template-columns:1.1fr 1fr; gap:1.6rem; align-items:start; }
@media (max-width:760px){ .support-grid{ grid-template-columns:1fr; } }
.support-list{ display:flex; flex-direction:column; gap:1rem; }
.support-list li{ padding-left:1.1rem; position:relative; font-size:.96rem; color:var(--ink); }
.support-list li::before{ content:'▸'; position:absolute; left:0; color:var(--maroon); }
.fea-callout{ border:1px solid var(--line-strong); padding:1.2rem; background:var(--parchment-3); }
.fea-callout .slot-desc{ margin-top:.4rem; }
.fea-finding{ font-size:.92rem; margin-top:.9rem; color:var(--ink-muted); }

.closing-note{ margin-top:2.4rem; padding-top:2rem; border-top:1px solid var(--line); }
.closing-note p{ font-size:1.05rem; font-style:italic; color:var(--maroon-bright); max-width:60ch; }

/* ============ LIGHT PROJECT CARDS ============ */
.light-grid{ display:grid; grid-template-columns:repeat(auto-fit,minmax(280px,1fr)); gap:1.4rem; margin-top:2.4rem; }
.light-card{ border:1px solid var(--line-strong); background:var(--parchment-2); padding:1.5rem; display:flex; flex-direction:column; gap:.9rem; }
.light-card h4{ font-size:1.15rem; }
.light-card .lc-meta{ font-family:var(--font-mono); font-size:.72rem; color:var(--ink-faint); }
.light-card ul{ display:flex; flex-direction:column; gap:.4rem; }
.light-card li{ font-size:.9rem; padding-left:1rem; position:relative; color:var(--ink-muted); }
.light-card li::before{ content:'—'; position:absolute; left:0; color:var(--maroon); }
.lc-status{ margin-top:auto; padding-top:.6rem; border-top:1px solid var(--line); font-family:var(--font-mono); font-size:.7rem; color:var(--ink-faint); }

/* short "project report" style summary (why / what we built / what we're
   comparing) placed above a media gallery so a visitor has context before
   pressing play -- reuses the site's existing mono-uppercase label voice
   (.skill-group-name) rather than inventing new typography. */
.rl-report{ display:flex; flex-direction:column; gap:.9rem; margin:.2rem 0; }
.rl-report-block p{ margin:0; }
.rl-report-label{ font-family:var(--font-mono); font-size:.72rem; letter-spacing:.08em; text-transform:uppercase; color:var(--maroon); margin-bottom:.3rem; }
.rl-report-block p:not(.rl-report-label){ font-size:.92rem; color:var(--ink-muted); line-height:1.6; }
.rl-report-finding{ font-size:.92rem; color:var(--ink-muted); line-height:1.6; margin:.2rem 0 0; }
.rl-report-finding strong{ color:var(--maroon-deep); }

/* a small gallery of labeled clips inside one light-card, e.g. comparing RL
   policies/ablations side by side -- distinct from .video-compare (which
   height-matches exactly two mismatched-aspect clips); this wraps N clips
   of roughly the same aspect into a simple auto-fit grid. Each clip gets a
   short caption, not just a filename-style label, so the clip is legible
   without having already read the report text above it. */
.rl-video-grid{ display:grid; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); gap:1.2rem; }
.rl-video-item{ display:flex; flex-direction:column; gap:.45rem; }
.rl-video-item video{ width:100%; height:auto; display:block; border:1px solid var(--line-strong); background:#1a1210; }
.rl-video-label{ font-family:var(--font-mono); font-size:.7rem; letter-spacing:.05em; text-transform:uppercase; color:var(--maroon); }
.rl-video-caption{ font-size:.78rem; color:var(--ink-faint); line-height:1.45; margin:0; }

/* ============ SKILLS ============ */
.skill-groups{ display:flex; flex-direction:column; gap:1.6rem; }
.skill-group{ display:grid; grid-template-columns:180px 1fr; gap:1rem; align-items:start; padding:1.1rem 0; border-top:1px solid var(--line); }
@media (max-width:640px){ .skill-group{ grid-template-columns:1fr; gap:.6rem; } }
.skill-group-name{ font-family:var(--font-mono); font-size:.78rem; letter-spacing:.08em; text-transform:uppercase; color:var(--maroon); }
.tag-row{ display:flex; flex-wrap:wrap; gap:.5rem; }
.tag{ font-family:var(--font-mono); font-size:.8rem; padding:.35rem .7rem; border:1px solid var(--line-strong); color:var(--ink); background:var(--parchment-2); }

/* ============ PERSONAL ============ */
.personal-grid{ display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:1.4rem; }
.personal-card{ border:1px solid var(--line-strong); background:var(--parchment-2); padding:1.4rem; display:flex; flex-direction:column; gap:.9rem; }
.personal-card h4{ font-size:1.1rem; display:flex; align-items:center; gap:.5rem; }
.personal-card .icon-sm{ width:1.1rem; height:1.1rem; color:var(--maroon); }
.personal-card p{ font-size:.9rem; color:var(--ink-muted); margin:0; }
.personal-card .from-story{ font-family:var(--font-mono); font-size:.68rem; color:var(--ink-faint); }

/* ============ CONTACT ============ */
.contact-row{ display:flex; flex-wrap:wrap; gap:1rem; margin-top:1.6rem; }
.contact-item{ display:flex; align-items:center; gap:.6rem; font-family:var(--font-mono); font-size:.9rem; }
.btn[disabled]{ opacity:.5; cursor:not-allowed; pointer-events:none; border-style:dashed; }

footer.site-foot{ padding:2.5rem 0 3.5rem; }
.foot-row{ display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:1rem; font-family:var(--font-mono); font-size:.72rem; color:var(--ink-faint); letter-spacing:.04em; }
.foot-gear{ width:1.4rem; height:1.4rem; color:var(--maroon); opacity:.7; }

.skip-link{
  position:absolute; left:-999px; top:auto;
  background:var(--maroon); color:var(--parchment); padding:.6rem 1rem; font-family:var(--font-mono); font-size:.8rem;
  z-index:100;
}
.skip-link:focus{ left:1rem; top:1rem; }

/* ============ FOLDABLE / DOSSIER FOLDER ============
   Given the light red/blush treatment on purpose — these are the site's
   "extendable" (collapsible) content blocks, visually flagged as a distinct,
   optional-reading category rather than blending into the parchment cards. */
.folder{
  border:1px solid var(--blush-border); background:var(--blush); margin-top:1.6rem;
}
.folder + .folder{ margin-top:1.2rem; }
.folder-tab{
  display:flex; align-items:center; justify-content:space-between; gap:1rem;
  padding:1.1rem 1.4rem; cursor:pointer; list-style:none;
  font-family:var(--font-mono); font-size:.85rem; letter-spacing:.08em; text-transform:uppercase;
  color:var(--maroon-deep); user-select:none;
}
.folder-tab::-webkit-details-marker{ display:none; }
.folder-tab::marker{ content:''; }
.folder-tab .folder-tab-left{ display:flex; align-items:center; gap:.8rem; }
.folder-tab .folder-count{
  font-family:var(--font-mono); font-size:.7rem; color:var(--maroon); letter-spacing:.05em;
  text-transform:none; border:1px solid var(--blush-border); padding:.15rem .5rem;
  background:var(--blush-2);
}
.folder-tab .folder-chevron{
  width:.9rem; height:.9rem; color:var(--maroon); flex-shrink:0;
  transition:transform .25s ease;
}
.folder[open] > .folder-tab .folder-chevron{ transform:rotate(90deg); }
.folder-tab:hover{ color:var(--maroon-bright); }
.folder-tab:hover .folder-chevron{ color:var(--maroon-bright); }
.folder-body{
  padding:0 1.4rem 1.6rem; border-top:1px dashed var(--blush-border);
}
.folder-body-intro{ font-size:.9rem; color:var(--maroon-deep); opacity:.8; padding-top:1.2rem; margin-bottom:0; }
/* content nested inside a folder stays on the same blush tint as the
   folder's own chrome — the whole block should read as one uniform light-red
   panel, not a red tab sitting on top of parchment-colored cards */
.folder .light-card, .folder .tl-entry{ background:transparent; }
.folder .light-card{ border-color:var(--blush-border); padding:1.5rem; }
.folder .tl-entry{ border-bottom-color:var(--blush-border); padding-left:1rem; padding-right:1rem; }
.folder .media-slot{
  border-color:var(--blush-border);
  background:
    repeating-linear-gradient(135deg, rgba(122,36,29,0.06) 0 10px, transparent 10px 20px),
    var(--blush-2);
}

/* ============ FOLDABLE VARIANT — "current era" (post-CMU) ============
   The blush/archived tint above is deliberately reserved for work from
   BEFORE Oscar joined CMU (Earlier Work, Undergraduate Projects @ VT) --
   time-boxed, done, filed away. Anything from during the CMU/lab era reads
   instead in the same neutral parchment + maroon treatment as the main
   research (.flagship) above, even when it's still tucked into a foldable
   section for space reasons. Add class="folder-current" alongside
   class="folder" to opt a section into this palette. */
.folder.folder-current{ border-color:var(--line-strong); background:var(--parchment-2); }
.folder.folder-current .folder-tab{ color:var(--maroon-deep); }
.folder.folder-current .folder-tab .folder-count{ border-color:var(--line-strong); background:var(--parchment-3); }
.folder.folder-current .folder-body{ border-top:1px dashed var(--line-strong); }
.folder.folder-current .folder-body-intro{ opacity:1; color:var(--ink-muted); }
.folder.folder-current .light-card{ border-color:var(--line-strong); }
.folder.folder-current .media-slot{
  border-color:var(--line-strong);
  background:
    repeating-linear-gradient(135deg, rgba(122,36,29,0.05) 0 10px, transparent 10px 20px),
    var(--parchment-3);
}

/* ============ HARDWARE GENERATION COVERS (v4 — seamless ribbon, framed) ============
   Each of the 3 big hardware generations gets a Codex-page-style <summary>:
   a solid maroon ribbon, framed with a parchment margin on the top/bottom/
   outer edge (never flush to the card edge), alternates left/right per
   generation (.gen-cover.reverse flips it). The cutout photo fills the
   FULL ribbon height (not split into a text zone + photo zone) so there is
   no hard seam — the "MARK n" title is an absolutely-positioned overlay on
   a soft gradient scrim at the top, floating over the photo the way a
   Codex logo box floats over the character art beneath it. The photo is
   also deliberately wider than the ribbon so it bleeds out past the inner
   edge. A "what I did" bullet list, a reserved engineering-drawing slot,
   and a prominent bordered "read the full build" button sit in the
   parchment column beside it. Clicking anywhere on the cover unfolds the
   phase-by-phase write-up for that generation. */
.gen-fold{ border:1px solid var(--line-strong); background:var(--parchment-2); margin-top:1.8rem; overflow:hidden; }
.gen-fold:first-of-type{ margin-top:2.2rem; }
.gen-summary{ cursor:pointer; list-style:none; display:block; }
.gen-summary::-webkit-details-marker{ display:none; }
.gen-summary::marker{ content:''; }
.gen-summary:focus-visible .gen-cover{ outline:2px solid var(--maroon-bright); outline-offset:-2px; }

/* overflow:hidden here — not just on .gen-fold — so the photo's downward
   shift (see .gen-cover-photo below) is clipped at the bottom of the
   COVER itself (the "unextended block") and never bleeds into the
   phase-by-phase write-up once a fold is opened. Safe for the horizontal
   bleed too: nothing ever needs to render past this row's own width, only
   across the boundary between its two child columns. */
.gen-cover{ display:flex; flex-wrap:wrap; align-items:stretch; overflow:hidden; }

.gen-cover-ribbon-col{
  position:relative; z-index:1; order:1; flex:0 0 32%; min-width:260px;
  min-height:clamp(640px,58vw,820px);
  background:transparent;
  /* no rem-based margin here anymore -- the 10%-of-block outer margin is
     produced by the inset on ::before below, so it scales as a true
     percentage instead of a fixed/clamped rem gap. Column widened from
     30% to 32% (margin held at 10%, ribbon grew from 20% to 22%) so
     "Mark III" clears the band with real room instead of a ~3px margin. */
}
.gen-cover.reverse .gen-cover-ribbon-col{
  order:2;
}
.gen-cover.reverse .gen-cover-content-col{ order:1; }

/* the actual maroon ribbon: inset 31.25% within this 30%-of-block column,
   which works out to exactly 10% margin + 20% solid ribbon as a share of
   the whole block. Flush against the edge facing the content column (no
   gap between the ribbon and the bullet text), inset only on the outer
   edge. A flat (non-animated) black-to-transparent fade is layered under
   the maroon at that same outer edge for a little depth/roundedness --
   not a gradient standing in for the margin, the margin is real empty
   space; this fade lives entirely inside the solid ribbon itself. */
.gen-cover-ribbon-col::before{
  content:''; position:absolute; z-index:0; top:0; bottom:0;
  left:31.25%; right:0;
  background:
    linear-gradient(to right, rgba(0,0,0,.3), rgba(0,0,0,0) 22%),
    var(--maroon);
}
.gen-cover.reverse .gen-cover-ribbon-col::before{
  left:0; right:31.25%;
  background:
    linear-gradient(to left, rgba(0,0,0,.3), rgba(0,0,0,0) 22%),
    var(--maroon);
}

/* photo zone spans the full column so the cutout can bleed past the band.
   Bleeds toward the column's OUTER edge (into the reserved margin), not
   into the text column -- the margin is there on purpose so the photo has
   somewhere to break the rectangle into without crowding the bullet text. */
.gen-cover-photo-zone{ position:absolute; inset:0; z-index:1; }
.gen-cover-photo{
  /* left:65.625% (not 50%) centers the image on the RIBBON's own midpoint,
     not the column's -- the ribbon is inset within the column (31.25% to
     100%), so its center sits right of the column's center. Only a small
     extra shift (clamp below) then bleeds it toward the margin, instead
     of the image being dragged off-center by a big shift like before. */
  position:absolute; left:65.625%; top:0; height:88%;
  /* wide enough (240%) that HEIGHT is always the binding constraint for
     object-fit:contain, even for the near-square Gen 2 photo -- that's
     what actually guarantees all three render at the same height. At
     150% the square photo used to hit the width ceiling first and come
     out visibly shorter than the narrow Gen 1/3 crops. */
  width:240%; max-width:none;
  object-fit:contain; object-position:bottom center; z-index:2;
  /* shifted down + toward the column's OUTER edge (the margin), so the
     hardware bleeds into the reserved margin space and the top of the
     ribbon stays clear maroon behind the title. Sized a bit smaller than
     the column (88% height) on purpose, so there's slack to shift into
     without either fully swallowing the margin or crossing into the
     content column. */
  transform:translate(calc(-50% - clamp(6px,1.2vw,16px)), clamp(150px,16vw,240px));
  filter:drop-shadow(0 10px 18px rgba(20,10,8,.4));
}
.gen-cover.reverse .gen-cover-photo{
  /* reverse (Mark II) untouched: still anchored at the column's 50%, with
     the larger clamp(15-35px) bleed -- only Marks I/III were asked to
     re-center on the ribbon. */
  left:50%;
  transform:translate(calc(-50% + clamp(15px,3vw,35px)), clamp(150px,16vw,240px));
}

/* title sits directly on the solid ribbon band — no photo behind it once
   the photo is shifted down, so no scrim/gradient needed. Bounds updated
   to match the new 31.25%-inset ribbon band exactly (still just tracking
   the ribbon's own edges, not a position/style change to the title itself). */
.gen-cover-ribbon-top{
  position:absolute; z-index:3; top:0; left:31.25%; right:0;
  display:flex; flex-direction:column; align-items:center; text-align:center;
  padding:clamp(1.6rem,3.4vw,2.1rem) .7rem 1.1rem;
}
.gen-cover.reverse .gen-cover-ribbon-top{ left:0; right:31.25%; }
.gen-cover-mark{
  /* pushed as large as it can go while "Mark III" (the longest title)
     still fits the ribbon's actual measured width on a single line --
     values below are fit to real DOM measurements at two viewport widths
     (700px and 1300px), not eyeballed, with a small safety margin so font
     rendering variance doesn't tip it into wrapping. Same rule, all three. */
  font-family:var(--font-display); font-weight:700;
  font-size:clamp(2.3125rem, calc(-0.207rem + 4.6875vw), 3.25rem);
  color:#fff; letter-spacing:.03em; text-shadow:0 2px 12px rgba(0,0,0,.55);
  white-space:nowrap;
}
.gen-cover-mark-sub{
  /* same approach: as large as possible while the longest subtitle ("The
     Reverse-Engineered Conversion") still holds at two lines. */
  font-family:var(--font-mono);
  font-size:clamp(.69375rem, calc(-0.055rem + 1.2609vw), .875rem);
  letter-spacing:.04em; color:rgba(247,241,225,.92);
  margin-top:.6rem; max-width:24ch; line-height:1.4; text-shadow:0 1px 8px rgba(0,0,0,.5);
}

.gen-cover-content-col{
  position:relative; z-index:2; /* the ribbon photo (z-index:1 on its
    positioned ancestor) can bleed wide enough at narrow widths to
    physically overlap this column -- without its own stacking context
    above that, the photo would paint over the text instead of behind it. */
  flex:1 1 320px; order:2; background:var(--parchment-2);
  padding:clamp(1.8rem,3.4vw,2.6rem) clamp(1.8rem,3.4vw,2.6rem);
  display:flex; flex-direction:column; gap:1.5rem;
}
/* the "why this generation exists" line — sits above the "what I did"
   label, giving each cover its own thesis statement (the hypothesis being
   tested, the priority being chased, the question being answered) rather
   than only a bullet list of actions. */
.gen-cover-purpose{
  font-family:var(--font-display); font-weight:700;
  font-size:clamp(1.4rem,2.65vw,2.15rem); line-height:1.22;
  color:var(--maroon-bright); margin:0 0 1.1rem 0;
}
.gen-cover-bullets-label{
  font-family:var(--font-mono); font-size:.7rem; letter-spacing:.18em; text-transform:uppercase;
  color:var(--maroon);
}
.gen-cover-bullets{ list-style:none; padding:0; margin:.6rem 0 0; display:flex; flex-direction:column; gap:.7rem; }
.gen-cover-bullets li{
  font-family:var(--font-body); font-size:1rem; line-height:1.5; color:var(--ink);
  padding-left:1.4rem; position:relative;
}
.gen-cover-bullets li::before{
  content:'▸'; position:absolute; left:0; top:.02em; color:var(--maroon); font-weight:700;
}
/* ---- manifest checklist: replaces the plain bullet list on the cover card.
   Two groups — items closed out within this generation ("Resolved") and
   the one that surfaces as the next generation's whole reason for being
   ("Carried Forward"), with a small tag pointing at where it gets picked
   up. Keeps the "problem -> fix -> result -> next problem" thread visible
   at a glance instead of buried in four same-weight bullets. */
/* block flow, not flex -- a flex formatting context ignores floats entirely,
   and the drawing needs to float right with checklist rows narrowing beside
   it, then returning to full width once past its bottom. overflow:hidden
   gives this its own block formatting context so it properly encloses the
   float's height instead of collapsing around it. */
.gen-cover-manifest{ overflow:hidden; }
/* own overflow:hidden so a group containing a floated drawing (the float
   now lives inside the "open" group, after its label, so the label always
   renders full-width before the float starts) still gets its height
   properly contained, independent of the outer .gen-cover-manifest's BFC. */
.manifest-group{ margin-bottom:1.15rem; overflow:hidden; }
.manifest-group:last-child{ margin-bottom:0; }
/* size ladder is deliberate: title > label ("What I did" / "Carried
   Forward") > bullet item text, so the group labels read as real
   sub-headers rather than a small caption tag above bigger body text. */
.manifest-label{
  font-family:var(--font-mono); font-size:clamp(1.05rem,1.95vw,1.58rem);
  letter-spacing:.1em; text-transform:uppercase;
}
.manifest-group.resolved .manifest-label{ color:var(--maroon); }
.manifest-group.open .manifest-label{ color:var(--ink-faint); }
.manifest-list{ list-style:none; margin:.6rem 0 0; padding:0; }
/* deliberately NOT display:flex -- a flex container (like any box that
   establishes a new block formatting context) has to avoid a float's
   margin box for its ENTIRE height, all at once, rather than adapting
   line-by-line -- so a li beside the drawing float would get squeezed
   into one narrow lane for its whole height even long after the float's
   bottom edge had passed, instead of widening back out. Plain block flow
   with a floated bullet is what actually gives per-line text reflow. */
/* hanging indent, not a float, for the bullet -- Mark II's drawing is
   float:left (bottom-left placement) same as a floated bullet would be,
   and two same-side floats stack next to each other instead of the
   bullet sitting at the text's own start. text-indent pulls the first
   line back into the padding-left gutter (where the inline-block bullet
   sits); wrapped lines fall at the padding edge, so it still reads as a
   normal checklist indent either side of the drawing. */
/* no hanging indent (padding-left/text-indent) here on purpose -- the
   bullet is a plain inline-block sitting directly in front of the item
   text, inside the same paragraph run, so it travels with the text as one
   unit through every line the float reshapes -- a hanging indent would
   only re-apply its pull-back to the first line, leaving the bullet
   correctly wrapped but visually detached from how the rest of the block
   aligns once text passes below the float. */
.manifest-list li{
  margin-bottom:.6rem;
  font-family:var(--font-body); font-size:clamp(1rem,1.72vw,1.42rem); line-height:1.48; color:var(--ink);
}
.manifest-list li:last-child{ margin-bottom:0; }
/* the small engineering-drawing thumbnail, floated into the checklist's
   flow so text narrows beside it and returns to full width once past its
   bottom edge, rather than sitting in its own full-width block below. */
.gen-cover-drawing-float{
  float:right; clear:right;
  width:clamp(255px,57%,480px);
  margin:.15rem 0 .9rem 1.1rem;
  border:2px solid var(--photo-border);
  background:var(--parchment-2);
  padding:.35rem;
}
.gen-cover-drawing-float img{ width:100%; height:auto; display:block; }
/* Mark II specifically sits on the other side (bottom-left, mirrored
   margin) since its ribbon column is on the right. */
.gen-cover-drawing-float.left{ float:left; clear:left; margin:.15rem 1.1rem .9rem 0; }
/* placeholder variant for a generation whose drawing hasn't arrived yet --
   same small floated footprint as the real thing so the layout doesn't
   jump once an image replaces it, just icon+text centered instead of img. */
.gen-cover-drawing-float.placeholder{
  aspect-ratio:1.9/1;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:.4rem;
  color:var(--ink-faint);
  background:
    repeating-linear-gradient(135deg, rgba(122,36,29,0.05) 0 10px, transparent 10px 20px),
    var(--parchment-3);
}
.gen-cover-drawing-float.placeholder svg{ width:1.4rem; height:1.4rem; }
.gen-cover-drawing-float.placeholder span{
  font-family:var(--font-mono); font-size:.58rem; letter-spacing:.1em; text-transform:uppercase; text-align:center;
}
/* plain round bullet, not a bullet -- solid/filled for a "What I did"
   item, hollow/outline-only for a "Carried Forward" item, so the two
   groups still read as done-vs-open at a glance without looking like a
   to-do list. Sized and positioned to sit inline with the first line of
   text like a normal bullet marker. */
.manifest-check{
  display:inline-block; width:7px; height:7px; margin-right:.65em;
  vertical-align:middle; position:relative; top:-.15em;
  border-radius:50%; border:1.5px solid var(--maroon);
}
.manifest-list li.done .manifest-check{ background:var(--maroon); }
.manifest-list li.pending .manifest-check{ background:transparent; border-color:var(--ink-faint); }
/* wraps text+carry-tag together as one flex item so the tag can wrap onto
   its own line when space is tight (e.g. squeezed beside a float) instead
   of overflowing the row -- min-width:0 is what lets a flex item shrink
   below its content's natural width at all. */
/* plain inline span now (li is no longer flex) -- just carries the text +
   nested carry-tag as one run so normal line-wrapping applies to both. */
.manifest-item-text{ display:inline; }
.manifest-carry{
  display:inline-block; text-indent:0;
  font-family:var(--font-mono); font-size:.68rem; letter-spacing:.05em; color:var(--maroon-bright);
  white-space:nowrap; margin-left:.4rem;
}

/* jump targets inside a phase-body: land clear of the sticky nav, and get a
   brief highlight so it's obvious what the manifest link actually pointed
   at. Native browser behavior auto-opens a closed <details> when the
   fragment target is inside it, so no JS is needed for the fold itself. */
.jump-target{ scroll-margin-top:5.5rem; }
.jump-target:target{ animation:jump-flash 2.4s ease; }
@keyframes jump-flash{
  0%{ background:rgba(122,36,29,.16); }
  100%{ background:transparent; }
}

.gen-cover-hint{
  align-self:flex-start;
  display:inline-flex; align-items:center; gap:.55rem;
  font-family:var(--font-mono); font-size:.82rem; font-weight:700; letter-spacing:.09em; text-transform:uppercase;
  color:var(--maroon); border:1.5px solid var(--maroon); padding:.7rem 1.3rem;
  transition:background .2s ease, color .2s ease;
}
.gen-cover-hint svg{ width:.9rem; height:.9rem; transition:transform .25s ease; }
.gen-summary:hover .gen-cover-hint, .gen-fold[open] > .gen-summary .gen-cover-hint{
  background:var(--maroon); color:#fff;
}
.gen-fold[open] .gen-cover-hint svg{ transform:rotate(90deg); }

@media (max-width:640px){
  /* stacked layout: ribbon-col and content-col are separate flex LINES,
     not side-by-side columns, so .gen-cover's own overflow:hidden clips
     at the bottom of BOTH combined, not at the ribbon's own bottom edge —
     without its own overflow:hidden here, the down-shifted photo bleeds
     past the ribbon box into the bullet text below it. There's also no
     side-by-side column left to bleed into horizontally on mobile, so
     clipping both axes at the ribbon's own box is correct here. */
  .gen-cover-ribbon-col, .gen-cover.reverse .gen-cover-ribbon-col{
    order:1; flex:1 1 100%; min-height:460px;
    margin: 0 clamp(1rem,4vw,1.4rem) 0 clamp(1rem,4vw,1.4rem);
    overflow:hidden;
  }
  .gen-cover-content-col, .gen-cover.reverse .gen-cover-content-col{ order:2; flex:1 1 100%; }
  /* the 31.25% inset reads as margin+ribbon side-by-side against the
     content column on desktop; stacked full-width on mobile there's no
     content column beside it to react against, so the same inset just
     reads as a lopsided blank strip. Full-bleed the ribbon here instead. */
  .gen-cover-ribbon-col::before, .gen-cover.reverse .gen-cover-ribbon-col::before{ left:0; right:0; }
  .gen-cover-ribbon-top, .gen-cover.reverse .gen-cover-ribbon-top{ left:0; right:0; }
}

.gen-fold-body{ padding:clamp(1.6rem,4vw,2.4rem); border-top:1px dashed var(--line-strong); }
.gen-fold-body .phase:first-child{ padding-top:0; border-top:none; }

/* short connective line between two hardware-generation covers, stating
   what problem got handed from one generation to the next — a rule on
   each side, italic caption in the middle, so it reads as a chapter break
   rather than another content block. */
.gen-bridge{
  display:flex; align-items:center; gap:1rem;
  margin:1.4rem clamp(0.4rem,3vw,1.8rem);
  font-family:var(--font-mono); font-size:.8rem; font-style:italic;
  color:var(--ink-muted); text-align:center; line-height:1.4;
}
.gen-bridge::before, .gen-bridge::after{ content:''; flex:1 1 auto; height:1px; background:var(--line); }
.gen-bridge span{ flex:0 0 auto; max-width:52ch; }

/* ============ SITE INTRO STRIP (used on sub-pages under the page header) ============ */
.record-label{ font-family:var(--font-mono); font-size:.78rem; letter-spacing:.16em; text-transform:uppercase; color:var(--maroon); }
