/* Ta Phuong Linh, portfolio shell + Aurora exhibition
   Tokens and layout per DESIGN.md. Two moods: paper shell, void exhibition. */

@import url('../fonts/fonts.css');

:root {
  --ink: #1A1A1A;
  --paper: #F5F1EA;
  --lacquer: #8B2E1F;
  --digital: #87B5B0;
  --bone: #E8DFD0;
  --sky: #D6E4EB;
  --void: #0C0C0C;
  --smoke: #B9B9B9;

  --font-display: 'Archivo', 'Helvetica Neue', Arial, sans-serif; /* stand-in for Radnika Next, see DESIGN.md */
  --font-body: 'Inter', -apple-system, sans-serif;
  --font-mono: 'JetBrains Mono', 'SF Mono', monospace;

  --size-hero: clamp(2.3rem, 6vw, 5rem);
  --size-title: clamp(2.2rem, 6vw, 5rem);
  --size-section: clamp(1.6rem, 3.6vw, 2.8rem);
  --size-body: 1.05rem;
  --size-caption: 0.75rem;

  --gutter: clamp(1.25rem, 4vw, 4rem);
  --measure: 34em;
  --track-hero: -0.045em;
  --track-title: -0.032em;
  --track-section: -0.022em;
  --rule: color-mix(in srgb, var(--ink) 18%, transparent);
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  overflow-x: clip;
  font-family: var(--font-body);
  font-size: var(--size-body);
  line-height: 1.65;
  background: var(--paper);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
}

img, video { max-width: 100%; display: block; height: auto; }

a { color: inherit; text-decoration: none; cursor: pointer; }
a:focus-visible, button:focus-visible {
  outline: 2px solid var(--lacquer);
  outline-offset: 3px;
}

/* ---------- type roles ---------- */

.display {
  font-family: var(--font-display);
  font-weight: 750;
  line-height: 0.94;
  letter-spacing: var(--track-section, -0.022em);
  text-transform: uppercase;
}
h1, h2, h3 { text-wrap: balance; }
p { text-wrap: pretty; }

.counter { font-feature-settings: 'tnum' 1; }
.caption, .crumb, .counter {
  font-family: var(--font-mono);
  font-size: var(--size-caption);
  font-weight: 400; /* h2.caption section labels must match span weight */
  text-transform: uppercase;
  letter-spacing: 0.12em;
}

.crumb { color: var(--lacquer); }

.bracket::before { content: '[ '; }
.bracket::after { content: ' ]'; }

/* ---------- structure ---------- */

.wrap { padding-inline: var(--gutter); max-width: 1440px; margin-inline: auto; }

.rule { border: 0; border-top: 1px solid var(--rule); }

.site-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 1.1rem var(--gutter);
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--rule);
}

.wordmark {
  font-family: var(--font-display);
  font-weight: 800; font-size: 0.78rem; line-height: 1.02;
  text-transform: uppercase; letter-spacing: 0.02em;
  display: inline-flex; align-items: flex-start; gap: 0.3rem;
}
.wordmark .star { width: 0.55em; margin-top: 0.1em; }

.site-nav { display: flex; gap: clamp(1rem, 3vw, 2.2rem); }
.site-nav a {
  font-family: var(--font-mono); font-size: 0.74rem;
  text-transform: uppercase; letter-spacing: 0.12em;
  padding-block: 0.2rem;
  border-bottom: 1px solid transparent;
}
.site-nav a:hover, .site-nav a[aria-current="page"] { border-bottom-color: var(--lacquer); }

.star { fill: currentColor; }

/* section opener with sky block (her principle 03) */
.section-open {
  background: var(--sky);
  padding: 1.4rem var(--gutter);
  display: flex; justify-content: space-between; align-items: baseline; gap: 1rem;
}

/* ---------- hero ---------- */

.hero { padding: clamp(1.8rem, 4.5vh, 3rem) var(--gutter) clamp(1.4rem, 3.5vh, 2.4rem); }
@media (max-width: 700px) { .hero .crumb { font-size: 0.62rem; letter-spacing: 0.07em; white-space: nowrap; } }
@media (min-width: 1000px) {
  .hero { display: grid; grid-template-columns: minmax(0, 7fr) minmax(280px, 4fr); gap: 1rem 3rem; align-items: start; }
  .hero .crumb { grid-column: 1 / -1; }
  .hero h1 { grid-row: 2; }
  .hero .hero-aside { grid-row: 2; display: flex; flex-direction: column; gap: 1rem; padding-bottom: 0.8rem; }
  .hero .hero-aside .tagline, .hero .hero-aside .positioning { margin-top: 0; }
}
.hero h1 { font-size: var(--size-hero); letter-spacing: var(--track-hero); margin-inline-start: -0.045em; }
.hero h1 .star { width: 0.16em; margin-left: 0.06em; }
.hero .tagline { margin-top: 1.6rem; }
.hero .positioning {
  max-width: var(--measure); margin-top: 1.2rem;
  font-size: 1.12rem; line-height: 1.6;
}

/* ---------- aurora band on home ---------- */

.aurora-band {
  position: relative; display: block;
  background: var(--void); color: #fff;
  overflow: hidden;
  margin: clamp(2rem, 6vh, 4rem) 0;
}
.aurora-band video, .aurora-band img.band-poster {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; opacity: 0.8;
}
.aurora-band::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(100deg, rgba(12,12,12,0.88) 0%, rgba(12,12,12,0.55) 45%, rgba(12,12,12,0.15) 100%);
}
.aurora-band .band-inner {
  position: relative; z-index: 1;
  padding: clamp(4rem, 14vh, 9rem) var(--gutter);
  display: flex; flex-direction: column; gap: 1.1rem;
}
.aurora-band .band-title { font-size: var(--size-title); max-width: 8em; }
.aurora-band .enter {
  margin-top: 1.4rem; align-self: flex-start;
  font-family: var(--font-mono); font-size: 0.78rem;
  text-transform: uppercase; letter-spacing: 0.14em;
  color: #fff; border: 1px solid rgba(255,255,255,0.5);
  padding: 0.85rem 1.4rem;
  transition: background 0.25s ease, color 0.25s ease;
}
.aurora-band .enter:hover { background: #fff; color: var(--void); }

/* ---------- selected works: editorial rows ---------- */

.works { padding-block: clamp(2rem, 6vh, 4rem); display: flex; flex-direction: column; gap: clamp(4rem, 10vh, 7rem); }

.work-row {
  display: grid; gap: 1.4rem 2.2rem;
  grid-template-columns: repeat(12, 1fr);
  align-items: start;
}
.work-row .art-main { grid-column: 1 / 8; }
.work-row .art-side { grid-column: 9 / 13; margin-top: clamp(2rem, 8vh, 5rem); }
.work-row.alt .art-main { grid-column: 6 / 13; order: 2; }
.work-row.alt .art-side { grid-column: 1 / 5; order: 1; }
.work-row .art-main img, .work-row .art-side img { width: 100%; object-fit: cover; object-position: center 6%; height: auto; }
.work-row .art-main img { aspect-ratio: 4 / 5; }
.work-row .art-side img { aspect-ratio: 3 / 2; }
.work-row .meta { grid-column: 1 / 13; display: flex; flex-wrap: wrap; align-items: baseline; gap: 1rem 2rem; margin-top: 2.4rem; }
.work-row .meta h3 { font-size: var(--size-section); }
.work-row .meta .hook { max-width: 30em; color: color-mix(in srgb, var(--ink) 72%, transparent); font-size: 0.95rem; }
.work-row .counter { color: var(--lacquer); }

/* ---------- about preview / footer ---------- */

.about-preview {
  display: grid; grid-template-columns: minmax(200px, 340px) 1fr;
  gap: clamp(1.5rem, 5vw, 4rem); align-items: center;
  padding-block: clamp(3rem, 8vh, 6rem);
}
/* No grayscale filter here any more. The portraits are graded as a duotone
   between her ink and her paper, so the picture is made of the page's own two
   colours; a CSS grayscale pass would strip that warmth back out. */

.site-footer {
  background: var(--ink); color: var(--paper);
  padding: clamp(2.5rem, 7vh, 5rem) var(--gutter);
  display: flex; flex-wrap: wrap; gap: 2rem; justify-content: space-between; align-items: flex-end;
}
.site-footer a { border-bottom: 1px solid color-mix(in srgb, var(--paper) 40%, transparent); }
.site-footer a:hover { border-bottom-color: var(--digital); color: var(--digital); }
.site-footer .star { width: 1.6rem; }

/* ---------- project pages ---------- */

.project-head { padding: clamp(2.5rem, 7vh, 5rem) var(--gutter) 0; }
.project-head h1 { font-size: var(--size-title); max-width: 9em; letter-spacing: var(--track-title); margin-inline-start: -0.04em; }
.project-head .lead { max-width: var(--measure); margin-top: 1.6rem; font-size: 1.12rem; }
.project-hero { margin-top: clamp(2rem, 5vh, 3.5rem); }
/* fashion photography carries faces in the top third: crops bias upward, never center-behead */
.project-hero img { width: 100%; max-height: 88vh; object-fit: cover; object-position: center 6%; }

.spread { display: grid; grid-template-columns: repeat(12, 1fr); gap: 1.4rem; padding-block: clamp(1.6rem, 4vh, 3rem); }
.spread figure { position: relative; }
.spread figcaption { margin-top: 0.6rem; font-family: var(--font-mono); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.12em; color: color-mix(in srgb, var(--ink) 64%, transparent); }
.spread .w7 { grid-column: span 7; } .spread .w5 { grid-column: span 5; }
.spread .w8 { grid-column: span 8; } .spread .w4 { grid-column: span 4; }
.spread .w12 { grid-column: span 12; }
.spread .pull-up { margin-top: -14%; z-index: 1; box-shadow: 0 16px 44px rgba(26,26,26,0.16); }

.project-nav { display: flex; justify-content: space-between; padding: 2.2rem var(--gutter); border-top: 1px solid var(--rule); }

/* ---------- reveal motion (restrained) ---------- */

html.js .reveal { opacity: 0; transform: translateY(14px); transition: opacity 0.7s ease calc(var(--i, 0) * 70ms), transform 0.7s ease calc(var(--i, 0) * 70ms); }
html.js .reveal.in { opacity: 1; transform: none; }
/* image plates get a wipe instead of a slide (E03b) */
html.js figure.reveal { transform: none; clip-path: inset(0 0 100% 0); transition: clip-path 0.9s cubic-bezier(0.16, 1, 0.3, 1) calc(var(--i, 0) * 70ms); }
html.js figure.reveal img, html.js figure.reveal video { transform: scale(1.05); transition: transform 1.1s cubic-bezier(0.16, 1, 0.3, 1); }
html.js figure.reveal.in { clip-path: inset(0 0 0 0); }
html.js figure.reveal.in img, html.js figure.reveal.in video { transform: none; }
/* mono metadata fades only */
html.js p.caption.reveal, html.js .crumb.reveal { transform: none; }
@media (prefers-reduced-motion: reduce) {
  html.js .reveal, html.js figure.reveal { opacity: 1; transform: none; clip-path: none; transition: none; }
  html.js figure.reveal img, html.js figure.reveal video { transform: none; transition: none; }
}

/* ---------- responsive ---------- */

@media (max-width: 760px) {
  .work-row, .work-row.alt { display: flex; flex-direction: column; }
  .work-row .art-side { margin-top: 0; }
  .work-row.alt .art-main { order: 0; }
  .work-row .meta { margin-top: 0.6rem; }
  .about-preview { grid-template-columns: 1fr; }
  .spread { display: flex; flex-direction: column; }
  .spread .pull-up { margin-top: 0; box-shadow: none; }
  .site-nav { gap: 0.9rem; }
}

/* ---------- counters as system (E15) ---------- */
.page-counter {
  position: fixed; left: var(--gutter); bottom: 1.2rem; z-index: 30;
  font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.12em;
  color: color-mix(in srgb, var(--ink) 64%, transparent);
}
/* ---------- plate system (E10) ---------- */
.spread figure, .work-row figure {
  padding: clamp(6px, 0.9vw, 14px);
  background: color-mix(in srgb, var(--bone) 55%, var(--paper));
  outline: 1px solid var(--rule);
}
.spread figcaption { display: flex; align-items: baseline; gap: 0.8rem; }
.spread figcaption .pl { color: var(--lacquer); }
.spread figcaption::before { content: none; }
.spread figcaption .fill { flex: 1; border-bottom: 1px solid var(--rule); transform: translateY(-0.25em); }
/* grain: turbulence data URI, print texture over PDF crops */
body::after {
  content: ''; position: fixed; inset: 0; z-index: 80; pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
  opacity: 0.035; mix-blend-mode: multiply;
}
body.aurora::after { opacity: 0.05; mix-blend-mode: screen; }

/* ---------- work row hover choreography (E11) ---------- */
.work-row { position: relative; }
.work-row::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -1.6rem;
  height: 1px; background: var(--lacquer);
  transform: scaleX(0); transform-origin: left;
  transition: transform 0.5s cubic-bezier(0.65, 0, 0.35, 1);
}
.work-row:hover::after, .work-row:focus-visible::after { transform: scaleX(1); }
.work-row .meta h3 { transition: font-weight 0.35s ease; }
.work-row:hover .meta h3, .work-row:focus-visible .meta h3 { font-weight: 800; }
.work-row .counter { transition: transform 0.35s ease, color 0.35s ease; }
.work-row:hover .counter { transform: translateX(4px); }
.work-row .art-main img { transition: filter 0.4s ease; }
.work-row .art-side { transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1); }
.work-row .art-side img { filter: grayscale(1); transition: filter 0.4s ease; }
.work-row:hover .art-main img { filter: grayscale(1); }
.work-row:hover .art-side img { filter: grayscale(0); }
.work-row:hover .art-side { transform: translateY(-8px); }
@media (prefers-reduced-motion: reduce) {
  .work-row::after, .work-row .counter, .work-row .art-side { transition: none; transform: none; }
}
/* ---------- cursor plate (E12) ---------- */
.cursor-plate {
  position: fixed; left: 0; top: 0; z-index: 95; pointer-events: none;
  font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.14em;
  color: var(--lacquer); background: var(--paper);
  padding: 0.35rem 0.6rem; border: 1px solid var(--rule);
  opacity: 0; transition: opacity 0.2s ease;
  will-change: transform;
}
body.aurora .cursor-plate { color: var(--digital); background: var(--void); border-color: rgba(255,255,255,0.2); }
.cursor-plate.on { opacity: 1; }
@media (pointer: coarse) { .cursor-plate { display: none; } }

/* ---------- self-justifying wordmark (E05): each line sized to fill the measure ---------- */
.justify-block { display: flex; flex-direction: column; align-items: flex-start; max-width: 14ch; }
.justify-block .l { display: block; white-space: nowrap; line-height: 0.92; }
.justify-block .l .star { width: 0.16em; margin-left: 0.06em; }

/* ---------- language switch ---------- */
.site-footer .lang-switch {
  font-family: var(--font-mono); font-size: 0.72rem;
  text-transform: uppercase; letter-spacing: 0.1em;
  padding: 0.45rem 0.8rem; outline: 1px solid color-mix(in srgb, var(--paper) 35%, transparent);
  border-bottom: none; align-self: center;
  transition: background 0.2s ease, color 0.2s ease;
}
.site-footer .lang-switch:hover { background: var(--paper); color: var(--ink); }

/* ---------- about page: plates, ghost numerals, ledgers, quote ---------- */
.pillar-plate { position: relative; padding: 1.6rem 1.4rem 1.4rem; background: color-mix(in srgb, var(--bone) 55%, var(--paper)); outline: 1px solid var(--rule); overflow: hidden; }
.pillar-plate .ghost { position: absolute; right: -0.4rem; top: -1.6rem; font-family: var(--font-display); font-weight: 800; font-size: 7rem; line-height: 1; color: color-mix(in srgb, var(--ink) 6%, transparent); user-select: none; }
.pillar-plate h3, .pillar-plate p { position: relative; }
.ledger { list-style: none; display: flex; flex-direction: column; }
.ledger li { display: grid; grid-template-columns: 5.5em 1fr; gap: 0.2rem 1.6rem; padding-block: 1.1rem; border-bottom: 1px solid var(--rule); align-items: baseline; }
.ledger .yr { font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.1em; color: var(--lacquer); }
.ledger .what { grid-column: 2; font-family: var(--font-display); font-weight: 750; text-transform: uppercase; font-size: clamp(1rem, 2vw, 1.25rem); line-height: 1.15; }
.ledger .caption { grid-column: 2; }
.ledger .lead-rule { display: none; }
.quote-plate { background: var(--sky); padding: clamp(3rem, 9vh, 5.5rem) var(--gutter); margin-block: clamp(2.5rem, 7vh, 4.5rem); }
.quote-plate p.q { font-family: var(--font-display); font-weight: 750; text-transform: uppercase; font-size: clamp(1.8rem, 4.6vw, 3.4rem); line-height: 1.02; letter-spacing: var(--track-title); max-width: 14em; }
.quote-plate .caption { margin-top: 1rem; }
.about-plates { display: grid; grid-template-columns: repeat(4, 1fr); grid-auto-rows: 1fr; gap: 1.2rem; }
.about-plates .pillar-plate { min-height: 13.5rem; display: flex; flex-direction: column; }
.pillar-plate h3 { font-size: clamp(1rem, 1.6vw, 1.3rem); overflow-wrap: break-word; hyphens: auto; }
@media (max-width: 1099px) { .about-plates { grid-template-columns: 1fr 1fr; } .pillar-plate h3 { font-size: clamp(1rem, 2.6vw, 1.25rem); } }
@media (max-width: 640px) {
  .about-plates { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; gap: 0.9rem; padding-bottom: 0.8rem; margin-inline: calc(var(--gutter) * -1); padding-inline: var(--gutter); scrollbar-width: none; }
  .about-plates::-webkit-scrollbar { display: none; }
  .about-plates .pillar-plate { flex: 0 0 76vw; scroll-snap-align: center; min-height: 10rem; }
  .pillar-plate h3 { font-size: 1.15rem; }
}


/* header wraps on phones: wordmark row, then nav row, nothing crowds */
@media (max-width: 700px) {
  .site-header { flex-wrap: wrap; gap: 0.6rem 0; padding-block: 0.8rem; }
  .site-header .wordmark { flex: 1 0 100%; }
  .site-nav { flex: 1 0 100%; flex-wrap: wrap; justify-content: flex-start; gap: 0.5rem 1.3rem; }
  .site-nav a { font-size: 0.68rem; letter-spacing: 0.08em; white-space: nowrap; }
}

/* tonal grade tokens, shared by every page that shows her films */
.grade { filter: grayscale(1) brightness(var(--b, 1)) contrast(1.08); }
.v01 { --b: 1.24 } .v02 { --b: 0.68 } .v03 { --b: 0.92 } .v04 { --b: 1.58 }
.v05 { --b: 2.2 } .v06 { --b: 2.2 } .v07 { --b: 0.57 } .v08 { --b: 0.58 }
.v09 { --b: 2.14 } .v10 { --b: 0.73 } .v11 { --b: 0.77 }
/* full-bleed motion band: a room divider that breathes */
.motion-band { position: relative; width: 100vw; margin-left: calc(50% - 50vw); margin-block: clamp(2.5rem, 7vh, 4.5rem); background: var(--void); }
/* motion bands crop to a band, so bias upward: a figure's head must survive */
.motion-band video { width: 100%; max-height: 52vh; object-fit: cover; object-position: center 22%; display: block; opacity: 0.9; }
html.js figure.motion-band.reveal video { transform: none; }
.motion-band figcaption { position: absolute; left: var(--gutter); bottom: 1.2rem; z-index: 1; font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--paper); }
.motion-band::after { content: ''; position: absolute; inset: 55% 0 0 0; background: linear-gradient(to bottom, transparent, rgba(6,6,6,0.65)); }

/* a11y-hardening */
/* Access-and-interaction pass. Every rule below exists to serve main.js,
   aurora.js or threshold.js (skip link, motion toggle, chapter offset,
   measured contrast), styled only with tokens and vocabulary already used
   above (mono caption, star, paper/lacquer, void) per the no-redesign law. */
/* Stray horizontal scroll guard: full-bleed sections (negative gutter
   margins) and transient reveal scale must never widen the page itself.
   Measured 2026-08-09: about page scrollWidth 395 vs 375 viewport. */
html { overflow-x: clip; }
/*
   Nothing above this line is edited; overrides win on specificity or,
   within this same file, on source order. */

/* ---------- skip link (main.js injects as first body child) ---------- */
.skip-link {
  position: fixed; top: 0; left: -9999px; z-index: 200;
  background: var(--paper); color: var(--ink);
  font-family: var(--font-mono); font-size: var(--size-caption);
  text-transform: uppercase; letter-spacing: 0.12em;
  padding: 0.85rem 1.3rem;
  outline: 2px solid var(--lacquer); outline-offset: -2px;
}
/* :focus, not :focus-visible, on purpose: a skip link has to surface on
   whatever focus path reaches it first, not only a detected keyboard modality. */
.skip-link:focus { left: 0; }

/* ---------- motion pause control (main.js appends to .site-footer) ---------- */
.site-footer .motion-toggle {
  display: inline-flex; align-items: center; gap: 0.5rem;
  min-width: 44px; min-height: 44px;
  padding: 0.6rem 0.9rem;
  background: none; border: none; color: inherit; cursor: pointer;
  outline: 1px solid color-mix(in srgb, var(--paper) 35%, transparent);
  align-self: center;
  transition: background 0.2s ease, color 0.2s ease;
}
.site-footer .motion-toggle:hover { background: var(--paper); color: var(--ink); }
.site-footer .motion-toggle .star { width: 0.9em; height: 0.9em; flex: 0 0 auto; }

/* motion-off: stop what CSS can reach everywhere; main.js pauses
   video[data-loop] directly and force-hides the residue canvas here because
   residue.js (outside this fence) does not read window.__motionOff itself. */
html.motion-off * { animation-play-state: paused !important; transition: none !important; }
html.motion-off video { display: var(--keep, block); }
html.motion-off canvas[aria-hidden] { display: none; }

/* ---------- chapter bar sits below the (possibly retreated) header ---------- */
/* the header only retreats on scroll-down, so overlap can only happen when
   scrolling back up; this offset keeps the sticky chapter bar clear of it. */
:root { --header-h: 4.65rem; }
@media (max-width: 700px) { :root { --header-h: 6.4rem; } }
body.aurora .chapter-head { top: var(--header-h); }
body.aurora .chapter { scroll-margin-top: var(--header-h); }

/* ---------- measured contrast ----------
   WCAG relative-luminance formula; color-mix(in srgb, C X%, transparent) on a
   solid backdrop is alpha composited as X%*C + (1-X%)*backdrop before the
   ratio (Llight+0.05)/(Ldark+0.05) is taken. Every color-mix ink-on-paper
   text use in the codebase, plus every solid smoke-on-void text use:

   ink #1A1A1A on paper #F5F1EA
     .page-counter          0.70rem  55% -> ~#7D7B78 -> 3.77:1  FAIL -> raised to 70% -> ~#5C5B58 -> 6.08:1  PASS
     .spread figcaption     0.70rem  60% -> ~#72706D -> 4.39:1  FAIL -> raised to 70% -> ~#5C5B58 -> 6.08:1  PASS
     .work-row .meta .hook  0.95rem  72% -> ~#575654 -> 6.49:1  PASS -> left unchanged, already clears 4.5:1
   (no color-mix ink 62% instance exists anywhere in the codebase; 55%, 60%
   and 72% are the only sub-1rem/near-1rem ink-color-mix text uses found.)

   smoke #B9B9B9 on void #0C0C0C (solid, not color-mix)
     .x-hero .caption, .slot .caption, .works-list .status, all sub-1rem
       -> 9.97:1  PASS -> left unchanged

   Caveat: .page-counter is position:fixed and can sit over photographic
   content, not only flat paper; the ratio above is against the flat --paper
   backdrop the task specified and is not re-verified per-image. */
.page-counter { color: color-mix(in srgb, var(--ink) 70%, transparent); }
.spread figcaption { color: color-mix(in srgb, var(--ink) 70%, transparent); }

/* ---------- the original spreads, beneath each project (2026-08-10) ----------
   The pages her editorial crops were cut from, shown as the stratum underneath.
   Paper mood, existing vocabulary: bone plates, lacquer PL numbering, hairlines,
   and the same scroll-snap strip the about-plates already use on phones. */
.spread-archive { padding-block: clamp(2.5rem, 7vh, 4.5rem); border-top: 1px solid var(--rule); margin-top: 2rem; }
.spread-archive .act-label { margin-bottom: 1rem; }
.spread-strip {
  display: flex; gap: 0.9rem; overflow-x: auto; scroll-snap-type: x mandatory;
  padding-bottom: 0.8rem; margin-inline: calc(var(--gutter) * -1); padding-inline: var(--gutter);
  scrollbar-width: none;
}
.spread-strip::-webkit-scrollbar { display: none; }
.spread-strip:focus-visible { outline: 2px solid var(--lacquer); outline-offset: 4px; }
.spread-sheet { flex: 0 0 auto; width: min(60vw, 520px); scroll-snap-align: center; margin: 0; }
.spread-sheet a { display: block; padding: clamp(5px, 0.7vw, 10px); background: color-mix(in srgb, var(--bone) 55%, var(--paper)); outline: 1px solid var(--rule); }
.spread-sheet a:hover { outline-color: var(--lacquer); }
.spread-sheet a:focus-visible { outline: 2px solid var(--lacquer); outline-offset: 2px; }
.spread-sheet img { width: 100%; height: auto; display: block; }
.spread-sheet figcaption { margin-top: 0.5rem; display: flex; gap: 0.6rem; align-items: baseline; font-family: var(--font-mono); font-size: 0.64rem; letter-spacing: 0.1em; text-transform: uppercase; color: color-mix(in srgb, var(--ink) 64%, transparent); }
.spread-sheet .pl { color: var(--lacquer); }
@media (max-width: 700px) { .spread-sheet { width: 84vw; } }

/* Her portrait on the commission page. Small and set to the side: the page's
   job is the form, so she is present without competing with it. The picture is
   graded to the paper, so no frame or border is needed to seat it. */
.atelier-portrait { margin: 2rem 0 0; max-width: 200px; }
.atelier-portrait img { width: 100%; height: auto; display: block; }
.atelier-portrait figcaption { margin-top: 0.6rem; color: color-mix(in srgb, var(--ink) 60%, transparent); }
@media (max-width: 700px) { .atelier-portrait { max-width: 60vw; margin-top: 1.6rem; } }

/* Visible to screen readers only. Used by the exhibition carousels, which
   JavaScript makes keyboard focusable, so a reader lands on them and needs to
   hear which room they control and how to drive them. */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
