/* ══════════ TYPE — self-hosted, no third party ══════════
   Newsreader is the variable optical-size cut, so the display sizes get
   display optics and the body copy gets text optics from one file.       */
@font-face{
  font-family:'Newsreader';font-style:normal;font-weight:200 800;
  font-display:swap;src:url(f/newsreader.woff2) format('woff2-variations');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,
                U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,
                U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Newsreader';font-style:italic;font-weight:200 800;
  font-display:swap;src:url(f/newsreader-italic.woff2) format('woff2-variations');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,
                U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,
                U+2212,U+2215,U+FEFF,U+FFFD;
}
/* Metrics-matched stand-in, so the swap to Newsreader doesn't shove the page.
   Newsreader's average advance is within 0.5% of Times; only the vertical
   metrics differ, and those are overridden outright. */
@font-face{
  font-family:'Newsreader Fallback';
  src:local('Times New Roman'),local('Times'),local('Liberation Serif'),local('Tinos');
  size-adjust:100.4%;ascent-override:73.5%;descent-override:26.5%;line-gap-override:0%;
}
@font-face{
  font-family:'IBM Plex Mono';font-style:normal;font-weight:300;
  font-display:swap;src:url(f/plexmono-300.woff2) format('woff2');
}
@font-face{
  font-family:'IBM Plex Mono';font-style:normal;font-weight:400;
  font-display:swap;src:url(f/plexmono-400.woff2) format('woff2');
}

:root{
  --paper:#E9E4DA;      /* the work surface */
  --desk:#DCD5C7;       /* surface under a plate */
  --ink:#14130E;
  --serif:'Newsreader','Newsreader Fallback',Georgia,'Times New Roman',serif;
  --mono:'IBM Plex Mono',ui-monospace,Menlo,monospace;
  --pad:clamp(18px,3.6vw,50px);
  --wordrow:clamp(110px,17vh,200px);
  --bar:clamp(42px,4.8vh,54px);
}
*{margin:0;padding:0;box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  font-family:var(--serif);font-weight:300;
  background:var(--paper);color:var(--ink);
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
  overflow-x:hidden;
}
::selection{background:var(--ink);color:var(--paper)}
a{color:inherit}
.mono{
  font-family:var(--mono);font-weight:400;
  font-size:clamp(11px,.86vw,13.2px);letter-spacing:.15em;text-transform:uppercase;
}

/* ══════════ STAGE ══════════ */
#stage{
  position:fixed;inset:0;height:100vh;height:100svh;overflow:hidden;z-index:1;
  background:var(--paper);
  transition:background-color 1.4s cubic-bezier(.4,0,.2,1);
}
#runway{position:relative;z-index:0}

/* ── the vitrine: hairline frame + words orbiting it ── */
#case{position:fixed;inset:0;z-index:30;pointer-events:none}
#case svg{width:100%;height:100%;display:block;overflow:visible}
#casePath{fill:none;stroke:currentColor;stroke-width:1;opacity:.17}
#caseWords,#caseWords2{
  font-family:var(--mono);font-size:10px;letter-spacing:.5em;text-transform:uppercase;
  fill:currentColor;opacity:.24;
}

/* ── animated film grain over the paper ── */
#grain{
  position:fixed;inset:-120px;z-index:32;pointer-events:none;
  opacity:.58;mix-blend-mode:multiply;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='260' height='260'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.62' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='260' height='260' filter='url(%23n)' opacity='.62'/%3E%3C/svg%3E");
  animation:grain .58s steps(5,end) infinite;
}
@keyframes grain{
  0%  {transform:translate3d(0,0,0)}
  20% {transform:translate3d(-38px,26px,0)}
  40% {transform:translate3d(31px,-19px,0)}
  60% {transform:translate3d(-24px,-32px,0)}
  80% {transform:translate3d(42px,17px,0)}
  100%{transform:translate3d(0,0,0)}
}

/* ══════════ THE GHOST — traces of the old site ══════════ */
#ghost{position:absolute;inset:0;z-index:-1;pointer-events:none}
#ghost .gh{
  position:absolute;opacity:0;
  transition:opacity 1.2s cubic-bezier(.4,0,.2,1);
  mix-blend-mode:multiply;               /* white ground dissolves into the paper */
  /* feather the frame edge away — otherwise the video's rectangle reads as a box */
  -webkit-mask-image:radial-gradient(ellipse 64% 64% at 50% 50%,#000 38%,rgba(0,0,0,.55) 62%,transparent 84%);
          mask-image:radial-gradient(ellipse 64% 64% at 50% 50%,#000 38%,rgba(0,0,0,.55) 62%,transparent 84%);
}
#ghost video,#ghost img{filter:brightness(1.07) contrast(1.14)}  /* push the scan white to true white */
#ghost .gh.show{opacity:var(--go)}
#ghost .gh.out{transition-duration:1.8s}
#ghost video,#ghost img{display:block;width:100%;height:auto}

#arch{
  position:fixed;left:calc(var(--pad)*2.15);bottom:calc(var(--bar) + var(--pad)*1.0);
  z-index:44;opacity:0;pointer-events:none;background:none;border:0;padding:6px;
  color:inherit;font-family:var(--mono);font-size:12px;line-height:1;cursor:pointer;
  transition:opacity .9s ease;
}
#arch.on{opacity:.18;pointer-events:auto}
#arch:hover,#arch:focus-visible{opacity:.5}

/* ══════════ BEATS ══════════ */
.beat{
  position:absolute;inset:0;display:flex;align-items:center;
  padding:calc(var(--pad)*2.1) calc(var(--pad)*2.1) calc(var(--bar) + var(--pad)*1.6);
  opacity:0;visibility:hidden;will-change:opacity,transform;
}
.beat.on{visibility:visible}
.beat .inner{width:100%;max-width:1080px;margin:0 auto}

/* arrival — the first beat is already composed when a stranger lands, but it
   settles rather than snaps. Runs once; every later beat is scroll-driven. */
@keyframes composeIn{
  from{opacity:0;transform:translate3d(0,9px,0)}
  to  {opacity:1;transform:none}
}
body.arrived #stage>section.beat:first-of-type .inner{
  animation:composeIn .92s cubic-bezier(.2,0,.2,1) both;
}
@media (prefers-reduced-motion:reduce){
  body.arrived #stage>section.beat:first-of-type .inner{animation:none}
}

/* type — deliberately small, plenty of air */
.big{font-size:clamp(1.9rem,4.2vw,3.75rem);line-height:1.1;letter-spacing:-.022em;font-weight:200}
.big em{font-style:italic}
.body{
  margin-top:clamp(18px,2.8vh,30px);max-width:40ch;
  font-size:clamp(1.03rem,1.2vw,1.26rem);line-height:1.8;opacity:.76;
}
.body + .body{margin-top:1.5em}
.kick{display:block;margin-bottom:clamp(16px,2.6vh,26px);opacity:.5}

/* ── 02 places ── */
#places{position:relative;height:var(--wordrow)}
#places .pl{
  position:absolute;left:0;top:50%;
  font-size:clamp(1.9rem,5.4vw,4.4rem);line-height:.94;letter-spacing:-.03em;
  font-weight:200;white-space:nowrap;opacity:0;will-change:opacity,transform;
}
#places .pl em{font-style:italic}

/* ── the twin columns: where he grew up, set against what he is ──
   Two scroll-driven word stacks on one sub-timeline, running in opposite
   directions so the columns cross in the middle of the beat. Seven places
   against six roles, so the lists drift out of phase and a place only lands
   level with a role now and then; the hairline between them draws itself
   when it happens and retreats when it doesn't. That drift is the point —
   do not equalise the two counts to make it tidy.                        */
.twin{
  position:relative;
  display:grid;grid-template-columns:1fr 1fr;
  column-gap:clamp(12px,2.2vw,40px);align-items:end;max-width:1080px;
}
.tw-r{text-align:right}
#roles{position:relative;height:var(--wordrow)}
/* both columns step down from the single-column size — two word stacks have
   to share the width the places alone used to own */
.twin #places .pl,#roles .rl{font-size:clamp(1.5rem,3.9vw,3.2rem)}
#roles .rl{
  position:absolute;right:0;top:50%;
  line-height:.94;letter-spacing:-.03em;
  font-weight:200;white-space:nowrap;opacity:0;will-change:opacity,transform;
}
/* the article rides with the noun so "I am" + "an editor" stays grammatical,
   set small enough that the noun is still the word you read */
#roles .rl i{
  font-style:normal;font-size:.4em;opacity:.5;
  margin-right:.3em;vertical-align:.42em;letter-spacing:.02em;
}
/* The rule between the columns is positioned by the script, not by the grid:
   it runs from the trailing edge of the place currently in front to the leading
   edge of the role, so it reads as a connection between those two words rather
   than a dash parked in the gutter. Length is measured in layout(), not per
   frame, so the scroll loop stays free of reads. */
.tie{
  position:absolute;left:0;top:50%;height:1px;width:0;pointer-events:none;
  background:currentColor;transform:scaleX(var(--lock,0));transform-origin:left center;
  opacity:calc(.1 + .5 * var(--lock,0));
}

/* ══════════ WORK — plates on the surface ══════════ */
.plate{
  position:absolute;z-index:1;opacity:0;visibility:hidden;
  will-change:opacity,transform;
  left:62%;top:calc(50% - 2vh);transform:translate(-50%,-50%);
  width:min(43vw,570px);
}
.plate.on{visibility:visible}
.plate.tall{width:min(24vw,270px)}
.plate img{
  display:block;width:100%;height:auto;
  box-shadow:0 1px 2px rgba(20,19,14,.10), 0 18px 44px -18px rgba(20,19,14,.34);
}
.beat.work{align-items:center;justify-content:flex-start}
.beat.work .inner{max-width:1080px}
.wcap{max-width:29ch}
.wtitle{font-size:clamp(1.52rem,2.9vw,2.5rem);line-height:1.16;letter-spacing:-.02em;font-weight:200}
.wtitle em{font-style:italic}
.wrole{margin-top:11px;opacity:.66;letter-spacing:.13em}
.wnote{margin-top:13px;font-size:clamp(.99rem,1.14vw,1.2rem);line-height:1.86;opacity:.7}

.play{
  display:inline-flex;align-items:center;gap:11px;
  background:none;border:0;cursor:pointer;color:inherit;
  padding:13px 0 9px;margin-top:16px;border-bottom:1px solid currentColor;
  font-family:var(--mono);font-size:clamp(11px,.86vw,13.2px);letter-spacing:.15em;text-transform:uppercase;
  opacity:.72;transition:opacity .4s,gap .4s;
}
.play:hover,.play:focus-visible{opacity:1;gap:19px}
.play .disc{width:23px;height:23px;border:1px solid currentColor;border-radius:50%;display:grid;place-items:center;flex:0 0 auto}
.play .disc::before{content:'';border-left:5px solid currentColor;border-top:3.5px solid transparent;border-bottom:3.5px solid transparent;margin-left:2px}

/* ── photographs: prints laid out on the desk ── */
.scatter{position:absolute;inset:0;z-index:1;pointer-events:none}
.scatter .pr{
  position:absolute;opacity:0;visibility:hidden;will-change:opacity,transform;
}
/* Slot width alone made portrait frames ~1.5x as tall as landscape ones, and
   a portrait in a low slot spilled past the hairline frame onto the exit bar.
   The height cap keeps every print inside the vitrine; aspect is preserved
   because width and height are both auto under the two maxima. */
.scatter .pr img{display:block;width:auto;height:auto;max-width:100%;max-height:42vh;box-shadow:0 1px 2px rgba(20,19,14,.10),0 16px 38px -18px rgba(20,19,14,.32)}
.scatter .pr.on{visibility:visible}
/* prints are laid down by hand, so they don't share a baseline. The wrapper
   transform belongs to the script (drift + scale); the tilt lives on the img. */
.scatter .pr img{transform:rotate(var(--rot,0deg))}
.pr1{width:min(17vw,222px);left:4.5%;top:13%}
.pr2{width:min(19vw,252px);left:11%;bottom:13%}
.pr3{width:min(19vw,254px);right:5.5%;top:11%}
.pr4{width:min(21vw,296px);right:12%;bottom:14%}
.pr5{width:min(14vw,184px);left:2.5%;top:47%}
.pr6{width:min(14vw,192px);right:2.5%;top:45%}

.exitline{
  display:inline-flex;align-items:center;gap:10px;text-decoration:none;
  border-bottom:1px solid currentColor;padding-bottom:5px;margin-top:20px;
  transition:gap .4s;
}
.exitline:hover,.exitline:focus-visible{gap:17px}

.mail{
  font-size:clamp(1.32rem,2.6vw,2.2rem);line-height:1;letter-spacing:-.02em;font-weight:200;
  text-decoration:none;border-bottom:1px solid rgba(20,19,14,.26);padding-bottom:.12em;
  transition:border-color .4s;
}
.mail:hover{border-color:currentColor}
.cols{display:flex;gap:clamp(20px,4vw,64px);flex-wrap:wrap;margin-top:clamp(22px,3.6vh,40px)}
.cols div{min-width:130px}
.cols .mono{opacity:.5;display:block;margin-bottom:8px}
.cols p{font-size:clamp(.99rem,1.14vw,1.2rem);line-height:1.8;opacity:.8}

/* ══════════ CHROME ══════════ */
#mark{
  position:fixed;top:calc(var(--pad)*2.15);left:calc(var(--pad)*2.15);z-index:45;
  text-decoration:none;letter-spacing:.3em;opacity:.5;transition:opacity .4s;
}
#mark:hover{opacity:.9}
#bar{
  position:fixed;left:0;right:0;bottom:0;z-index:45;height:var(--bar);
  display:flex;align-items:center;justify-content:center;gap:clamp(12px,2.8vw,42px);
  padding:0 var(--pad);
}
#bar a,#bar .here{
  text-decoration:none;opacity:.42;transition:opacity .4s;
  font-family:var(--mono);font-weight:400;
  font-size:clamp(10.5px,.78vw,12.4px);letter-spacing:.16em;text-transform:uppercase;white-space:nowrap;
}
#bar a:hover,#bar a:focus-visible,#bar a[aria-current="true"]{opacity:.95}
/* the page you are on: not a link, marked with a seal rather than emphasis */
#bar .here{opacity:.9;position:relative;cursor:default}
#bar .here::after{
  content:"";position:absolute;left:0;right:0;bottom:-6px;height:1px;
  background:currentColor;opacity:.34;
}
#bar .dot{opacity:.2;font-size:7px}
#cue{
  position:fixed;left:50%;bottom:calc(var(--bar) + var(--pad)*1.5);transform:translateX(-50%);
  z-index:44;opacity:.3;animation:cue 3.6s ease-in-out infinite;
}
@keyframes cue{0%,100%{transform:translate(-50%,0);opacity:.18}50%{transform:translate(-50%,5px);opacity:.42}}

/* ══════════ LIGHTBOX ══════════ */
#lb{position:fixed;inset:0;z-index:100;display:none;background:rgba(233,228,218,.97);align-items:center;justify-content:center;padding:calc(var(--pad)*2)}
#lb.open{display:flex}
#lb .box{width:min(100%,1120px);aspect-ratio:16/9;position:relative;box-shadow:0 24px 70px -26px rgba(20,19,14,.5)}
#lb iframe{width:100%;height:100%;border:0;display:block}
#lbClose{position:absolute;top:calc(var(--pad)*.6);right:calc(var(--pad)*.6);background:none;border:0;color:var(--ink);cursor:pointer;padding:12px;font-family:var(--mono);font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;opacity:.6}
#lbClose:hover,#lbClose:focus-visible{opacity:1}

:focus-visible{outline:1px solid currentColor;outline-offset:5px}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
/* the skip link is real: hidden until a keyboard finds it, then a paper tab */
.sr:focus{
  position:fixed;left:50%;top:0;transform:translateX(-50%);
  width:auto;height:auto;clip:auto;z-index:200;
  padding:11px 20px 12px;background:var(--paper);color:var(--ink);
  border:1px solid rgba(20,19,14,.34);border-top:none;border-radius:0 0 4px 4px;
  font-family:var(--mono);font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;
  box-shadow:0 14px 34px -18px rgba(20,19,14,.5);
}

/* ══════════ FLOW FALLBACK — reduced motion only ══════════ */
body.flow #stage{position:static;height:auto;overflow:visible}
body.flow #runway,body.flow #case,body.flow #cue{display:none}
body.flow{padding-bottom:var(--bar)}
body.flow .beat{
  position:relative;inset:auto;opacity:1!important;visibility:visible!important;
  transform:none!important;padding:clamp(56px,9vh,96px) var(--pad);display:block;
}
body.flow .beat.work{padding-top:0}
body.flow .plate,body.flow .scatter .pr{
  position:relative;inset:auto;left:auto;right:auto;top:auto;bottom:auto;
  transform:none!important;opacity:1!important;visibility:visible!important;
  width:100%;margin:0 0 clamp(18px,3vh,28px);
}
body.flow .plate.tall{width:100%}
body.flow .beat .inner,body.flow .plate,body.flow .scatter{max-width:660px;margin-left:auto;margin-right:auto}
body.flow .scatter{
  position:relative;inset:auto;pointer-events:auto;display:grid;
  grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:8px;
  margin-bottom:clamp(20px,3vh,32px);padding:0 var(--pad);
}
body.flow .scatter .pr{width:100%;margin:0}
body.flow .scatter .pr img{aspect-ratio:3/4;object-fit:cover;transform:none}
/* in the reading fallback the canvas word is a plain heading again */
body.flow .beat.canvas .cvs{font-size:clamp(1.5rem,7vw,2.4rem);opacity:1;white-space:normal}
body.flow .beat.ground .cvs{position:static;transform:none;text-align:left;margin-bottom:.35em;
  font-size:clamp(1.5rem,7vw,2.4rem);opacity:1;white-space:normal}
body.flow .beat.ground .lst{max-width:none}
body.flow #places{height:auto;display:flex;flex-direction:column;gap:1px}
body.flow #places .pl{position:relative;top:auto;opacity:1;font-size:clamp(1.5rem,7vw,2.4rem)}
body.flow .twin{display:block}
body.flow .tie{display:none}
body.flow .tw-r{text-align:left;margin-top:clamp(22px,4vh,40px)}
body.flow #roles{height:auto;display:flex;flex-direction:column;gap:1px}
body.flow .twin #places .pl,body.flow #roles .rl{
  position:relative;right:auto;top:auto;opacity:1;font-size:clamp(1.5rem,7vw,2.4rem)}
body.flow #mark{position:absolute}
body.flow #bar{background:var(--paper);border-top:1px solid rgba(20,19,14,.14)}
body.flow #grain{opacity:.42;animation:none}
@media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}

/* ══════════ MULTI-PAGE ADDITIONS ══════════ */

/* work page: a main plate with a small collage of stills around it */
.plate.hero{left:50%;top:calc(50% - 7.5vh);width:min(52vw,700px)}
.collage{position:absolute;inset:0;z-index:1;pointer-events:none}
.collage .pr{position:absolute;opacity:0;visibility:hidden;will-change:opacity,transform}
.collage .pr.on{visibility:visible}
.collage .pr img{display:block;width:100%;height:auto;
  box-shadow:0 1px 2px rgba(20,19,14,.10),0 12px 30px -14px rgba(20,19,14,.30)}
.c1{width:min(13.5vw,182px);left:4.5%;top:17%}
.c2{width:min(12vw,160px);left:9%;bottom:22%}
.c3{width:min(13.5vw,184px);right:4.5%;top:19%}
.c4{width:min(12vw,164px);right:9%;bottom:23%}
.c5{width:min(11vw,146px);left:2.5%;top:52%}
.c6{width:min(11vw,150px);right:2.5%;top:55%}

/* a play control that sits over the centred plate */
.plate .pl-play{
  position:absolute;inset:0;display:grid;place-items:center;
  background:none;border:0;cursor:pointer;color:#F2EEE5;
  opacity:0;pointer-events:none;transition:opacity .5s cubic-bezier(.4,0,.2,1);
}
.plate.lead .pl-play{opacity:1;pointer-events:auto}
.plate .pl-play .disc{
  width:52px;height:52px;border:1px solid currentColor;border-radius:50%;
  display:grid;place-items:center;
  background:rgba(20,19,14,.24);backdrop-filter:blur(2px);
  opacity:.82;transition:opacity .4s,transform .4s;
}
.plate .pl-play:hover .disc,.plate .pl-play:focus-visible .disc{opacity:1;transform:scale(1.07)}
.plate .pl-play .disc::before{
  content:'';border-left:11px solid currentColor;
  border-top:7px solid transparent;border-bottom:7px solid transparent;margin-left:4px;
}


/* work / leftovers captions sit under the plate, centred */
.beat.centred{justify-content:center;text-align:center}
.beat.centred .inner{max-width:700px}
.beat.centred .wcap{max-width:44ch;margin:0 auto}
.beat.under{align-items:flex-end}
.beat.under .inner{padding-bottom:1vh}
.beat.under .wcap .kick{margin-bottom:10px}

/* a plain index — leftovers list */
.lst{list-style:none;max-width:640px}
.lst li{
  display:flex;justify-content:space-between;gap:20px;align-items:baseline;
  padding:11px 0;border-bottom:1px solid rgba(20,19,14,.14);
  transition:opacity .35s;
}
.lst:hover li{opacity:.42}
.lst li:hover,.lst li:focus-within{opacity:1}
.lst a{text-decoration:none;font-size:clamp(1.1rem,1.34vw,1.32rem);opacity:.88;transition:opacity .3s}
.lst a:hover{opacity:1}
.lst .yr{opacity:.56;flex:0 0 auto}

/* page label in the corner, so you always know where you are */
#where{
  position:fixed;top:calc(var(--pad)*2.15);right:calc(var(--pad)*2.15);z-index:45;
  opacity:.5;letter-spacing:.2em;
}
body.flow #where{position:absolute}

/* ── photography page: small prints strewn across the whole surface ──
   Deliberately NOT aligned — no shared column, no shared baseline, and the
   field is allowed to cross the middle of the screen. The category word
   underneath is the canvas; the prints sit on top of it. */
.scatter.wide{z-index:3}
.scatter.wide .pr img{box-shadow:0 1px 2px rgba(20,19,14,.10),0 20px 46px -20px rgba(20,19,14,.34)}
/* The top-left corner belongs to the monogram, the top-right to the page
   label and the bottom strip to the exit bar — slots keep out of all three.
   Everything else is fair game, including the middle. */
.f1{width:min(16vw,208px);left:4%;    top:21%;    --rot:-2.4deg}
.f2{width:min(13vw,168px);left:26%;   top:40%;    --rot:1.8deg}
.f3{width:min(18vw,232px);right:6%;   top:22%;    --rot:2.6deg}
.f4{width:min(14vw,180px);left:14%;   bottom:16%; --rot:1.2deg}
.f5{width:min(11vw,146px);right:23%;  top:54%;    --rot:-3.1deg}
.f6{width:min(17vw,214px);right:4.5%; bottom:13%; --rot:-1.6deg}
.f7{width:min(12vw,152px);left:42%;   top:13%;    --rot:2.2deg}
.f8{width:min(15vw,192px);left:34%;   bottom:12%; --rot:-2.0deg}
.f9{width:min(10vw,132px);left:61%;   top:35%;    --rot:3.0deg}
/* f10–f16 extend a field to sixteen prints. Same three keep-out zones. */
.f10{width:min(13vw,168px);left:30%;  top:66%;    --rot:-1.4deg}
.f11{width:min(11vw,146px);left:8%;   top:62%;    --rot:2.8deg}
.f12{width:min(15vw,192px);right:30%; bottom:15%; --rot:-2.2deg}
.f13{width:min(12vw,152px);left:52%;  top:58%;    --rot:1.5deg}
.f14{width:min(10vw,132px);left:20%;  top:30%;    --rot:-2.9deg}
.f15{width:min(14vw,180px);right:38%; top:16%;    --rot:2.0deg}
.f16{width:min(11vw,146px);left:46%;  bottom:22%; --rot:-1.8deg}

/* the category word as ground, not as label — large, faint, and overlapped */
.beat.canvas{justify-content:center;text-align:center}
.beat.canvas .inner{max-width:none}
.beat.canvas .cvs{
  display:block;font-weight:200;line-height:.92;letter-spacing:-.035em;
  font-size:clamp(2.6rem,10.5vw,8.6rem);opacity:.17;
  white-space:nowrap;
}
.beat.canvas .cvs em{font-style:italic}
.beat.canvas .kick{margin-bottom:clamp(10px,1.6vh,18px)}


/* ── archives: an index laid over its own genre word ──
   Same premise as the photography canvas — the word is ground, not label —
   but what sits on top here is a list, not a field of prints. The word is
   taken out of flow so the rows cross it instead of stacking under it. */
.beat.ground{justify-content:flex-start}
.beat.ground .inner{position:relative}
.beat.ground .cvs{
  position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  z-index:0;pointer-events:none;margin:0;text-align:center;
  display:block;font-weight:200;line-height:.92;letter-spacing:-.035em;
  font-size:clamp(2.4rem,9.4vw,7.6rem);opacity:.15;white-space:nowrap;
  transition:opacity .45s cubic-bezier(.4,0,.2,1);
}
/* a preview will always cross the word — let the word give way rather
   than be guillotined by the edge of a thumbnail */
body.peeking .beat.ground .cvs{opacity:.055}
.beat.ground .cvs em{font-style:italic}
/* the list and its kick ride above the word; the hover preview needs the
   room to its right, so the column stops well short of the frame */
.beat.ground .kick,.beat.ground .lst{position:relative;z-index:2}
.beat.ground .lst{max-width:min(560px,48vw)}

/* mood board grid */
.mood{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(8px,1.2vw,16px);
  padding:calc(var(--pad)*3.4) calc(var(--pad)*3.4) calc(var(--bar) + var(--pad)*3);
  align-content:center;
}
.mood .pr{opacity:0;visibility:hidden;will-change:opacity,transform;position:relative}
.mood .pr.on{visibility:visible}
.mood .pr img{display:block;width:100%;height:auto;
  box-shadow:0 1px 2px rgba(20,19,14,.10),0 10px 26px -14px rgba(20,19,14,.28)}
body.flow .mood{
  position:relative;inset:auto;padding:0 var(--pad);
  grid-template-columns:repeat(4,1fr);max-width:660px;margin:0 auto 8px;
}

body.flow .scatter.wide{max-width:660px;margin:0 auto}

/* a beat that exists only to host a ghost — no text of its own */
.beat.blank{pointer-events:none}
.beat.blank .inner{opacity:.42}

/* the note Marwan still has to replace */
.todo{ display:none; }
/* Internal build notes. Hidden from visitors by default; add class="draft" to
   the <html> tag (or run tools/build.py --draft) to see them while editing. */
html.draft .todo{
  display:inline-block;margin-top:14px;padding:7px 11px;
  border:1px dashed rgba(20,19,14,.3);opacity:.6;
  font-family:var(--mono);font-size:10px;letter-spacing:.18em;text-transform:uppercase;
}

/* hover preview for the spillover lists */
#peek{
  position:fixed;z-index:43;pointer-events:none;
  width:min(28vw,380px);opacity:0;
  transform:translateY(8px);
  transition:opacity .45s cubic-bezier(.4,0,.2,1),transform .45s cubic-bezier(.4,0,.2,1);
}
#peek.on{opacity:1;transform:translateY(0)}
#peek img{display:block;width:100%;height:auto;
  box-shadow:0 1px 2px rgba(20,19,14,.10),0 16px 40px -18px rgba(20,19,14,.34)}
body.flow #peek{display:none}

/* the surrounding stills are a stage device — in the document fallback
   the main plate carries the project on its own */
body.flow .collage{display:none}


/* ══════════════════════════════════════════════════════════
   THE STAGE ON SMALL SCREENS
   Same static scroll, same beats — the case just draws in.
   ══════════════════════════════════════════════════════════ */
@media (max-width: 900px){
  :root{ --pad:clamp(13px,3.4vw,22px); --bar:clamp(40px,6.2vh,50px); }
  .beat{ padding:calc(var(--pad)*2.4) calc(var(--pad)*2.4) calc(var(--bar) + var(--pad)*2.4); }
  .beat .inner{ max-width:none }
  .big{ font-size:clamp(1.62rem,7vw,2.6rem); line-height:1.14 }
  .body{ max-width:32ch; font-size:clamp(.98rem,4vw,1.12rem); line-height:1.8 }
  #places{ height:clamp(84px,15vh,130px) }
  #places .pl{ font-size:clamp(1.7rem,9.2vw,3rem) }
  /* no room for two columns beside each other — stack them, and give each
     stack a shorter row so the body copy and the exit line still fit the beat */
  .twin{ display:block }
  .tie{ display:none }
  .tw-r{ text-align:left; margin-top:clamp(14px,2.4vh,24px) }
  .twin #places,#roles{ height:clamp(62px,10.5vh,98px) }
  #roles .rl{ right:auto; left:0 }
  .twin #places .pl,#roles .rl{ font-size:clamp(1.45rem,7.6vw,2.4rem) }
  #caseWords,#caseWords2{ font-size:8px; letter-spacing:.34em }
  #mark{ top:calc(var(--pad)*3.4); left:calc(var(--pad)*3.2) }
  #where{ top:calc(var(--pad)*3.4); right:calc(var(--pad)*3.2) }
  #mark .mono-mark{ width:1.6em; height:1.6em }

  /* plates fill the frame instead of floating in it */
  .plate,.plate.hero{ width:min(84vw,560px); left:50%; top:calc(50% - 9vh) }
  .beat.work,.beat.centred.under{ align-items:flex-end }
  .wcap{ max-width:none }
  .wtitle{ font-size:clamp(1.38rem,6vw,2rem) }
  .wnote{ font-size:clamp(.96rem,3.9vw,1.1rem) }

  /* the collage tucks into the corners rather than ringing the plate */
  .c1{width:26vw;left:2%;top:9%}      .c2{width:23vw;left:4%;bottom:30%}
  .c3{width:26vw;right:2%;top:11%}    .c4{width:23vw;right:4%;bottom:32%}
  .c5,.c6{display:none}

  .pr1{width:30vw;left:2%;top:8%}     .pr2{width:33vw;left:5%;bottom:24%}
  .pr3{width:31vw;right:2%;top:10%}   .pr4{width:34vw;right:4%;bottom:26%}
  .pr5{width:24vw;left:1%;top:46%}    .pr6{width:24vw;right:1%;top:44%}

  /* the field still scatters on a phone, just with fewer, larger prints —
     nine small prints on a 390px screen would be confetti */
  .f1{width:36vw;left:3%;top:9%}      .f2{width:29vw;left:22%;top:38%}
  .f3{width:38vw;right:2%;top:15%}    .f4{width:31vw;left:9%;bottom:15%}
  .f5{width:25vw;right:19%;top:55%}   .f6{width:35vw;right:3%;bottom:12%}
  .f7{width:27vw;left:44%;top:6%}     .f8{width:32vw;left:30%;bottom:6%}
  .f9{display:none}
  .beat.canvas .cvs{ font-size:clamp(2rem,13vw,3.4rem); white-space:normal }
  .beat.ground .cvs{ position:static; transform:none; text-align:left; margin-bottom:.35em;
    font-size:clamp(1.6rem,7.4vw,2.4rem); opacity:.34; white-space:normal }
  .beat.ground .lst{ max-width:none }

  .mood{ grid-template-columns:repeat(2,1fr); padding:calc(var(--pad)*4) calc(var(--pad)*3) calc(var(--bar) + var(--pad)*3) }
  .lst a{ font-size:clamp(1rem,4.2vw,1.15rem) }
  .lst li{ padding:9px 0 }
  #bar{ gap:clamp(8px,2.4vw,18px) }
  #bar a{ font-size:9.5px; letter-spacing:.09em }
  #bar{ height:calc(var(--bar)*.92) }
  #bar .dot{ display:none }
  #peek{ display:none }
}
@media (max-width: 560px){
  .lst .yr{ display:none }
  .cols{ gap:20px }
  #caseWords,#caseWords2{ font-size:7px; letter-spacing:.26em }
}

/* ══════════ PHOTO LIGHTBOX ══════════ */
.scatter .pr[data-full]{ pointer-events:auto; cursor:pointer }
.scatter .pr[data-full] img{ transition:transform .5s cubic-bezier(.16,1,.3,1) }
.scatter .pr[data-full]:hover img{ transform:scale(1.035) }
#lb.photo{ background:rgba(14,13,10,.94) }
#lb.photo .box{ aspect-ratio:auto; width:auto; max-width:min(92vw,1300px); max-height:86vh; box-shadow:none }
#lb.photo .box img{ display:block; max-width:min(92vw,1300px); max-height:86vh; width:auto; height:auto;
  box-shadow:0 30px 80px -30px rgba(0,0,0,.7) }
#lb.photo #lbClose{ color:#EDE9E0 }

/* ══════════ SCROLL PROGRESS ══════════ */
#prog{
  position:fixed; left:0; top:0; height:1px; z-index:46;
  background:currentColor; color:var(--ink); opacity:.28; width:0;
  transition:width .1s linear;
}

/* ══════════ WORDMARK + MONOGRAM ══════════ */
#mark{
  display:flex; align-items:center; gap:11px;
  font-family:var(--serif); font-weight:300;
  font-size:clamp(1rem,1.35vw,1.24rem); letter-spacing:.06em;
  text-transform:none; opacity:.78;
}
#mark:hover,#mark:focus-visible{ opacity:1 }
#mark .mono-mark{ width:1.75em; height:1.75em; flex:0 0 auto; display:block;
  transition:transform .5s cubic-bezier(.16,1,.3,1) }
#mark:hover .mono-mark{ transform:scale(1.06) }
/* the old mark was drawn in strokes; the ligature is a solid letterform */
#mark .mono-mark path,#mark .mono-mark circle{ stroke:currentColor; fill:none }
#mark .mono-mark.solid path{ fill:currentColor; stroke:none }
/* it is a link home from every page — say so on hover instead of hoping
   people try it. The rule draws itself in rather than blinking on. */
#mark .nm{ line-height:1; position:relative }
#mark .nm::after{
  content:''; position:absolute; left:0; right:0; bottom:-4px; height:1px;
  background:currentColor; opacity:.5;
  transform:scaleX(0); transform-origin:left;
  transition:transform .55s cubic-bezier(.16,1,.3,1);
}
#mark:hover .nm::after,#mark:focus-visible .nm::after{ transform:scaleX(1) }
@media (prefers-reduced-motion:reduce){
  #mark .nm::after,#mark .mono-mark{ transition:none }
}
@media (max-width:560px){ #mark .nm{ display:none } }

/* ══════════ CURSOR + INK ══════════ */
@media (hover:hover) and (pointer:fine){
  body.nib, body.nib *{ cursor:none }
  #nib{
    position:fixed; left:0; top:0; z-index:120; pointer-events:none;
    width:26px; height:26px; margin:-3px 0 0 -3px;
    transition:opacity .3s;
  }
  #nib svg{ display:block; width:100%; height:100% }
}
#ink{ position:fixed; inset:0; z-index:119; pointer-events:none }
@media (prefers-reduced-motion:reduce){ #nib,#ink{ display:none } body.nib,body.nib *{ cursor:auto } }
