/* ==========================================================================
   MANUAL.CSS — technical-manual portfolio
   Sections: 1 tokens · 2 base · 3 header/nav · 4 layout · 5 figure panels
   6 callouts · 7 schematic · 8 contents table · 9 photography
   10 case studies · 11 design plates · 12 about · 13 footer
   14 focus/a11y · 15 responsive · 16 motion · 17 print · 18 cursor
   ========================================================================== */

/* 0 ── SELF-HOSTED FONTS -------------------------------------------------- */
@font-face {
  font-family: "Cormorant";
  src: url("../fonts/Cormorant.ttf") format("truetype");
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Cormorant";
  src: url("../fonts/Cormorant-Italic.ttf") format("truetype");
  font-weight: 300 700;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Drafting Mono";
  src: url("../fonts/DraftingMono-Regular.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Drafting Mono";
  src: url("../fonts/DraftingMono-Bold.ttf") format("truetype");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Drafting Mono";
  src: url("../fonts/DraftingMono-Italic.ttf") format("truetype");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Drafting Mono";
  src: url("../fonts/DraftingMono-BoldItalic.ttf") format("truetype");
  font-weight: 700;
  font-style: italic;
  font-display: swap;
}

/* 1 ── TOKENS ------------------------------------------------------------- */
:root {
  --paper: #FAFAF8;
  --paper-rgb: 250, 250, 248;
  --blueprint: #2B4CFF;
  --blueprint-fill: #8E9EF0;
  --blueprint-tint: #EAEEFF;
  --grid-line: #DFE4F7;
  --ink: #15171C;
  --ink-muted: #5C6070;

  --font-display: "Silkscreen", "Courier New", monospace;
  --font-serif: "Cormorant", "Iowan Old Style", Georgia, serif;
  --font-mono: "Drafting Mono", "SF Mono", "Menlo", monospace;

  /* cone-cell accents for the about spec stack (red / green / blue / ink) */
  --c-skills: #D64550;
  --c-tools: #2FA65A;
  --c-interests: #4C63D6;
  --c-background: #2B2F38;

  --s1: 8px;  --s2: 16px; --s3: 24px; --s4: 40px; --s5: 64px; --s6: 96px;

  --max-w: 1600px;
  --gutter: 24px;

  --hatch: repeating-linear-gradient(
    -45deg,
    var(--blueprint) 0,
    var(--blueprint) 1.5px,
    transparent 1.5px,
    transparent 5px
  );
  --graph: repeating-linear-gradient(
      0deg, var(--grid-line) 0, var(--grid-line) 1px, transparent 1px, transparent 16px),
    repeating-linear-gradient(
      90deg, var(--grid-line) 0, var(--grid-line) 1px, transparent 1px, transparent 16px);

  /* fixed stamp colors for panels that are always "blue ink block, white
     text" (footer, date pills) - these do not swap in dark mode, so the
     stamp keeps a consistent identity instead of inverting into a
     light panel on a dark page. */
  --stamp-bg: #2B4CFF;
  --stamp-bg-hover: #2140D6;
  --stamp-ink: #FAFAF8;

  /* fixed brand-identity colors for third-party logos (project-title icons) -
     real brand hex, same in both themes, like --stamp-* above. */
  --brand-github: #181717;
  --brand-airbnb: #FF5A5F;

  color-scheme: light;
}

/* blueprint negative: a true engineering blueprint is white lines on blue
   paper, so dark mode inverts the brand relationship instead of just
   dimming it - deep navy paper, brightened accent for contrast. Every rule
   in this file reads color through these tokens, so this block is the only
   place dark mode needs to be defined.

   Three tiers: system preference (media query) sets the default, an
   explicit user choice (data-theme, written by the header toggle) overrides
   it in either direction. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper: #10152B;
    --paper-rgb: 16, 21, 43;
    --blueprint: #6C8CFF;
    --blueprint-fill: #4A5FCB;
    --blueprint-tint: #1B2350;
    --grid-line: #262C52;
    --ink: #F1F2F8;
    --ink-muted: #8890B0;
    --c-background: #F1F2F8;
    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --paper: #10152B;
  --paper-rgb: 16, 21, 43;
  --blueprint: #6C8CFF;
  --blueprint-fill: #4A5FCB;
  --blueprint-tint: #1B2350;
  --grid-line: #262C52;
  --ink: #F1F2F8;
  --ink-muted: #8890B0;
  --c-background: #F1F2F8;
  color-scheme: dark;
}

/* registered vars so the exploded-view drift and hover-lift animate on
   separate properties - hover never restarts the idle float (no jitter) */
@property --floatY { syntax: "<length>"; inherits: false; initial-value: 0px; }
@property --hoverY { syntax: "<length>"; inherits: false; initial-value: 0px; }
@property --driftX { syntax: "<length>"; inherits: false; initial-value: 0px; }
@property --driftY { syntax: "<length>"; inherits: false; initial-value: 0px; }
@property --popX   { syntax: "<length>"; inherits: false; initial-value: 0px; }
@property --popY   { syntax: "<length>"; inherits: false; initial-value: 0px; }

/* 2 ── BASE --------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  background: var(--paper);
  scroll-behavior: smooth;
}

body {
  margin: 0;
  font-family: var(--font-serif);
  font-size: 17px;
  line-height: 1.55;
  color: var(--ink);
  counter-reset: fig;
  -webkit-font-smoothing: antialiased;
}

img, svg { max-inline-size: 100%; block-size: auto; display: block; }

a { color: var(--blueprint); }

h1, h2, h3 { margin: 0 0 var(--s2); }

h1 {
  font-family: var(--font-display);
  font-size: clamp(24px, 3.5vw, 44px);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--blueprint);
  line-height: 1.1;
}

h2, h3 {
  font-family: var(--font-mono);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--blueprint);
}
h2 { font-size: 13px; }
h3 { font-size: 12px; }

p { margin: 0 0 var(--s2); }

.prose p {
  text-align: justify;
  hyphens: auto;
  -webkit-hyphens: auto;
}

/* real drop cap on the opening paragraph of each page */
.dropcap::first-letter {
  float: left;
  font-family: var(--font-serif);
  font-size: 3.6em;
  line-height: 0.82;
  padding-inline-end: 0.08em;
  padding-block-start: 0.04em;
  color: var(--ink);
}

.mono,
.label {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--blueprint);
}

.muted { color: var(--ink-muted); }

hr, .rule-hatch {
  border: 0;
  block-size: 12px;
  margin: 0;
  background: var(--hatch);
}

.wrap {
  max-inline-size: var(--max-w);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.skip-link {
  position: absolute;
  inset-block-start: -100px;
  inset-inline-start: var(--s2);
  z-index: 100;
  padding: var(--s1) var(--s2);
  background: var(--stamp-bg);
  color: var(--stamp-ink);
  font-family: var(--font-mono);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  text-decoration: none;
}
.skip-link:focus { inset-block-start: var(--s2); }

/* reading-progress hairline (case-study detail) */
.progress {
  position: fixed;
  inset-block-start: 0;
  inset-inline-start: 0;
  block-size: 2px;
  inline-size: 0;
  background: var(--blueprint);
  z-index: 60;
}

/* 3 ── HEADER / NAV ------------------------------------------------------- */
.site-header {
  position: sticky;
  inset-block-start: 0;
  z-index: 50;
  background: var(--paper);
}

.masthead {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--s3);
  padding-block: var(--s3) var(--s2);
}

.masthead-left {
  display: flex;
  align-items: center;
  gap: var(--s2);
}

.wordmark {
  font-family: var(--font-display);
  font-size: clamp(20px, 2.6vw, 34px);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--blueprint);
  text-decoration: none;
  line-height: 1;
  image-rendering: pixelated;
}

/* dark-mode toggle: sun/moon crossfade, no icon library - a couple of
   plain strokes fit the drafting-tool mark better than a generic glyph. */
.theme-toggle {
  position: relative;
  display: inline-grid;
  place-items: center;
  inline-size: 30px;
  block-size: 30px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 4px;
  background: transparent;
  color: var(--blueprint);
  cursor: pointer;
}
.theme-toggle:hover { background: var(--blueprint-tint); }
.theme-toggle:focus-visible {
  outline: 2px solid var(--blueprint);
  outline-offset: 2px;
}
.theme-toggle:active { transform: scale(0.94); }

.theme-toggle .ti {
  grid-area: 1 / 1;
  transition: opacity 320ms cubic-bezier(0.16, 1, 0.3, 1),
    rotate 320ms cubic-bezier(0.16, 1, 0.3, 1),
    scale 320ms cubic-bezier(0.16, 1, 0.3, 1);
}
.theme-toggle .ti-sun { opacity: 1; rotate: 0deg; scale: 1; }
.theme-toggle .ti-moon { opacity: 0; rotate: -90deg; scale: 0.5; }
.theme-toggle.is-dark .ti-sun { opacity: 0; rotate: 90deg; scale: 0.5; }
.theme-toggle.is-dark .ti-moon { opacity: 1; rotate: 0deg; scale: 1; }

@media (prefers-reduced-motion: reduce) {
  .theme-toggle .ti { transition: opacity 120ms linear; }
  .theme-toggle .ti-sun,
  .theme-toggle .ti-moon,
  .theme-toggle.is-dark .ti-sun,
  .theme-toggle.is-dark .ti-moon { rotate: 0deg; scale: 1; }
}

.masthead-right {
  text-align: end;
  font-size: 15px;
  line-height: 1.35;
}
.masthead-right .subtitle {
  display: block;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--blueprint);
  margin-block-end: 4px;
}

.site-header .rule-hatch { transition: height 120ms linear; }
.site-header.is-stuck .rule-hatch { block-size: 6px; }
.site-header.is-stuck .masthead { padding-block: var(--s1); }

.site-nav ul {
  list-style: none;
  margin: 0;
  padding: var(--s1) 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  position: relative; /* offset parent for the sliding pill */
}

/* active-state indicator: one blue pill that slides in X to the active link.
   the [ ] brackets ride on the pill, so they stay on the fill as it moves */
.site-nav .nav-indicator {
  position: absolute;
  top: 0;
  left: 0;
  background: var(--blueprint);
  z-index: 0;
  pointer-events: none;
  transform: translate(0, 0);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 7px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.12em;
  color: var(--paper);
}
.site-nav .nav-indicator::before { content: "["; }
.site-nav .nav-indicator::after  { content: "]"; }
.site-nav .nav-indicator.is-ready {
  transition: transform 340ms cubic-bezier(0.4, 0, 0.2, 1),
    width 340ms cubic-bezier(0.4, 0, 0.2, 1),
    height 340ms cubic-bezier(0.4, 0, 0.2, 1);
}

.site-nav li { display: flex; align-items: center; }

.site-nav li + li::before {
  content: "";
  inline-size: 1px;
  block-size: 14px;
  background: var(--blueprint);
  margin-inline: var(--s2);
}

.site-nav a {
  font-family: var(--font-mono);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--blueprint);
  text-decoration: none;
  padding: 8px 10px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  position: relative;
  z-index: 1; /* label sits above the sliding pill */
}

.site-nav a:hover {
  background: var(--blueprint-tint);
  text-decoration: underline;
  text-decoration-style: dashed;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
}

/* active page: paper text on the sliding blue pill (no dot, no underline) */
.site-nav a[aria-current="page"] {
  color: var(--paper);
  text-decoration: none;
}
.site-nav a[aria-current="page"]:hover {
  color: var(--paper);
  background: none;
  text-decoration: none;
}

.menu-btn { display: none; }

/* 4 ── LAYOUT: two-column manual spread ---------------------------------- */
.spread {
  display: grid;
  grid-template-columns: minmax(0, 30fr) minmax(0, 70fr);
  column-gap: var(--s4);
  padding-block: var(--s4) var(--s5);
  position: relative;
}
.spread > .col-text { padding-inline-end: var(--s3); }
.spread > .col-fig { border-inline-start: 1px solid var(--grid-line); padding-inline-start: var(--s4); }

.page-title-block { margin-block-end: var(--s3); }
.page-no {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  color: var(--ink-muted);
  text-transform: uppercase;
  display: block;
  margin-block-end: var(--s1);
}

/* 5 ── FIGURE PANELS ------------------------------------------------------ */
.fig {
  counter-increment: fig;
  position: relative;
  border: 1.5px solid var(--blueprint);
  background-color: var(--paper);
  background-image: var(--graph);
  margin: 0 0 var(--s4);
  padding: var(--s4);
}

/* rotated figure ID + bracketed data-tag removed sitewide */
.fig::before,
.fig::after { content: none; display: none; }

/* service-history role meta line (About Me) */
.svc-meta {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--ink-muted);
  margin: 2px 0 10px;
}

/* ── Experience: flex-row cards (auto-layout) + decorative year strip ───── */
.svc-hz { margin-block: var(--s3) var(--s5); }
.svc-hz > h2 { margin-block-end: var(--s2); }

/* pinned horizontal scroll: .svc-pin is tall (JS sizes it), .svc-sticky sticks
   below the menu while scroll scrubs the track sideways, then releases */
.svc-pin { position: relative; }
.svc-sticky { position: sticky; /* inset-block-start set by JS = header + 100 */ }
.svc-scale { position: relative; overflow: hidden; }
.svc-track {
  position: relative;      /* in-flow so the band takes the cards' height */
  inline-size: max-content; /* wider than the band → translateX scrubs it */
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  will-change: transform;
}

/* below 900px or reduced motion: no pin — plain horizontal scroll */
@media (max-width: 899px), (prefers-reduced-motion: reduce) {
  .svc-pin { block-size: auto !important; }
  .svc-sticky { position: static; }
  .svc-scale { overflow-x: auto; }
  .svc-track { transform: none !important; }
}

/* auto-layout row of experience cards */
.svc-flow {
  display: flex;
  gap: 8px;                 /* ≥8px between experiences */
  align-items: stretch;     /* all cards equal height */
  padding: 16px 48px;       /* 48px lead so the first card is off the edge */
}
.svc-card {
  flex: 0 0 auto;
  max-inline-size: 720px;   /* cap so many-bullet cards stay within the band */
  border: 1px solid var(--blueprint);
  background: var(--paper);
  padding: 10px;            /* 10px inner padding */
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.svc-card-head { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.svc-card h3 { margin: 2px 0 0; font-size: 1rem; }
.svc-card .svc-meta { margin: 0 0 6px; }
.svc-span {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--stamp-ink); background: var(--stamp-bg); padding: 2px 7px;
}
.svc-dur {
  font-family: var(--font-mono);
  font-size: 11px; letter-spacing: 0.06em;
  color: var(--blueprint);
}

/* bullets: horizontal auto-layout inside a card */
.svc-bullets { display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: flex-start; }
.svc-bul {
  flex: 0 0 clamp(140px, 15vw, 172px);
  position: relative;
  padding-block-start: 12px;
  font-size: 0.92rem;
  line-height: 1.4;
}
.svc-bul::before {
  content: "";
  position: absolute;
  inset-block-start: 0; inset-inline-start: 0;
  inline-size: 18px; block-size: 3px;
  background: var(--blueprint);
}
/* B.E. card: fewer bullets, stack them narrow */
.svc-card--edu .svc-bullets { flex-direction: column; gap: 6px; }
.svc-card--edu .svc-bul { flex: none; inline-size: 210px; }

/* decorative year strip below the cards (not aligned to the cards) */
.svc-strip {
  display: flex;
  justify-content: space-between;
  margin-inline: 48px;
  padding-block-start: 8px;
  border-block-start: 1.5px solid var(--blueprint);
}
.svc-strip .svc-yr {
  position: relative;
  font-family: var(--font-mono);
  font-size: 13px; font-weight: 700; letter-spacing: 0.08em;
  color: var(--blueprint);
  padding-block-start: 8px;
}
.svc-strip .svc-yr::before { /* short tick up to the strip line */
  content: "";
  position: absolute;
  inset-block-start: -1.5px; inset-inline-start: 50%;
  inline-size: 1.5px; block-size: 6px;
  background: var(--blueprint-fill);
}

.svc-hint {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.06em;
  color: var(--ink-muted); margin-block-start: 8px;
}

/* B.E. card slides in from the right when the section reaches view */
.svc-intro { transform: translate(64px, 18px); opacity: 0; transition: transform 0.6s ease, opacity 0.6s ease; }
.svc-intro.is-in { transform: none; opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .svc-scale { overflow-x: auto; }
  .svc-track { position: relative; transform: none !important; }
  .svc-intro { transform: none; opacity: 1; transition: none; }
}

.fig > figcaption,
.fig-caption {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--blueprint);
  margin-block-start: var(--s2);
}

/* the one highlighted part per figure */
.fig .part-focus { fill: var(--blueprint-fill); }

.plate-art { border: 1px solid var(--grid-line); background: var(--paper); }

/* clickable design plates — stretched overlay link (used on every page that
   shows a plate grid, so it lives here in manual.css, not experience.css) */
.plate-open { position: absolute; inset: 0; z-index: 4; cursor: pointer; }
.plate:hover { outline: 1px solid var(--blueprint); outline-offset: 2px; }

/* 6 ── CALLOUTS with leader lines ---------------------------------------- */
.callout-host { position: relative; }

.callout {
  position: absolute;
  display: flex;
  align-items: center;
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--blueprint);
  white-space: nowrap;
  text-decoration: none;
}

.callout .lead {
  display: inline-block;
  inline-size: var(--lead, 56px);
  block-size: 7px;
  /* 8px dash / 8px gap = one 16px grid cell per cycle; the 1px line is
     vertically centered in the 7px box, sharing the arrowhead's midline */
  background-image: linear-gradient(
    90deg,
    var(--blueprint) 0,
    var(--blueprint) 8px,
    transparent 8px,
    transparent 16px
  );
  background-size: 16px 1px;
  background-repeat: repeat-x;
  background-position: 0 50%;
  margin-inline: 6px;
  position: relative;
}

/* solid arrowhead at the pointing end, centered on the same midline */
.callout .lead::after {
  content: "";
  position: absolute;
  inset-block-start: 0;
  border-block: 3.5px solid transparent;
}
.callout.points-right .lead::after {
  inset-inline-end: -1px;
  border-inline-start: 6px solid var(--blueprint);
}
.callout.points-left .lead::after {
  inset-inline-start: -1px;
  border-inline-end: 6px solid var(--blueprint);
}

a.callout:hover .txt { background: var(--blueprint-tint); text-decoration: underline; }

/* fallback list shown under 900px instead of positioned callouts */
.callout-list {
  list-style: none;
  margin: var(--s2) 0 0;
  padding: 0;
  display: none;
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--blueprint);
}
.callout-list li { padding-block: 4px; border-block-end: 1px solid var(--grid-line); }

/* 7b ── ABOUT SPEC STACK (flat, expand on hover / tap) -------------------- */
.spec-stack {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;   /* 2×2 card grid */
  /* fixed track heights sized to the tallest expanded card (Skills). Each row
     reserves exactly the room a panel needs when open, so the outer square is
     the tallest-expanded size — no empty waste, no jump when a panel opens. */
  --spec-track: 174px;
  grid-template-rows: var(--spec-track) var(--spec-track);
  gap: 12px;
}
.spec-fig { padding: 10px; }         /* tighter than the global .fig 40px */
/* Top row (Skills, Tools) expands UPWARD: card pinned to the bottom of its
   track so added body height grows up (heading stays on top, bullets below).
   Bottom row (Interests, Background) expands DOWNWARD. */
.spec-stack > .spec-row:nth-child(1),
.spec-stack > .spec-row:nth-child(2) { align-self: end; }
.spec-stack > .spec-row:nth-child(3),
.spec-stack > .spec-row:nth-child(4) { align-self: start; }
@media (max-width: 560px) {
  .spec-stack { grid-template-columns: 1fr; grid-template-rows: none; }
  .spec-stack > .spec-row { align-self: auto; display: block; }
}
.spec-row {
  border: 1.5px solid var(--c);
  background: var(--paper);
  transition: background 240ms ease;
  position: relative;
  overflow: hidden;
}

/* glass-glare sweep: two diagonal light streaks cross each row in its
   accent colour. rows fire in sequence, 3s apart, looping every 12s. */
@media (prefers-reduced-motion: no-preference) {
  .spec-row::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 2;
    transform: translateX(-140%);
    background: linear-gradient(
      115deg,
      transparent 30%,
      color-mix(in srgb, var(--c) 42%, transparent) 36%,
      transparent 42%,
      transparent 50%,
      color-mix(in srgb, var(--c) 42%, transparent) 56%,
      transparent 62%
    );
    animation: glassSweep 8s ease-in-out infinite;
  }
  .spec-stack .spec-row:nth-child(1)::after { animation-delay: 0s; }
  .spec-stack .spec-row:nth-child(2)::after { animation-delay: 2s; }
  .spec-stack .spec-row:nth-child(3)::after { animation-delay: 4s; }
  .spec-stack .spec-row:nth-child(4)::after { animation-delay: 6s; }
  @keyframes glassSweep {
    0%    { transform: translateX(-140%); }
    22.5% { transform: translateX(140%); }
    100%  { transform: translateX(140%); }
  }
}
.spec-head {
  inline-size: 100%;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px 18px;
  background: none;
  border: 0;
  cursor: pointer;
  font-family: var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--ink);
  text-align: start;
}
.spec-icon {
  inline-size: 26px;
  block-size: 26px;
  flex: none;
  color: var(--c);
}
.spec-icon svg {
  inline-size: 100%;
  block-size: 100%;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.spec-label { font-size: 13px; font-weight: 700; }
.spec-toggle {
  margin-inline-start: auto;
  color: var(--c);
  font-size: 18px;
  line-height: 1;
  transition: transform 300ms ease;
}
/* grid 0fr → 1fr gives a smooth height transition without a fixed max */
.spec-body {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 320ms ease;
}
.spec-body-inner { overflow: hidden; }
.spec-body p {
  margin: 0;
  padding: 0 18px 16px 58px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--ink-muted);
}
/* expanded: each listed thing on its own row with its own icon */
.spec-items {
  list-style: none;
  margin: 0;
  padding: 2px 18px 18px 58px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px 24px;
}
.spec-items li {
  display: flex;
  align-items: center;
  gap: 11px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.spec-item-icon {
  inline-size: 18px;
  block-size: 18px;
  flex: none;
  color: var(--c);
}
.spec-item-icon svg {
  inline-size: 100%;
  block-size: 100%;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* about spec sheet: height is driven by the grid track reserve above, so the
   square hugs the tallest-expanded panel with uniform 10px padding. */
.spec-fig .spec-stack { inline-size: 100%; }

/* open state: on hover (pointer devices) and via .is-open (tap toggle) */
@media (hover: hover) {
  .spec-row:hover { background: color-mix(in srgb, var(--c) 8%, var(--paper)); }
  .spec-row:hover .spec-body { grid-template-rows: 1fr; }
  .spec-row:hover .spec-toggle { transform: rotate(45deg); }
}
.spec-row.is-open { background: color-mix(in srgb, var(--c) 8%, var(--paper)); }
.spec-row.is-open .spec-body { grid-template-rows: 1fr; }
.spec-row.is-open .spec-toggle { transform: rotate(45deg); }

/* 7 ── EXPLODED STACK ----------------------------------------------------- */
.explode {
  position: relative;
  block-size: var(--explode-h, 520px);
  perspective: 1400px;
  /* keep the projected bottom layer clear of whatever follows */
  margin-block-end: var(--s4);
}

.explode .guide {
  position: absolute;
  inset-block: 6%;
  inline-size: 0;
  border-inline-start: 1px dashed var(--blueprint);
}

.explode .layer {
  position: absolute;
  inset-inline-start: 50%;
  inset-block-start: 50%;
  inline-size: var(--layer-w, 240px);
  block-size: var(--layer-w, 240px);
  margin-inline-start: calc(var(--layer-w, 240px) / -2);
  margin-block-start: calc(var(--layer-w, 240px) / -2);
  border: 1.5px solid var(--blueprint);
  background: var(--paper);
  transform: translateY(calc(var(--lift) + var(--floatY) + var(--hoverY))) rotateX(55deg) rotateZ(-45deg);
  transform-style: preserve-3d; /* lets the ghost trails un-project to screen space */
  transition: transform 120ms linear, --hoverY 120ms linear;
  display: flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
}

/* hover: the plate itself rises 4px on screen. --hoverY is its own
   (transitioned) variable so hovering never touches the float animation */
.explode .layer:hover {
  --hoverY: -4px;
}

.explode .layer.is-focus { background: var(--blueprint-fill); }

/* labels sit on the face as bordered chips: legible over any overlap,
   and they read as pressable */
.explode .layer .layer-label {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--blueprint);
  background: var(--paper);
  border: 1px solid var(--blueprint);
  padding: 6px 12px;
  transform: rotateZ(45deg);
  text-align: center;
  max-inline-size: 90%;
  line-height: 1.4;
  white-space: nowrap;
  overflow-wrap: normal;
}
.explode .layer:hover .layer-label {
  background: var(--blueprint-tint);
  text-decoration: underline;
  text-decoration-style: dashed;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

.explode .layer:hover { background: var(--blueprint-tint); }
.explode .layer.is-focus:hover { background: var(--blueprint-fill); }

/* inner detail lines on a layer face; rises 18px on screen when hovered.
   In face coordinates (k, -k) projects to pure screen-vertical after the
   isometric rotations; 22px face units ≈ 18px on screen. */
.explode .layer .face-detail {
  position: absolute;
  inset: 16px;
  border: 1px solid var(--blueprint);
  pointer-events: none;
  transform: translate(calc(var(--driftX) + var(--popX)), calc(var(--driftY) + var(--popY)));
  transition: --popX 120ms linear, --popY 120ms linear;
}
.explode .layer:hover .face-detail { --popX: 22px; --popY: -22px; }

/* displacement trails: dotted lines from the resting corners up to the
   popped rectangle's edge, shown only while that layer is hovered */
.explode .layer .face-ghost {
  position: absolute;
  inset: 16px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 120ms linear;
}
.explode .layer .face-ghost::before,
.explode .layer .face-ghost::after {
  content: "";
  position: absolute;
  inline-size: 0;
  block-size: 18px; /* matches the 18px screen-space pop */
  border-inline-start: 1px dotted var(--blueprint);
  /* inverse of the layer's isometric rotation: the line renders as a true
     screen-vertical, pinned by its bottom end to the face corner */
  transform: rotateZ(45deg) rotateX(-55deg);
  transform-origin: 0 100%;
}
.explode .layer .face-ghost::before { inset-block-end: 100%; inset-inline-start: 0; }
.explode .layer .face-ghost::after { inset-block-end: 0; inset-inline-start: 100%; }
.explode .layer:hover .face-ghost { opacity: 1; }

/* assembly axis: drafting-style center line through every layer */
.explode .axis {
  position: absolute;
  inset-block: 2%;
  inset-inline-start: 50%;
  inline-size: 1px;
  background-image: repeating-linear-gradient(
    180deg,
    var(--blueprint) 0,
    var(--blueprint) 8px,
    transparent 8px,
    transparent 11px,
    var(--blueprint) 11px,
    var(--blueprint) 13px,
    transparent 13px,
    transparent 16px
  );
  z-index: 5;
  pointer-events: none;
}

/* rectangular "screen" layers for wireframe stacks */
.explode--screens { --layer-w: 260px; }
.explode--screens .layer {
  block-size: 170px;
  margin-block-start: -85px;
}

/* placeholder plate art (inline SVG standing in for photos/screens) */
.ph-art { inline-size: 100%; background: var(--paper); }
.ph-art .stroke { stroke: var(--blueprint-fill); stroke-width: 1.5; fill: none; }
.ph-art .stroke-thin { stroke: var(--blueprint-fill); stroke-width: 1; fill: none; }
.ph-art .fill { fill: var(--blueprint-fill); }
.ph-art .tint { fill: var(--blueprint-tint); }
.ph-art text {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.12em;
  fill: var(--blueprint-fill);
  text-transform: uppercase;
}

/* Find the Tempo card — clean screenshot that pops out on hover / keyboard
   focus, revealing a short description panel and an underlined arrow. */
.tempo-frame {
  position: relative;
  display: block;
  aspect-ratio: 1264 / 791;
  overflow: hidden;
  border: 1px solid var(--grid-line);
  background: var(--paper);
}
.tempo-frame img {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  display: block;
}
.tempo-card {
  transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.tempo-card:hover,
.tempo-card:focus-within {
  transform: translateY(-6px) scale(1.02);
  box-shadow: 0 18px 40px -12px rgba(43, 76, 255, 0.35);
  position: relative;
  z-index: 5;
}
/* description panel over the image, hidden until hover */
.tempo-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: var(--s2);
  padding: var(--s3);
  background: linear-gradient(to top,
    rgba(var(--paper-rgb), 1),
    rgba(var(--paper-rgb), 0.98) 55%,
    rgba(var(--paper-rgb), 0.85) 100%);
  opacity: 0;
  transition: opacity 0.25s ease;
  pointer-events: none; /* clicks fall through to the .plate-open link */
}
.tempo-card:hover .tempo-overlay,
.tempo-card:focus-within .tempo-overlay { opacity: 1; }
.tempo-desc {
  margin: 0;
  max-inline-size: 48ch;
  font-family: var(--font-serif);
  color: var(--ink);
  font-size: 16px;
  line-height: 1.45;
}
.tempo-arrow {
  align-self: flex-end;
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--blueprint);
  text-decoration: underline;
  text-underline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
  .tempo-card,
  .tempo-overlay { transition: none; }
}

/* 404 missing figure */
.fig-404 {
  min-block-size: 380px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.fig-404 .missing {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--blueprint);
  border: 1px dashed var(--blueprint);
  padding: var(--s2) var(--s3);
  background: var(--paper);
}

/* 8 ── CONTENTS TABLE ----------------------------------------------------- */
.toc { margin-block-start: var(--s4); }
.toc-row {
  display: flex;
  align-items: baseline;
  gap: var(--s1);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--blueprint);
  text-decoration: none;
  padding-block: 10px;
}
.toc-row .leader {
  flex: 1;
  border-block-end: 1px dotted var(--blueprint);
  transform: translateY(-3px);
}
.toc-row .count { color: var(--ink-muted); }
.toc-row:hover .name { background: var(--blueprint-tint); }

/* 9 ── PHOTOGRAPHY: contact sheet + lightbox ------------------------------ */
.contact-sheet {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--blueprint);
  border: 1.5px solid var(--blueprint);
}

.contact-sheet > figure {
  margin: 0;
  background: var(--paper);
  padding: var(--s2);
}

.contact-sheet .frame-btn {
  display: block;
  inline-size: 100%;
  padding: 0;
  border: 1px solid var(--grid-line);
  background: none;
  cursor: pointer;
}

/* plain photo plate (dither removed); a subtle zoom on hover/focus */
.contact-sheet .plate {
  position: relative;
  display: block;
  inline-size: 100%;
  aspect-ratio: 4 / 5;
  background: var(--paper);
  overflow: hidden;
}
/* frame drawn over the photo so the 1px outline shows on all four sides —
   the image (.plate-orig, z-index 2) was painting over the top line */
.contact-sheet .plate::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  border: 1px solid var(--grid-line);
  pointer-events: none;
}
.contact-sheet .plate-shader { display: none; } /* dither shader removed */
.contact-sheet .plate-orig {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  z-index: 2;
  object-fit: cover;
  background: var(--paper);
  transition: transform 0.35s ease;
}
.contact-sheet .frame-btn:hover .plate-orig,
.contact-sheet .frame-btn:focus-visible .plate-orig {
  transform: scale(1.12);
}
@media (prefers-reduced-motion: reduce) {
  .contact-sheet .plate-orig { transition: none; }
  .contact-sheet .frame-btn:hover .plate-orig,
  .contact-sheet .frame-btn:focus-visible .plate-orig { transform: none; }
}

.contact-sheet figcaption {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--blueprint);
  margin-block-start: var(--s1);
  display: grid;
  gap: 2px;
}
.contact-sheet figcaption .meta { color: var(--ink-muted); }
/* Grid caption shows only a call to action; the real title + EXIF stay in the
   DOM (hidden here) so the lightbox can still read them from figcaption. */
.contact-sheet figcaption > span { display: none; }
.contact-sheet figcaption::before { content: "[ click to view ]"; }

.lightbox {
  border: 1.5px solid var(--blueprint);
  padding: var(--s4);
  background-color: var(--paper);
  background-image: var(--graph);
  /* fixed width + fixed-height stage below → every photo, portrait or
     landscape, gets the same frame, so the Prev/Close/Next row never shifts */
  inline-size: min(920px, 90vw);
}
.lightbox::backdrop { background: rgba(21, 23, 28, 0.55); }
.lightbox .lb-controls {
  display: flex;
  justify-content: space-between;
  gap: var(--s2);
  margin-block-start: var(--s2);
}
.lightbox button {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--blueprint);
  background: var(--paper);
  border: 1px solid var(--blueprint);
  padding: 12px 16px;
  cursor: pointer;
}
.lightbox button:hover { background: var(--blueprint-tint); }
.lightbox .lb-stage {
  inline-size: 100%;
  block-size: 70vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--paper);
  border: 1px solid var(--grid-line);
}
.lightbox .lb-photo {
  display: block;
  max-inline-size: 100%;
  max-block-size: 100%;
  inline-size: auto;
  block-size: auto;
  object-fit: contain;
}
.lightbox .lb-caption { display: none; } /* caption text removed — leave the lightbox uncaptioned */

/* 10 ── CASE STUDIES ------------------------------------------------------ */
.study-index { list-style: none; margin: 0; padding: 0; }

.study-row {
  display: grid;
  grid-template-columns: 90px minmax(0, 2fr) minmax(0, 3fr) 140px 70px 24px;
  gap: var(--s2);
  align-items: baseline;
  padding-block: var(--s3);
  border-block-end: 1px solid var(--grid-line);
  text-decoration: none;
  color: var(--ink);
  transition: transform 120ms linear;
}
.study-row:hover { transform: translateX(4px); background: var(--blueprint-tint); }
.study-row .arrow { visibility: hidden; color: var(--blueprint); font-family: var(--font-mono); }
.study-row:hover .arrow { visibility: visible; }
.study-row .study-no, .study-row .study-role, .study-row .study-year {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--blueprint);
}
.study-row .study-year { color: var(--ink-muted); }
.study-row .study-title { font-weight: 700; font-size: 19px; }
.study-row .study-problem { color: var(--ink-muted); font-style: italic; }

/* project-title brand icons (GitHub/Airbnb) - shared base, reused by .cs-bar
   in experience.css. Neutral at rest, tints to real brand hex at low
   opacity on hover so it doesn't clash with a hover background. */
.proj-ico { display: inline-flex; flex: none; }
.proj-ico svg { display: block; width: 15px; height: 15px; fill: currentColor; }

.study-title .proj-ico { margin-inline-start: 6px; vertical-align: -2px; color: var(--ink); }
a.study-row:hover .proj-ico[data-brand="github"] { color: var(--brand-github); }
a.study-row:hover .proj-ico[data-brand="airbnb"] { color: var(--brand-airbnb); }

.spec-sheet {
  border: 1.5px solid var(--blueprint);
  background: var(--paper);
  padding: var(--s3);
  margin-block-end: var(--s4);
}
.spec-sheet dl {
  margin: 0;
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--s1) var(--s3);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.spec-sheet dt { color: var(--ink-muted); }
.spec-sheet dd { margin: 0; color: var(--blueprint); }

.metrics { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s2); }
.metric {
  border: 1px solid var(--blueprint);
  background: var(--paper);
  padding: var(--s2);
}
.metric .num {
  font-family: var(--font-mono);
  font-size: 22px;
  color: var(--blueprint);
  display: block;
}
.metric .what {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

/* 11 ── DESIGN PLATES + FILTER -------------------------------------------- */
.filter-bar,
.view-bar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s1);
  margin-block-end: var(--s4);
}
.filter-bar button,
.view-bar button {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--blueprint);
  background: var(--paper);
  border: 1px solid var(--blueprint);
  padding: 12px 16px;
  cursor: pointer;
}
.filter-bar button:hover,
.view-bar button:hover { background: var(--blueprint-tint); }
.filter-bar button[aria-pressed="true"],
.view-bar button[aria-pressed="true"] {
  background: var(--stamp-bg);
  color: var(--stamp-ink);
}
.plate.is-hidden { display: none; }
.plate[id] { scroll-margin-top: 120px; }

/* plate gallery: grid by default, single column in list view */
.plate-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(440px, 100%), 1fr));
  gap: var(--s3);
}
.plate-grid.view-list { grid-template-columns: 1fr; }

/* contact sheet in list view: one frame per row, caption beside it */
.contact-sheet.view-list { grid-template-columns: 1fr; }
.contact-sheet.view-list > figure {
  display: grid;
  grid-template-columns: minmax(160px, 260px) 1fr;
  gap: var(--s3);
  align-items: center;
}
.contact-sheet.view-list figcaption { margin-block-start: 0; }

/* study index in grid view: spec rows become spec cards */
.study-index.view-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
  gap: var(--s3);
}
.study-index.view-grid .study-row {
  grid-template-columns: 1fr;
  gap: var(--s1);
  align-content: start;
  border: 1px solid var(--blueprint);
  border-block-end: 1px solid var(--blueprint);
  padding: var(--s3);
}
.study-index.view-grid .study-row:hover { transform: none; }
.study-index.view-grid .arrow { display: none; }

/* 12 ── ABOUT: person diagram, timeline, contact -------------------------- */
.timeline {
  list-style: none;
  margin: var(--s4) 0 0;
  padding: 0 0 0 var(--s3);
  border-inline-start: 1px dashed var(--blueprint);
}
.timeline li { position: relative; padding-block-end: var(--s3); }
.timeline li::before {
  content: "";
  position: absolute;
  inset-inline-start: calc(-1 * var(--s3) - 4px);
  inset-block-start: 6px;
  inline-size: 7px;
  block-size: 7px;
  background: var(--blueprint);
}
.timeline .year {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  color: var(--blueprint);
  display: block;
}

.status-chip {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  border: 1px solid var(--blueprint);
  background: var(--blueprint-tint);
  color: var(--blueprint);
  padding: 12px 16px;
}

.contact-block a { color: var(--blueprint); }

/* back-to-top: fixed, centered, appears after scrolling */
.back-top {
  position: fixed;
  inset-block-end: 24px;
  inset-inline-start: 50%;
  transform: translateX(-50%);
  z-index: 40;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--blueprint);
  background: var(--paper);
  border: 1px solid var(--blueprint);
  padding: 8px 12px;
  text-decoration: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 120ms linear, visibility 120ms linear;
}
.back-top.is-visible { opacity: 1; visibility: visible; }
.back-top:hover { background: var(--blueprint-tint); }

/* "view all frames" CTA — bracket-mono button after the photography section */
.frames-more {
  display: inline-block;
  margin-block-start: var(--s3);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--stamp-ink);
  background: var(--stamp-bg);
  border: 1px solid var(--stamp-bg);
  padding: 10px 16px;
  text-decoration: none;
}
.frames-more:hover { background: var(--stamp-bg-hover); border-color: var(--stamp-bg-hover); }

/* 13 ── FOOTER ------------------------------------------------------------ */
.site-footer { margin-block-start: var(--s5); }
.footer-cols {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s3);
  padding-block: var(--s4);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.footer-cols ul { list-style: none; margin: 0; padding: 0; }
.footer-cols li { padding-block: 4px; }
.footer-cols a { color: var(--blueprint); text-decoration: none; }
.footer-cols a:hover { text-decoration: underline; text-decoration-style: dashed; }
.footer-cols .colophon { color: var(--ink-muted); }

/* 14 ── FOCUS / A11Y ------------------------------------------------------ */
:focus-visible {
  outline: 2px solid var(--blueprint);
  outline-offset: 2px;
}

/* mobile nav overlay */
.nav-overlay {
  position: fixed;
  inset: 0;
  z-index: 80;
  background-color: var(--paper);
  background-image: var(--graph);
  padding: var(--s3);
  display: none;
  flex-direction: column;
}
.nav-overlay.is-open { display: flex; }
.nav-overlay ul { list-style: none; margin: var(--s5) 0 0; padding: 0; }
.nav-overlay a {
  display: block;
  font-family: var(--font-mono);
  font-size: 16px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--blueprint);
  text-decoration: none;
  padding: var(--s2) 0;
  border-block-end: 1px solid var(--grid-line);
}
.overlay-group-label {
  margin: var(--s5) 0 0;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  opacity: 0.55;
}
.overlay-group-label + ul { margin-top: var(--s2); }
.nav-overlay .close-btn { align-self: flex-end; }

.menu-btn, .nav-overlay .close-btn {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--blueprint);
  background: none;
  border: 1px solid var(--blueprint);
  padding: 12px 16px;
  cursor: pointer;
}

/* scroll reveal (JS adds .reveal; IO adds .is-in) */
.reveal { opacity: 0; transform: translateY(12px); transition: opacity 150ms linear, transform 150ms linear; }
.reveal.is-in { opacity: 1; transform: none; }

/* 15 ── RESPONSIVE (mobile-first collapses live here) --------------------- */
@media (max-width: 899px) {
  .spread { grid-template-columns: 1fr; }
  .spread > .col-fig { border-inline-start: 0; padding-inline-start: 0; margin-block-start: var(--s4); }
  .spread > .col-text { padding-inline-end: 0; }

  .callout-host .callout { display: none; }
  .callout-list { display: block; }

  .site-nav { display: none; }
  .menu-btn { display: inline-block; margin-block: var(--s1); }

  .explode { --layer-w: 180px; --explode-h: 420px; }

  .contact-sheet { grid-template-columns: repeat(2, 1fr); }

  .study-row { grid-template-columns: 70px 1fr 24px; }
  .study-row .study-problem, .study-row .study-role, .study-row .study-year { display: none; }

  .metrics { grid-template-columns: 1fr; }
  .footer-cols { grid-template-columns: 1fr; }

  .masthead { flex-direction: column; align-items: flex-start; gap: var(--s2); }
  .masthead-right { text-align: start; }
}

@media (max-width: 639px) {
  .contact-sheet { grid-template-columns: 1fr; }
}

@media (min-width: 1280px) {
  .wrap { padding-inline: 48px; }
}

/* 16 ── MOTION ------------------------------------------------------------ */
@media (prefers-reduced-motion: no-preference) {
  /* the one orchestrated moment: the stack expands from collapsed on load.
     Fill is `backwards`, not `both` - a forwards fill would keep overriding
     the hover transform after the animation ends. */
  .explode.animate .layer {
    animation: assemble 1200ms cubic-bezier(0.22, 1, 0.36, 1) backwards;
  }
  @keyframes assemble {
    from { transform: translateY(0) rotateX(55deg) rotateZ(-45deg); }
    to   { transform: translateY(var(--lift)) rotateX(55deg) rotateZ(-45deg); }
  }
  .explode.animate .guide {
    animation: guides-in 1200ms linear backwards;
  }
  /* the center axis draws top-to-bottom as the stack expands */
  .explode.animate .axis {
    transform-origin: top center;
    animation: axis-draw 1200ms cubic-bezier(0.22, 1, 0.36, 1) backwards;
  }
  @keyframes axis-draw {
    from { transform: scaleY(0); }
  }
  @keyframes guides-in {
    from { opacity: 0; }
    60%  { opacity: 0; }
    to   { opacity: 1; }
  }
  /* callouts fade in once the stack has mostly expanded */
  .explode-callouts.animate .callout { animation: guides-in 1600ms linear backwards; }

  /* dashes march toward the part they name, ticking one half grid cell
     (8px) per beat so they stay registered with the 16px graph paper */
  .callout.points-right .lead { animation: march-right 1s steps(2) infinite; }
  .callout.points-left .lead { animation: march-left 1s steps(2) infinite; }
  @keyframes march-right { to { background-position-x: 16px; } }
  @keyframes march-left { to { background-position-x: -16px; } }

  /* EXPLODED-VIEW DRIFT ---------------------------------------------------
     From the resting position (0), each plate eases up to -Y and back;
     its inner rectangle eases down to +Y and back - opposite directions,
     never crossing past rest, both on the same smooth cycle. */

  /* outer plate drifts via --floatY only (screen-space +Y = down) */
  @keyframes layerFloat {
    0%, 100% { --floatY: 0px; }
    50%      { --floatY: 8px; }
  }
  .explode .layer {
    animation: layerFloat 3.4s ease-in-out infinite;
  }
  /* home stack: assemble animates `transform`, layerFloat animates `--floatY`
     - different properties, so they coexist. The 1200ms delay holds --floatY
     at 0 through the entrance for a clean handoff. */
  .explode.animate .layer {
    animation: assemble 1200ms cubic-bezier(0.22, 1, 0.36, 1) backwards,
               layerFloat 3.4s ease-in-out 1200ms infinite;
  }

  /* inner rectangle drifts via --driftX/--driftY, opposite the plate.
     (16,-16) in the plate's tilted plane projects to screen-up. */
  @keyframes faceDrift {
    0%, 100% { --driftX: 0px; --driftY: 0px; }
    50%      { --driftX: 16px; --driftY: -16px; }
  }
  .explode .layer .face-detail {
    animation: faceDrift 3.4s ease-in-out infinite;
  }
  /* start together with the plate float on the home stack */
  .explode.animate .layer .face-detail { animation-delay: 1200ms; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
  .study-row { transition: none; }
}

/* 17 ── PRINT ------------------------------------------------------------- */
@media print {
  .site-header, .site-footer, .menu-btn, .skip-link, .progress, .back-top { display: none; }
  .fig { background-image: none; }
  body { font-size: 11pt; }
  a { text-decoration: none; color: var(--ink); }
}

/* K ── BLUEPRINT FOOTER --------------------------------------------------- */
/* A blueprint-blue panel with a light-blue drafting grid, corner crop marks
   framing the panel and the wordmark, and mono spec labels. Page-scoped
   (experience.css only) so other pages keep the plain footer. Palette:
   --blueprint bg, white-alpha grid reads as light blue, --paper text,
   --blueprint-fill / --blueprint-tint as the light-blue accents. */
.site-footer.fb { margin-block-start: 0; }

/* reusable corner crop marks — anchor to the nearest .framed box */
.framed { position: relative; }
.crop {
  position: absolute;
  inline-size: 20px;
  block-size: 20px;
  border: 0 solid var(--paper);
  pointer-events: none;
}
.crop-tl { inset-block-start: 0; inset-inline-start: 0; border-block-start-width: 2px; border-inline-start-width: 2px; }
.crop-tr { inset-block-start: 0; inset-inline-end: 0; border-block-start-width: 2px; border-inline-end-width: 2px; }
.crop-bl { inset-block-end: 0; inset-inline-start: 0; border-block-end-width: 2px; border-inline-start-width: 2px; }
.crop-br { inset-block-end: 0; inset-inline-end: 0; border-block-end-width: 2px; border-inline-end-width: 2px; }

/* footer particle canvas — sits behind the content, clipped to the panel */
.fb .fb-particles {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

/* drafting tick ruler seam above the panel */
.fb .fb-ruler {
  block-size: 18px;
  background-image: repeating-linear-gradient(90deg,
    var(--blueprint) 0, var(--blueprint) 1.5px, transparent 1.5px, transparent 16px);
  border-block-end: 1.5px solid var(--blueprint);
  opacity: 0.55;
}

/* the blue panel + light-blue grid (minor 24px, major 96px). The grid is kept
   faint so text stays readable over it. */
.fb .fb-panel {
  position: relative;
  overflow: hidden;
  background-color: var(--stamp-bg);
  background-image:
    repeating-linear-gradient(0deg,  rgba(255,255,255,.14) 0 1px, transparent 1px 96px),
    repeating-linear-gradient(90deg, rgba(255,255,255,.14) 0 1px, transparent 1px 96px),
    repeating-linear-gradient(0deg,  rgba(255,255,255,.05) 0 1px, transparent 1px 24px),
    repeating-linear-gradient(90deg, rgba(255,255,255,.05) 0 1px, transparent 1px 24px);
  background-position: center top;
  color: var(--stamp-ink);
}

.fb .fb-inner {
  max-inline-size: 1200px;
  margin-inline: auto;
  padding: calc(var(--s5) - 23px) var(--s4) calc(var(--s4) - 22px);
  position: relative;
  z-index: 1;
}

/* header tag row */
.fb .fb-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s2);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--blueprint-tint);
}

/* columns */
.fb .fb-cols {
  display: grid;
  grid-template-columns: max-content max-content;
  justify-content: space-between;
  row-gap: var(--s4);
  margin-block-start: var(--s3);
  padding-block-start: var(--s4);
  border-block-start: 1px solid rgba(255,255,255,.35);
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.06em;
}
.fb .fb-col-h {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--blueprint-tint);
  margin: 0 0 var(--s3);
}
.fb .fb-col ul { list-style: none; margin: 0; padding: 0; }
.fb .fb-col li { padding-block: 7px; display: flex; align-items: center; gap: 10px; }
.fb .fb-col a { color: var(--paper); text-decoration: underline; text-underline-offset: 3px; }
.fb .fb-col a:hover { text-decoration-style: dashed; text-underline-offset: 4px; }
.fb .fb-cv {
  color: var(--blueprint);
  background: var(--paper);
  border: 1px solid var(--paper);
  padding: 6px 12px;
  text-decoration: none;
}
.fb .fb-cv:hover { background: var(--blueprint-tint); border-color: var(--blueprint-tint); }
.fb .fb-ico { inline-size: 16px; block-size: 16px; flex: none; color: var(--paper); }
.fb .fb-ico svg {
  inline-size: 100%; block-size: 100%;
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
}
/* spec column: label → value on aligned rows sharing the link-list rhythm */
.fb .fb-spec dl { margin: 0; }
.fb .fb-spec dl > div {
  display: grid;
  grid-template-columns: 72px 1fr;
  gap: var(--s2);
  align-items: baseline;
  padding-block: 7px;
}
.fb .fb-spec dt {
  margin: 0;
  color: var(--blueprint-tint);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 11px;
}
.fb .fb-spec dd { margin: 0; color: var(--paper); }

/* baseline row */
.fb .fb-base {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s2);
  margin-block-start: var(--s4);
  padding-block-start: var(--s3);
  border-block-start: 1px solid rgba(255,255,255,.28);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--blueprint-tint);
}
.fb .fb-plus { color: var(--blueprint-fill); }
.fb .fb-top-link {
  margin-inline-start: auto;
  color: var(--blueprint);
  background: var(--paper);
  border: 1px solid var(--paper);
  padding: 6px 12px;
  text-decoration: none;
}
.fb .fb-top-link:hover { background: var(--blueprint-tint); border-color: var(--blueprint-tint); }

@media (max-width: 899px) {
  .fb .fb-cols { grid-template-columns: 1fr; gap: var(--s3); }
  .fb .fb-inner { padding: var(--s4) var(--s3); }
}

/* scroll cue — bouncing arrow at bottom of first viewport, fades on scroll */
.scroll-hint {
  position: fixed;
  left: 50%;
  bottom: 22px;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--blueprint);
  text-decoration: none;
  z-index: 40;
  opacity: 1;
  transition: opacity 0.3s ease;
}
.scroll-hint .scroll-hint-txt {
  background: var(--stamp-bg);
  color: var(--stamp-ink);
  padding: 4px 8px;
  border: 1px solid var(--stamp-bg);
}
.scroll-hint .scroll-hint-arrow {
  font-size: 16px;
  line-height: 1;
  animation: scrollHintBounce 1.4s ease-in-out infinite;
}
.scroll-hint.is-hidden { opacity: 0; pointer-events: none; }
@keyframes scrollHintBounce {
  0%, 100% { transform: translateY(0); opacity: 0.5; }
  50% { transform: translateY(6px); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .scroll-hint .scroll-hint-arrow { animation: none; }
}

/* 18 ── CURSOR -------------------------------------------------------------
   A small dot follows the pointer; an outer ring appears around it over
   links/buttons. Both are plain white with mix-blend-mode: difference, so
   the color is never a fixed brand token - it's a true per-pixel negative
   of whatever is underneath (dark-on-paper, light-on-dark-mode, amber over
   the blueprint-blue header/footer panels), always readable regardless of
   theme or background. Position (--cx/--cy, set from js/main.js every rAF
   frame) is NOT transitioned - it has to snap 1:1 with the real pointer or
   the dot visibly lags behind fast mouse movement. Only opacity (ready/hover
   fades) and the hover scale get a transition. Hover-capable, fine-pointer
   only: touch/coarse-pointer devices keep their native cursor untouched. */
@media (hover: hover) and (pointer: fine) {
  html, a, button, .theme-toggle, .menu-btn { cursor: none; }

  .cursor-dot, .cursor-ring {
    position: fixed;
    top: 0;
    left: 0;
    pointer-events: none;
    z-index: 200;
    /* stepped octagon instead of border-radius: 50% - a blocky "pixel
       circle" silhouette, matching the Silkscreen/pixelated wordmark rather
       than a smooth anti-aliased circle */
    clip-path: polygon(25% 0%, 75% 0%, 100% 25%, 100% 75%, 75% 100%, 25% 100%, 0% 75%, 0% 25%);
    opacity: 0;
    will-change: transform;
    mix-blend-mode: difference;
    transform: translate3d(var(--cx, 0px), var(--cy, 0px), 0) translate(-50%, -50%);
    transition: opacity 150ms ease;
  }
  .cursor-dot {
    inline-size: 9.6px;
    block-size: 9.6px;
    background: #fff;
  }
  .cursor-ring {
    inline-size: 34px;
    block-size: 34px;
    border: 1.5px solid #fff;
  }
  body.cursor-ready .cursor-dot { opacity: 1; }
  body.cursor-hover .cursor-ring { opacity: 1; }
  body.cursor-hover .cursor-dot {
    transform: translate3d(var(--cx, 0px), var(--cy, 0px), 0) translate(-50%, -50%) scale(0.7);
  }
}
