/* ==========================================================================
   siris-v2.css — the v2 design system layer
   --------------------------------------------------------------------------
   Load AFTER css/siris.css. This file does not replace siris.css; it adds the
   dark-ground system that /ordinary and /process moved to, and collapses the
   drifted values from those two pages into one vocabulary.

   Everything here is specified in DESIGN-SPEC.md. If you need a value that
   is not here, add it to the spec first.

   Do not add a second accent colour. Do not add spacing values outside the
   --sp-* scale inherited from siris.css.
   ========================================================================== */

:root{

  /* ---- dark ground ramp (§2) -------------------------------------------
     Collapsed from seven near-identical near-blacks found across
     OrdinaryV2.html and esp-site.html. */
  --ink-000:#0a0806;   /* cinema black — full-bleed stages, film sections */
  --ink-050:#0d0b09;   /* page ground for dark pages                      */
  --ink-100:#16130f;   /* "the wall" — default dark surface               */
  --ink-150:#1d1915;   /* raised surface, cards, hover states             */
  --ink-200:#241f19;   /* hairline borders on dark                        */

  /* ---- paper (text on dark, ground on light) ---- */
  --paper-100:#f7f5f0; /* warm near-white — light page ground             */
  --paper-200:#f2ede3; /* primary text on dark                            */
  --paper-300:#f6f2ea; /* display headings on dark                        */
  /* --gold:#9d8a5a is inherited from siris.css. The only accent. */

  /* ---- text opacity ladder on dark. Use these, not ad-hoc rgba(). ---- */
  --on-dark-1:rgba(242,237,227,1);    /* primary body      */
  --on-dark-2:rgba(242,237,227,.62);  /* secondary/caption */
  --on-dark-3:rgba(242,237,227,.45);  /* eyebrow/meta      */
  --on-dark-4:rgba(242,237,227,.12);  /* hairline/disabled */

  /* ---- type scale (§3.2) — collapsed from 30 ad-hoc clamp() values ---- */
  --t-hero:    clamp(38px,5.5vw,68px);
  --t-section: clamp(30px,3.8vw,58px);
  --t-sub:     clamp(23px,2.4vw,38px);
  --t-lead:    clamp(19px,1.7vw,23px);
  --t-body:    clamp(17px,1.2vw,21px);

  /* ---- motion (§4) ----
     --ease is the house curve. It appears independently in BOTH source
     pages, which is the strongest evidence in the codebase of deliberate
     shared intent. Use it for every entrance and reveal. */
  --ease:      cubic-bezier(.19,1,.22,1);
  /* A SEPARATE CURVE FOR TEXT ARRIVING.
     --ease above is cubic-bezier(.19,1,.22,1): a very heavy ease-out that
     dumps roughly 80% of its travel into the first 15% of its duration and
     then crawls. On a picture that reads as a graceful settle. On a
     paragraph it reads as a snap followed by nothing, which is why the
     archive entries and the exhibition rows on the home page felt like the
     text was being flung into place faster than you could start reading it.
     This spreads the motion evenly across the whole duration instead, so a
     line of text arrives at a readable pace rather than appearing and then
     drifting. */
  --ease-text: cubic-bezier(.22,.61,.36,1);
  --ease-ui:   cubic-bezier(.4,0,.15,1);
  --dur-ui:    400ms;
  --dur-reveal:1.3s;
  --dur-slow:  2.4s;

  /* ---- chrome contract (§7) ----
     BUG FIX: OrdinaryV2.html referenced --page-header-h but nothing ever
     defined it, so every consumer silently used its 93px fallback. Defined
     here once. Pages with a subnav set --page-header-h:var(--header-h-sub)
     on <body>. */
  /* ---- REGISTERS (§ theme architecture) --------------------------------
     These are FIXED. They never change with the light/dark switch, and that
     is the whole point of them.

     The site has three grounds, and they mean different things:

       paper  the reading surface. This one DOES follow the theme: cream in
              light, warm charcoal in dark. It is handled by the plaster
              tokens, which the theme redefines.
       wall   a gallery wall. Always dark, in both themes, because it is the
              ground artwork hangs on and a painting does not want a white
              wall behind it at 2am any more than it does at noon.
       void   cinema black. Film, full-bleed stages, the inside of a frame.

     THE BUG THIS FIXES. Sections that are dark by intent were written as
     background:var(--umber-900) — a palette colour that also happens to be
     the body text colour on a light page. When the dark theme inverted
     --umber-900 so that text would go pale, those sections inverted with it:
     a cream panel with cream text hard-coded on top of it. Invisible.

     A colour used to mean "the wall" and a colour used to mean "the ink"
     cannot be the same token, however similar they look. These are the wall.
     Nothing inverts them. */
  --wall:      #16130f;   /* the gallery wall — dark in BOTH themes  */
  --wall-deep: #0c0a07;   /* the same wall, one step further in      */
  --wall-ink:  #f5f1e8;   /* what is legible against it              */
  --wall-ink-2:rgba(245,241,232,.78);
  --wall-ink-3:rgba(245,241,232,.52);
  --wall-line: rgba(245,241,232,.16);
  --wall-accent:#c8b182;

  /* A solid chip — a button, a badge, the skip link. It must always read as
     a filled block against the page, so in light mode it is dark-on-light and
     in dark mode it inverts to light-on-dark. Declared once here; the theme
     flips the pair together so the two halves can never drift apart. */
  --chip-bg: #1a170e;
  --chip-fg: #f5f1e8;

  --header-h:52px;
  --header-h-sub:93px;
  --page-header-h:var(--header-h);

  /* ---- measures ---- */
  --measure-essay:58ch;   /* long-form reading, from OrdinaryV2 */

  /* ---- section rhythm (§5) ---- */
  --section-y:clamp(80px,12vh,180px);
}

/* Pages that carry a subnav under the main nav opt in with this class so
   nothing hard-codes 93px. */
body.has-subnav{ --page-header-h:var(--header-h-sub); }


/* ==========================================================================
   DARK GROUND
   Opt in per page with <body class="v2-dark">. Feature pages only —
   /, /ordinary, /process, /film. Utility pages stay on siris.css light.
   ========================================================================== */

body.v2-dark{
  background:var(--ink-050);
  color:var(--on-dark-1);
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
}

body.v2-dark ::selection{ background:var(--gold); color:var(--ink-000); }


/* ==========================================================================
   TYPOGRAPHY PRIMITIVES
   ========================================================================== */

/* The eyebrow — the site's most repeated element. Both benchmark pages use
   this construction identically. Never track below .22em. */
.v2-eyebrow{
  font-family:var(--font-sans);
  font-size:12px;
  font-weight:var(--w-normal,400);
  letter-spacing:.32em;
  text-transform:uppercase;
  color:var(--on-dark-3);
  margin:0 0 var(--sp-2);
}
.v2-eyebrow--tight{ letter-spacing:.24em; }
.v2-eyebrow--wide { letter-spacing:.4em;  }

.v2-hero-title{
  font-family:var(--font-serif);
  font-size:var(--t-hero);
  line-height:1.12;
  letter-spacing:.02em;
  color:var(--paper-300);
  margin:0;
}

.v2-section-title{
  font-family:var(--font-serif);
  font-size:var(--t-section);
  line-height:1.12;
  letter-spacing:.02em;
  color:var(--paper-300);
  margin:0 0 var(--sp-3);
}

.v2-sub{
  font-family:var(--font-serif);
  font-style:italic;
  font-size:var(--t-sub);
  line-height:1.3;
  color:var(--on-dark-1);
  margin:0 0 var(--sp-2);
}

.v2-lead{
  font-family:var(--font-serif);
  font-size:var(--t-lead);
  line-height:1.5;
  color:var(--on-dark-1);
  margin:0 0 var(--sp-2);
}

.v2-body{
  font-family:var(--font-longform);
  font-size:var(--t-body);
  line-height:var(--lh-body,1.65);
  color:var(--on-dark-1);
  max-width:var(--measure-essay);
}

.v2-caption{
  font-family:var(--font-serif);
  font-style:italic;
  font-size:16px;
  line-height:1.75;
  color:var(--on-dark-2);
}

.v2-rule{
  display:block; width:44px; height:1px; border:0;
  background:var(--gold); opacity:.6;
  margin:var(--sp-2) auto;
}


/* ==========================================================================
   LAYOUT PRIMITIVES
   Composition rule (§5): one focal object per screen, centred, with air.
   ========================================================================== */

.v2-section{
  padding-block:var(--section-y);
  padding-inline:var(--sp-2);
}

.v2-inner{
  max-width:var(--w-content,1480px);
  margin-inline:auto;
}
.v2-inner--essay{ max-width:var(--measure-essay); }
.v2-inner--mid  { max-width:1040px; }

/* Full-viewport stage. svh, not vh — vh is wrong under mobile browser
   chrome and was the cause of the hero tucking under the header. */
.v2-stage{
  position:relative;
  min-height:100svh;
  display:grid;
  place-items:center;
  box-sizing:border-box;
  padding-top:var(--page-header-h);
  padding-bottom:var(--sp-2);
  background:var(--ink-000);
  overflow:hidden;
}

.v2-stage__media{
  position:absolute; inset:0;
  z-index:0;
}
.v2-stage__media img,
.v2-stage__media video{
  width:100%; height:100%;
  object-fit:cover;
  display:block;
}
/* Warm falloff so display type always has ground to sit on, regardless of
   what the artwork behind it is doing. */
.v2-stage__media::after{
  content:""; position:absolute; inset:0;
  background:
    radial-gradient(ellipse 70% 60% at 50% 45%, rgba(0,0,0,0) 0%, rgba(10,8,6,.55) 78%),
    linear-gradient(180deg, rgba(10,8,6,.5) 0%, rgba(10,8,6,0) 28%, rgba(10,8,6,.72) 100%);
}
.v2-stage__body{ position:relative; z-index:1; text-align:center; padding-inline:var(--sp-2); }

/* Contained artwork on a stage — never let the painting hide under the
   fixed header stack. */
.v2-art{
  display:block;
  max-width:95vw;
  max-height:calc(100svh - var(--page-header-h) - var(--sp-2));
  width:auto; height:auto;
  margin-inline:auto;
}

/* Projector beam — the warm glow thrown from above on the film section.
   Anchored to the section, not its inner wrapper, so the section's own top
   padding is lit too. */
.v2-beam{
  position:absolute; top:0; left:50%; width:150%; height:52%;
  transform:translateX(-50%); z-index:0; pointer-events:none;
  background:radial-gradient(ellipse 60% 75% at 50% 0%, rgba(157,138,90,.3) 0%, transparent 72%);
}


/* ==========================================================================
   COMPONENTS
   ========================================================================== */

.v2-cta{
  display:inline-block;
  font-family:var(--font-sans);
  font-size:12px;
  letter-spacing:.28em;
  text-transform:uppercase;
  color:var(--paper-200);
  text-decoration:none;
  padding-bottom:6px;
  border-bottom:1px solid var(--on-dark-4);
  transition:border-color var(--dur-ui) var(--ease-ui),
             color var(--dur-ui) var(--ease-ui);
}
.v2-cta:hover,
.v2-cta:focus-visible{ color:var(--gold); border-bottom-color:var(--gold); }

.v2-card{
  display:block;
  text-decoration:none;
  color:inherit;
  background:var(--ink-100);
  border:1px solid var(--ink-200);
  transition:background var(--dur-ui) var(--ease-ui),
             border-color var(--dur-ui) var(--ease-ui),
             transform var(--dur-ui) var(--ease-ui);
}
.v2-card:hover,
.v2-card:focus-visible{
  background:var(--ink-150);
  border-color:var(--gold);
  transform:translateY(-2px);
}
.v2-card__thumb{ aspect-ratio:4/3; overflow:hidden; background:var(--ink-000); }
.v2-card__thumb img{ width:100%; height:100%; object-fit:cover; display:block;
  transition:transform var(--dur-reveal) var(--ease); }
.v2-card:hover .v2-card__thumb img{ transform:scale(1.03); }
.v2-card__body{ padding:var(--sp-2); }
.v2-card__title{ font-family:var(--font-serif); font-size:var(--t-lead);
  line-height:1.25; color:var(--paper-300); margin:0 0 8px; }
.v2-card__meta{ font-family:var(--font-sans); font-size:12px; letter-spacing:.12em;
  text-transform:uppercase; color:var(--on-dark-3); margin:0; }

.v2-grid{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(280px,1fr));
  gap:var(--sp-2);
}

/* Video frame — a screen floating in the dark, sized off the room rather
   than the page's max-width. */
.v2-frame{
  position:relative; z-index:1;
  background:#000;
  box-shadow:0 60px 160px rgba(0,0,0,.8), 0 0 0 1px rgba(244,239,231,.08);
  margin-inline:auto;
}
.v2-frame--wide{ width:min(72vw,1100px); }
.v2-frame--4x3 { width:min(52.9vw,644px); }
.v2-frame__inner{ position:relative; width:100%; aspect-ratio:16/9; background:#000; }
.v2-frame--4x3 .v2-frame__inner{ aspect-ratio:4/3; }
/* The iframe itself must carry the dark ground, not just its container.
   A blocked or slow Vimeo embed renders as the browser's default WHITE
   rectangle — blinding on a near-black page, and it happens to anyone with
   a privacy extension. Failure should degrade to black. */
.v2-frame__inner iframe,
.v2-frame__inner video{
  position:absolute; inset:0; width:100%; height:100%; border:0;
  background:#000; color-scheme:dark;
}


/* ==========================================================================
   REVEALS
   Opt in with .v2-reveal; js adds .is-in when the element enters view.
   Degrades to visible if JS never runs — never hide content permanently.
   ========================================================================== */

.v2-reveal{
  opacity:0;
  transform:translateY(18px);
  transition:opacity var(--dur-reveal) var(--ease),
             transform var(--dur-reveal) var(--ease);
  will-change:opacity,transform;
}
/* Drop the compositing layer once the reveal has played. Leaving
   will-change set permanently pins a layer per element for the life of the
   page — it also makes full-page screenshot capture drop these elements,
   which is how this was caught. */
.v2-reveal.is-in{ opacity:1; transform:none; will-change:auto; }
.no-js .v2-reveal{ opacity:1; transform:none; }


/* ==========================================================================
   ACCESSIBILITY
   ========================================================================== */

.v2-skip{
  position:absolute; left:-9999px; top:0;
  background:var(--ink-100); color:var(--paper-200);
  padding:12px 20px; z-index:9999;
  font-family:var(--font-sans); font-size:14px;
}
.v2-skip:focus{ left:12px; top:12px; }

body.v2-dark a:focus-visible,
body.v2-dark button:focus-visible{
  outline:2px solid var(--gold);
  outline-offset:3px;
}

.v2-visually-hidden{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}


/* ==========================================================================
   BREAKPOINTS (§6)
   ========================================================================== */

@media (max-width:900px){
  :root{ --section-y:clamp(56px,9vh,110px); }
  .v2-frame--wide,
  .v2-frame--4x3{ width:min(92vw,900px); }
  .v2-grid{ grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); }
}

@media (max-width:560px){
  .v2-eyebrow{ font-size:11px; letter-spacing:.26em; }
  .v2-section{ padding-inline:var(--sp-1); }
}

/* Landscape phones on full-viewport stages — esp-site.html already handled
   this and it was correct. A 100svh stage on a 480px-tall viewport with a
   52px header leaves nothing for content. */
@media (max-height:520px) and (max-width:900px){
  .v2-stage{ min-height:auto; padding-block:calc(var(--page-header-h) + 24px) 48px; }
  .v2-art{ max-height:none; }
}


/* ==========================================================================
   REDUCED MOTION — mandatory, must be last (§4)
   ========================================================================== */

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.01ms !important;
    scroll-behavior:auto !important;
  }
  .v2-reveal{ opacity:1 !important; transform:none !important; }
}


/* ==========================================================================
   PAGE MODULES
   These restyle EXISTING markup rather than requiring the HTML to be
   rewritten. Six sitter pages share one structure; giving each its own
   hand-built page is how a site drifts. One block here, two lines per page.
   ========================================================================== */

/* ---- sitter pages: /ordinary/{name} ------------------------------------ */

body.v2-dark .sitter-hero{
  background:var(--ink-000);
  min-height:100svh;
  display:grid; place-items:center;
  box-sizing:border-box;
  padding:calc(var(--page-header-h) + var(--sp-2)) var(--sp-2) var(--sp-2);
}
body.v2-dark .sitter-hero img{
  max-width:min(92vw,760px);
  max-height:calc(100svh - var(--page-header-h) - var(--sp-3));
  width:auto; height:auto; display:block;
  box-shadow:0 60px 160px rgba(0,0,0,.7);
}

body.v2-dark .sitter-body{ background:var(--ink-100); padding-block:var(--section-y); }
body.v2-dark .sitter-inner{
  max-width:var(--measure-essay);
  margin-inline:auto; padding-inline:var(--sp-2);
}
body.v2-dark .sitter-eyebrow{
  font-family:var(--font-sans); font-size:12px; letter-spacing:.32em;
  text-transform:uppercase; color:var(--on-dark-3); margin:0 0 var(--sp-2);
}
body.v2-dark .sitter-name{
  font-family:var(--font-serif); font-size:var(--t-hero); line-height:1.12;
  letter-spacing:.02em; color:var(--paper-300); margin:0 0 var(--sp-3);
}
body.v2-dark .sitter-subtitle{
  font-family:var(--font-serif); font-style:italic; font-size:var(--t-lead);
  color:var(--on-dark-2); margin:calc(var(--sp-3) * -1) 0 var(--sp-3);
}
body.v2-dark .sitter-letter{
  font-family:var(--font-longform); font-size:var(--t-body);
  line-height:var(--lh-body,1.65); color:var(--on-dark-1);
}
body.v2-dark .sitter-letter p{ margin:0 0 var(--sp-2); }
body.v2-dark .sitter-letter p:first-of-type::first-letter{
  float:left; font-family:var(--font-serif); font-size:3.4em;
  line-height:.86; padding:.06em .12em 0 0; color:var(--gold);
}
body.v2-dark .sitter-letter strong{ color:var(--paper-300); font-weight:var(--w-normal,400); }
body.v2-dark .sitter-letter em{ color:var(--on-dark-2); }

body.v2-dark .colophon{
  margin:var(--sp-4) 0 0; padding-top:var(--sp-2);
  border-top:1px solid var(--on-dark-4);
  display:grid; grid-template-columns:repeat(auto-fit,minmax(140px,1fr));
  gap:var(--sp-2);
}
body.v2-dark .colophon dt{
  font-family:var(--font-sans); font-size:11px; letter-spacing:.24em;
  text-transform:uppercase; color:var(--on-dark-3); margin:0 0 6px;
}
body.v2-dark .colophon dd{
  font-family:var(--font-serif); font-size:16px;
  color:var(--on-dark-1); margin:0;
}
body.v2-dark .sitter-enquire{ margin-top:var(--sp-4); }

/* ---- about ------------------------------------------------------------- */

body.v2-dark .about-body{ background:var(--ink-050); padding-block:var(--section-y); }
body.v2-dark .about-cols{
  display:grid; grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr);
  gap:clamp(32px,6vw,96px); align-items:start;
  max-width:1180px; margin-inline:auto; padding-inline:var(--sp-2);
}
body.v2-dark .about-cols__img img{ width:100%; height:auto; display:block; }
body.v2-dark .about-cols__text{
  font-family:var(--font-longform); font-size:var(--t-body);
  line-height:var(--lh-body,1.65); color:var(--on-dark-1);
}
body.v2-dark .about-cols__text p{ margin:0 0 var(--sp-2); }

body.v2-dark .cv{
  max-width:1180px; margin:var(--section-y) auto 0;
  padding-inline:var(--sp-2);
}
body.v2-dark .cv__head{
  font-family:var(--font-sans); font-size:12px; letter-spacing:.32em;
  text-transform:uppercase; color:var(--on-dark-3);
  margin:var(--sp-3) 0 var(--sp-2);
  padding-bottom:var(--sp-1); border-bottom:1px solid var(--on-dark-4);
}
body.v2-dark .cv__list{ list-style:none; margin:0; padding:0; }
body.v2-dark .cv__list li{
  font-family:var(--font-serif); font-size:16px; line-height:1.7;
  color:var(--on-dark-2); padding:6px 0;
}
body.v2-dark .cv__contact a{ color:var(--gold); }

/* ---- contact ----------------------------------------------------------- */

body.v2-dark .arch-hero{ background:var(--ink-000); }
body.v2-dark .section{ padding-block:var(--section-y); }
body.v2-dark .section--air{ background:var(--ink-100); }
body.v2-dark .t-lead{
  font-family:var(--font-serif); font-size:var(--t-lead);
  line-height:1.5; color:var(--on-dark-1);
}
body.v2-dark .eyebrow{
  font-family:var(--font-sans); font-size:12px; letter-spacing:.32em;
  text-transform:uppercase; color:var(--on-dark-3);
}
body.v2-dark .ml-input{
  background:transparent; border:0; border-bottom:1px solid var(--on-dark-4);
  color:var(--on-dark-1); font-family:var(--font-sans); font-size:15px;
  padding:10px 0; width:100%;
}
body.v2-dark .ml-input:focus{ outline:0; border-bottom-color:var(--gold); }
body.v2-dark .ml-btn{
  background:transparent; border:0; border-bottom:1px solid var(--on-dark-4);
  color:var(--paper-200); font-family:var(--font-sans); font-size:12px;
  letter-spacing:.28em; text-transform:uppercase; padding:10px 0; cursor:pointer;
  transition:color var(--dur-ui) var(--ease-ui), border-color var(--dur-ui) var(--ease-ui);
}
body.v2-dark .ml-btn:hover{ color:var(--gold); border-bottom-color:var(--gold); }

@media (max-width:900px){
  body.v2-dark .about-cols{ grid-template-columns:1fr; }
  body.v2-dark .sitter-hero{ min-height:auto; }
}

/* Legacy heading classes from siris.css, claimed for the dark ground.
   Without these, /about and /contact fall back to the light system's
   sans-serif heading treatment — caught in screenshot review, not by
   any error, which is exactly why the review step is not optional. */
body.v2-dark .section-title,
body.v2-dark h1:not([class]),
body.v2-dark h2:not([class]){
  font-family:var(--font-serif);
  font-size:var(--t-section);
  font-weight:var(--w-normal,400);
  line-height:1.12;
  letter-spacing:.02em;
  color:var(--paper-300);
  margin:0 0 var(--sp-3);
}
body.v2-dark .quote{
  font-family:var(--font-serif); font-style:italic;
  font-size:var(--t-sub); line-height:1.32;
  color:var(--paper-300);
}
body.v2-dark a{ color:var(--gold); }
body.v2-dark .site-footer{ background:var(--ink-000); }


/* ==========================================================================
   THE GRAMMAR — visual implementation of DESIGN-SPEC.md Part One.
   Paired with js/siris-v2.js. Nothing here hides content unless the engine
   has already confirmed it can reveal it (the .v2-motion gate on <html>).
   ========================================================================== */

/* §1.2 — one image, one line, one invitation. A screen in the void. */
.v2-screen{
  position:relative;
  min-height:100svh;
  display:grid;
  place-items:center;
  box-sizing:border-box;
  padding:calc(var(--page-header-h) + var(--sp-3)) var(--sp-2) var(--sp-5);
  background:var(--ink-000);
  overflow:hidden;
}
.v2-screen__field{ position:absolute; inset:0; z-index:0; overflow:hidden; }
.v2-screen__field img,
.v2-screen__field video{ width:100%; height:100%; object-fit:cover; display:block; }
.v2-screen__body{ position:relative; z-index:2; width:100%; max-width:var(--w-content,1480px); }

/* §1.1 — the void. More darkness than feels comfortable; the artwork is the
   only light source. This scrim is what makes the image "arrive". */
.v2-screen__veil{
  position:absolute; inset:0; z-index:1; pointer-events:none;
  background:
    radial-gradient(ellipse 75% 65% at 50% 45%, rgba(0,0,0,0) 0%, rgba(10,8,6,.5) 80%),
    linear-gradient(180deg, rgba(10,8,6,.62) 0%, rgba(10,8,6,0) 30%, rgba(10,8,6,.55) 72%, rgba(10,8,6,.95) 100%);
}

/* §1.5 emergence — the subject rises out of near-black as you scroll.
   --emerge is written by js/siris-v2.js from scroll position, so the viewer
   controls the pace of the arrival. Defaults to 1 (fully lit) if JS never
   runs, so the page is never stuck in darkness. */
[data-v2-emerge]{ --emerge:1; }
.v2-motion [data-v2-emerge]{ --emerge:0; }
[data-v2-emerge] .v2-screen__field img,
[data-v2-emerge] .v2-screen__field video{
  opacity:calc(.06 + var(--emerge) * .94);
  transform:scale(calc(1.10 - var(--emerge) * .10));
  transition:opacity 120ms linear, transform 120ms linear;
}

/* §1.5 immersion — a fixed aperture; the artwork travels beneath it. */
.v2-aperture{ position:relative; background:var(--ink-000); }
.v2-aperture__frame{
  position:sticky; top:0;
  height:100svh;
  display:grid; place-items:center;
  box-sizing:border-box;
  padding:calc(var(--page-header-h) + var(--sp-2)) var(--sp-2) var(--sp-2);
  overflow:hidden;
}
/* The work held at arm's length — contained, floating in black, the way you
   first see a painting across a gallery (§1.1). */
.v2-aperture__window{
  position:relative;
  width:min(64vw,900px);
  aspect-ratio:16/10;
  overflow:hidden;
  background:var(--ink-000);
  box-shadow:0 60px 180px rgba(0,0,0,.9);
}
.v2-aperture__window img{
  position:absolute; inset:0;
  width:100%; height:100%; object-fit:cover;
  transform-origin:50% 45%;
  will-change:transform;
}
.v2-aperture__caption{ position:relative; z-index:2; text-align:center; }
@media (max-width:900px){
  .v2-aperture__window{ width:min(92vw,700px); aspect-ratio:4/3; }
}

/* §1.4 — testimony wipes; everything else fades. */
[data-v2-reveal]{ opacity:1; transform:none; }
.v2-motion [data-v2-reveal]{
  opacity:0;
  /* 20px of travel was enough to read as the text sliding while you were
     trying to start on it. 12px still registers as an arrival without
     being a movement you have to wait out. */
  transform:translateY(12px);
  transition:opacity var(--dur-reveal) var(--ease-text),
             transform var(--dur-reveal) var(--ease-text);
}
.v2-motion [data-v2-reveal].is-in{ opacity:1; transform:none; will-change:auto; }

/* The letter line — the emotional register of the site. Set SMALL: the
   restraint is what makes it feel private. At display size it becomes a
   slogan and loses the person (§2.2). */
.v2-letter{
  font-family:var(--font-longform);
  font-style:italic;
  font-size:clamp(19px,1.7vw,23px);
  line-height:1.55;
  color:var(--paper-300);
  max-width:34ch;
  margin:0;
}
.v2-letter::before{
  content:""; display:block;
  width:28px; height:1px; background:var(--gold);
  opacity:.75; margin:0 0 var(--sp-2);
}
[data-v2-wipe]{ white-space:pre-wrap; }
[data-v2-wipe].is-wiping::after{
  content:""; display:inline-block;
  width:1px; height:1em; margin-left:2px;
  background:var(--gold); vertical-align:-.12em;
  animation:v2Caret 900ms steps(2,end) infinite;
}
@keyframes v2Caret{ 0%,100%{opacity:1} 50%{opacity:0} }

/* §1.3 — the invitation. Names the reward, never "next" or "scroll". */
.v2-invitation{
  position:absolute; left:50%; bottom:clamp(24px,5vh,56px);
  transform:translateX(-50%);
  z-index:3;
  display:flex; flex-direction:column; align-items:center; gap:12px;
  text-decoration:none; color:var(--on-dark-3);
  transition:opacity var(--dur-ui) var(--ease-ui), color var(--dur-ui) var(--ease-ui);
}
.v2-invitation__text{
  font-family:var(--font-sans); font-size:12px;
  letter-spacing:.32em; text-transform:uppercase;
  transition:opacity 220ms var(--ease-ui);
}
.v2-invitation.is-changing .v2-invitation__text{ opacity:0; }
.v2-invitation.is-hidden{ opacity:0; pointer-events:none; }
.v2-invitation:hover,
.v2-invitation:focus-visible{ color:var(--paper-200); }
.v2-invitation__chevron{
  width:30px; height:30px; border-radius:50%;
  border:1px solid var(--on-dark-4);
  display:grid; place-items:center;
  animation:v2Nudge 3s var(--ease) infinite;
}
.v2-invitation__chevron svg{ width:12px; height:12px; stroke:currentColor; fill:none; stroke-width:1.5; }
@keyframes v2Nudge{ 0%,100%{transform:translateY(0)} 50%{transform:translateY(5px)} }

/* §1.7 — indexes whisper. Present, not asserted. */
.v2-index{ list-style:none; margin:0; padding:0; }
.v2-index a,
.v2-index__item{
  display:block; text-decoration:none;
  font-family:var(--font-sans); font-size:11px;
  letter-spacing:.26em; text-transform:uppercase;
  color:var(--on-dark-4);
  padding:10px 0;
  transition:color var(--dur-ui) var(--ease-ui);
}
.v2-index a:hover,
.v2-index a:focus-visible,
.v2-index .is-current{ color:var(--paper-200); }
.v2-index__num{ color:var(--gold); margin-right:12px; opacity:.7; }

/* The year, set enormous and barely there, behind its works (§3.4). */
.v2-year{
  font-family:var(--font-serif);
  font-size:clamp(120px,26vw,420px);
  line-height:.8;
  color:var(--on-dark-4);
  margin:0; pointer-events:none; user-select:none;
}

@media (prefers-reduced-motion:reduce){
  .v2-invitation__chevron,
  [data-v2-wipe].is-wiping::after{ animation:none; }
  [data-v2-emerge]{ --emerge:1 !important; }
  .v2-aperture__frame{ position:relative; height:auto; }
}


/* ==========================================================================
   THE INSTITUTIONAL REGISTER
   --------------------------------------------------------------------------
   Positioning: Siris Hill at institutional level. The National Gallery is not
   a card in a grid — it is the single most consequential fact on the site and
   it gets its own screen.

   The register here is STATEMENT, not marketing. Institutions do not sell;
   they record. No exclamation, no "featured in", no badge. A date, a place,
   a fact, set large and left alone. The confidence is in what is omitted.
   ========================================================================== */

.inst{
  position:relative;
  min-height:100svh;
  display:grid; place-items:center;
  box-sizing:border-box;
  padding:calc(var(--page-header-h) + var(--sp-3)) var(--sp-2) var(--sp-4);
  background:var(--ink-000);
  overflow:hidden;
}
.inst__body{ position:relative; z-index:2; max-width:min(92vw,1000px); text-align:center; }

/* The venue, set as a record entry: institution, then place, then date.
   Hairlines above and below so it reads as an inscription rather than a
   headline. */
.inst__venue{
  font-family:var(--font-sans);
  font-size:clamp(13px,1.25vw,17px);
  letter-spacing:.38em;
  text-transform:uppercase;
  color:var(--paper-200);
  margin:0 0 var(--sp-2);
  padding:var(--sp-1) 0;
  border-top:1px solid var(--on-dark-4);
  border-bottom:1px solid var(--on-dark-4);
  display:inline-block;
}
.inst__title{
  font-family:var(--font-serif); font-style:italic;
  max-width:16ch; margin-inline:auto;
  font-size:clamp(34px,5vw,64px);
  line-height:1.1; letter-spacing:.01em;
  color:var(--paper-300);
  margin:0 0 var(--sp-3);
}
.inst__quote{ max-width:40ch; margin:var(--sp-3) auto 0; text-align:center; }
.inst__quote::before{ margin-inline:auto; }

.inst__line{
  font-family:var(--font-longform);
  font-size:var(--t-lead); line-height:1.7;
  color:var(--on-dark-2);
  max-width:56ch; margin:0 auto;
}

/* The anniversary figure. The one place on the site a number is allowed to
   be enormous, because the number IS the story: a man who found Rembrandt
   while homeless, standing in the Rembrandt Room 420 years after his birth.
   Set in the whispered register so it is a watermark, not a shout. */
/* CRITIQUE FIX 1: the figure was centred, which put it directly behind the
   paragraph that explains it — both became harder to read. It now sits high
   and cropped by the top edge, so it reads as a watermark pressed into the
   wall behind the inscription, and the reading text below sits on clear
   ground. */
.inst__figure{
  position:absolute; z-index:1;
  left:50%; top:-.16em; transform:translateX(-50%);
  font-family:var(--font-serif);
  font-size:clamp(200px,30vw,460px);
  line-height:.78;
  color:rgba(242,237,227,.07);
  white-space:nowrap; pointer-events:none; user-select:none;
}

/* CRITIQUE FIX 4: the screen was pure black — a text slide, not a screen in
   the void. The room itself now sits behind, heavily veiled, so the fact is
   inscribed over the place it happened. */
.inst__field{ position:absolute; inset:0; z-index:0; overflow:hidden; }
.inst__field img{ width:100%; height:100%; object-fit:cover; display:block; }
.inst__field::after{
  content:""; position:absolute; inset:0;
  background:
    radial-gradient(ellipse 68% 58% at 50% 46%, rgba(10,8,6,.60) 0%, rgba(10,8,6,.90) 72%),
    linear-gradient(180deg, rgba(10,8,6,.90) 0%, rgba(10,8,6,.66) 45%, rgba(10,8,6,.94) 100%);
}


/* ==========================================================================
   THE RECORD — chronological ascent
   --------------------------------------------------------------------------
   Replaces the three-card exhibition grid. Cards flatten a trajectory into
   a menu; a record shows a rise. Read top to bottom: a Norwich degree, an
   art fair in New York, a solo show, the National Gallery.
   ========================================================================== */

.record{ max-width:1000px; margin-inline:auto; }

.record__entry{
  display:grid;
  grid-template-columns:minmax(0,7.5rem) minmax(0,1fr) minmax(0,9rem);
  gap:var(--sp-3);
  align-items:baseline;
  padding:var(--sp-3) 0;
  border-top:1px solid rgba(242,237,227,.08);
  text-decoration:none; color:inherit;
  transition:background var(--dur-ui) var(--ease-ui);
}
a.record__entry:hover,
a.record__entry:focus-visible{ background:rgba(242,237,227,.03); }
.record__entry:last-child{ border-bottom:1px solid rgba(242,237,227,.08); }

.record__yr{
  font-family:var(--font-serif);
  font-size:clamp(26px,2.6vw,42px);
  line-height:1; color:var(--on-dark-4);
  transition:color var(--dur-reveal) var(--ease);
}
a.record__entry:hover .record__yr,
a.record__entry:focus-visible .record__yr{ color:var(--gold); }

.record__what{ min-width:0; }
.record__title{
  font-family:var(--font-serif);
  font-size:var(--t-lead); line-height:1.3;
  color:var(--paper-300); margin:0 0 6px;
}
.record__where{
  font-family:var(--font-longform); font-size:15px; line-height:1.6;
  color:var(--on-dark-2); margin:0;
}
.record__tag{
  font-family:var(--font-sans); font-size:10px;
  letter-spacing:.24em; text-transform:uppercase;
  color:var(--on-dark-3); text-align:right; white-space:nowrap;
}
/* The one entry that is not like the others. */
.record__entry--peak .record__yr{ color:var(--gold); }
.record__entry--peak .record__title{ font-style:italic; font-size:var(--t-sub); }
.record__entry--peak .record__tag{ color:var(--gold); }

@media (max-width:760px){
  .record__entry{ grid-template-columns:1fr; gap:8px; }
  .record__tag{ text-align:left; }
}


/* ==========================================================================
   THE ASCENT RAIL — persistent chronology on archive pages
   --------------------------------------------------------------------------
   Three archive pages were three disconnected documents. The rail makes each
   one show where it sits in the arc, so a visitor landing on 2019 can see
   there is a 2026 and that it is the National Gallery. Whispered (§1.7).
   ========================================================================== */

.rail{
  position:fixed; z-index:40;
  left:clamp(12px,2.2vw,32px); top:50%;
  transform:translateY(-50%);
  display:flex; flex-direction:column; gap:var(--sp-2);
  padding:0; margin:0; list-style:none;
}
/* Whispered, not invisible (§1.7). At --on-dark-4 (12%) the inactive years
   were effectively undiscoverable, which defeats the rail's whole purpose:
   telling someone on 2019 that a National Gallery year exists. */
.rail a{
  display:flex; align-items:center; gap:10px;
  text-decoration:none;
  font-family:var(--font-sans); font-size:12px;
  letter-spacing:.24em; color:var(--on-dark-3);
  transition:color var(--dur-ui) var(--ease-ui);
}
.rail a::before{
  content:""; width:14px; height:1px; background:currentColor;
  transition:width var(--dur-ui) var(--ease-ui);
}
.rail a:hover,
.rail a:focus-visible{ color:var(--paper-200); }
.rail a:hover::before,
.rail a:focus-visible::before{ width:26px; }
.rail [aria-current="page"]{ color:var(--gold); }
.rail [aria-current="page"]::before{ width:32px; background:var(--gold); }

/* Below 1200px there is no room beside the measure, so the rail becomes a
   quiet horizontal strip under the header instead of overlapping the text. */
@media (max-width:1200px){
  /* BUG FIX: going static put the rail into normal flow at the very top of
     the body, directly UNDERNEATH the fixed nav — it disappeared entirely
     on every screen below 1200px, which is most phones and tablets. It now
     clears the header stack explicitly. */
  .rail{
    position:static; transform:none;
    flex-direction:row; justify-content:center; gap:var(--sp-3);
    padding:calc(var(--page-header-h) + var(--sp-2)) var(--sp-2) 0;
    background:var(--ink-000);
  }
  .rail a::before{ width:0; }
  .rail a:hover::before{ width:0; }
  .rail [aria-current="page"]::before{ width:14px; }
}
