/* One night, one sky. A fixed sky with the moon sits behind everything; the keyed paintings
   move over it on a single scroll timeline. Type only, no rules, boxes or ornaments. */
:root {
  --night: #05070b;
  --bone: #d4d0ca;
  --bone-2: rgba(212, 208, 202, .62);
  --bone-3: rgba(212, 208, 202, .38);
  --crimson: #820c0c;
  --ink: #0b0e13;
  --night-2: rgba(5, 7, 11, .62);
  --display: "Big Shoulders", "Big Shoulders Display", "Oswald", "Arial Narrow", sans-serif;
  --body: "Geist", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --mono: "Geist Mono", ui-monospace, Menlo, Consolas, monospace;
  --gl: max(16px, env(safe-area-inset-left, 0px));
  --gr: max(16px, env(safe-area-inset-right, 0px));
  --edge: clamp(20px, 4.2vw, 72px);
  color-scheme: dark;
}
* { box-sizing: border-box; }
html { background: var(--night); }
body { margin: 0; background: var(--night); color: var(--bone); font: 300 16px/1.55 var(--body); -webkit-font-smoothing: antialiased; overflow-x: hidden; }
a { color: inherit; text-decoration: none; }
img { max-width: none; }
::selection { background: var(--crimson); color: var(--bone); }
:focus-visible { outline: 1px solid var(--bone); outline-offset: 4px; }
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }

/* ---------- the sky (fixed, behind everything) ---------- */
#sky { position: fixed; inset: 0; top: calc(-1 * var(--pad, 0px)); height: calc(100% + 2 * var(--pad, 0px)); z-index: 0; overflow: hidden; background: var(--crimson) url(/img/sky.jpg) repeat; background-size: 512px 512px; }
#moon { position: absolute; left: 0; top: 0; width: var(--moon, 76px); height: var(--moon, 76px); will-change: transform; visibility: hidden;
  -webkit-mask: radial-gradient(circle calc(var(--moon, 76px) / 2) at calc(50% - var(--shadow, 100%)) 50%, transparent 98%, #000 100%);
          mask: radial-gradient(circle calc(var(--moon, 76px) / 2) at calc(50% - var(--shadow, 100%)) 50%, transparent 98%, #000 100%); }
#moon img { width: 100%; height: 100%; display: block; }
#moon img.dark { position: absolute; inset: 0; visibility: hidden; }
/* daylight: paper sky, spread from the moon by a mask the script draws */
#day { position: absolute; inset: 0; background: var(--bone) url(/img/sky-day.jpg) repeat; background-size: 512px 512px; visibility: hidden; }
#sky .cloud { position: absolute; left: 0; top: 0; will-change: transform; opacity: .95; }
/* the light twin shown over the dark opening, where the painted-dark cloud vanishes */
#sky .cloud.lit { filter: invert(1) brightness(.62); }

/* ---------- loader ---------- */
#loader { position: fixed; inset: 0; z-index: 60; pointer-events: none; display: grid; place-items: end center; padding-bottom: 14vh; transition: opacity .9s ease; }
#loader b { font: 400 11px/1 var(--mono); letter-spacing: .3em; color: var(--bone-2); font-variant-numeric: tabular-nums; }
/* a page that opens on paper loads on paper: the count has to be ink to be read */
html.opened-paper #loader b { color: var(--night-2); }
body.ready #loader { opacity: 0; }

/* ---------- chrome ----------
   Each corner is its own fixed piece so it can turn to ink on its own when the daylight passes under it. */
.nav, .hud { font: 400 11px/1 var(--mono); letter-spacing: .16em; text-transform: uppercase; }
.nav > *, .hud > * { position: fixed; z-index: 40; opacity: var(--dip, 0); }
.nav > .brand, .hud > .clock { left: max(var(--edge), var(--gl)); }
.nav > .links, .nav > .menu-btn, .hud > #chapter { right: max(var(--edge), var(--gr)); }
.nav > * { top: calc(env(safe-area-inset-top, 0px) + 22px); color: var(--bone); }
.nav > .links { display: flex; gap: clamp(14px, 2vw, 32px); }
.nav .links a { opacity: .86; }
.nav .links a:hover, .nav .links a[aria-current] { opacity: 1; }
.nav > .brand:hover, .menu-btn:hover { color: #fff; }
.menu-btn { display: none; font: inherit; letter-spacing: inherit; text-transform: inherit; background: none; border: 0; padding: 0; margin: 0; cursor: pointer; z-index: 55 !important; }
.hud > * { bottom: calc(env(safe-area-inset-bottom, 0px) + 20px); pointer-events: none; color: var(--bone-2); }
.hud .clock { font-variant-numeric: tabular-nums; color: var(--bone); letter-spacing: .1em; }
.nav > .ink, .hud > .ink { mix-blend-mode: difference; }

/* phone menu */
.menu { position: fixed; inset: 0; z-index: 50; background: var(--night); display: flex; flex-direction: column; justify-content: center; gap: 6px;
  padding: 0 max(var(--edge), var(--gl)); }
.menu[hidden] { display: none; }
.menu a { font: 200 clamp(44px, 13vw, 78px)/.95 var(--display); text-transform: uppercase; color: var(--bone); animation: menu-in .6s cubic-bezier(.2, .8, .2, 1) both; }
.menu a[aria-current] { font-weight: 600; }
.menu a:nth-child(2) { animation-delay: .04s; } .menu a:nth-child(3) { animation-delay: .08s; } .menu a:nth-child(4) { animation-delay: .12s; }
.menu a:nth-child(5) { animation-delay: .16s; } .menu a:nth-child(6) { animation-delay: .2s; }
@keyframes menu-in { from { opacity: 0; transform: translateY(18px); } }

/* ---------- the journey ---------- */
#journey { position: relative; z-index: 1; }
.pin { position: sticky; top: 0; height: var(--vh, 100vh); overflow: hidden; }
.layer { position: absolute; inset: 0; overflow: hidden; visibility: hidden; }
.strip { position: absolute; inset: 0; }
/* Fixed and inset:0, exactly like #sky, so the painting always covers the sky.
   Sizing it from a measured viewport height instead left crimson (or paper)
   strips under the status bar and the browser toolbar on a phone. */
/* Fixed and inset:0, exactly like #sky, and a sibling of it so no overflow
   ancestor can clip it (Safari does clip fixed children of overflow:hidden).
   z-index 0 with #sky, but later in the DOM, so it covers the sky; #journey
   is z-index 1 and keeps the words above the painting. */
#paint { position: fixed; inset: 0; top: calc(-1 * var(--pad, 0px)); width: 100%; height: calc(100% + 2 * var(--pad, 0px)); z-index: 0; pointer-events: none; transition: opacity .9s ease; }
body:not(.ready) #paint, body:not(.ready) #journey .layer { opacity: 0 !important; }

/* hero tower doors */
.door { position: absolute; left: 0; top: 0; display: block; transform-origin: 0 0; }
.door i { position: absolute; background: #f3efe8; opacity: 0; transition: opacity .3s; }
.door span { position: absolute; right: calc(100% + 10px); top: 50%; transform: translateY(-50%); white-space: nowrap;
  font: 400 17px/1 var(--mono); letter-spacing: .2em; text-transform: uppercase; color: var(--bone); opacity: calc(.7 * var(--lab, 1)); transition: opacity .3s, transform .3s; }
.door:hover span, .door:focus-visible span { opacity: var(--lab, 1); transform: translate(-8px, -50%); }
.door:hover i, .door:focus-visible i { opacity: 1; }
/* going in: the window's light goes out as the camera closes on it */
.door.going i { opacity: 1; background: var(--night); transition: background .45s ease; }

/* the dark between pages */
#veil { position: fixed; inset: 0; z-index: 80; background: var(--night); opacity: 0; pointer-events: none; }
html.dark-in #veil { opacity: 1; }
html.dark-in, html.dark-in body { background: var(--night); }
/* a page set on paper is on paper from its first frame */
/* .paper is the server-rendered first paint only, so a page that opens on paper
   never flashes red. The script drops it on the first frame and the paper sky
   becomes #day, which a wave can clip.
   The page behind the sky stays night whichever way the sky goes: iOS Safari
   insets the fixed sky below the status bar and above the toolbar, and whatever
   is behind it shows in those bands. Night reads as part of the phone; crimson
   or bone read as a broken frame. */
html.open-paper #sky { background: var(--bone) url(/img/sky-day.jpg) repeat; background-size: 512px 512px; }
html.open-dark #sky { background: var(--ink) url(/img/sky-open.jpg) repeat; background-size: 512px 512px; }
/* #day is whichever sky is not the crimson night. The home page opens on the dark
   one and keeps the paper one for the Miscellaneous room and the portrait, so the
   script swaps the texture while the sky is fully crimson and nothing is showing. */
#day.dark { background: var(--ink) url(/img/sky-open.jpg) repeat; background-size: 512px 512px; }

/* text beats, set into the paintings */
.beat { position: absolute; z-index: 20; will-change: opacity, transform; transform: translate(var(--tx, 0), calc(var(--ty, 0%) + var(--dy, 0px))); }
.label { font: 400 11px/1.4 var(--mono); letter-spacing: .18em; text-transform: uppercase; color: var(--bone-2); margin: 0 0 18px; }
.big { font-family: var(--display); font-weight: 200; text-transform: uppercase; line-height: .86; letter-spacing: .005em; margin: 0; text-wrap: balance; }
.big b { font-weight: 800; }
.mid { font: 200 clamp(34px, 4.4vw, 76px)/.92 var(--display); text-transform: uppercase; margin: 0; text-wrap: balance; }
.mid b { font-weight: 700; }
.copy { font: 300 clamp(15px, 1.15vw, 18px)/1.55 var(--body); color: var(--bone); max-width: 30em; margin: 18px 0 0; }
.w { opacity: .2; transition: opacity .12s linear; }
.go { display: inline-flex; gap: 12px; align-items: baseline; font: 400 11px/1 var(--mono); letter-spacing: .18em; text-transform: uppercase; margin-top: 26px; padding: 6px 0; }
.go .arr { display: inline-block; transition: transform .3s cubic-bezier(.2, .8, .2, 1); }
.go:hover .arr { transform: translateX(6px); }

.b-hero { left: max(var(--edge), var(--gl)); top: 15vh; width: min(56vw, 900px); --hero-fs: clamp(52px, 7.6vw, 150px); }
/* --hero-cap is only set on a short viewport (see the foot of this file); at a
   normal height this resolves to the band's own size, unchanged. */
.b-hero .big { font-size: min(var(--hero-fs), var(--hero-cap, 9999px)); }
.b-hero-foot { left: max(var(--edge), var(--gl)); bottom: 11vh; width: min(46vw, 640px); }
/* The standfirst, in the body face the rest of the site uses. It used to be 16px under
   a 100px headline, which read as an afterthought; it is half again as big now and the
   deliverables carry weight. The headline names the three disciplines, so emphasising
   them again here would only repeat it: what comes out of them is the new information. */
.b-hero-foot .copy {
  font: 300 var(--foot-size, clamp(18px, 1.5vw, 23px))/1.52 var(--body);
  max-width: none; margin-top: 20px;
}
.b-hero-foot .copy b { font-weight: 500; color: #fff; }
.b-street { left: 50%; bottom: 13vh; width: min(84vw, 1000px); --tx: -50%; text-align: center; }
.b-street .mid { font-size: clamp(32px, 4.2vw, 72px); }
.b-street .copy { margin-inline: auto; }
.room-copy { position: absolute; left: max(var(--edge), var(--gl)); bottom: 13vh; width: min(40vw, 620px); z-index: 3; }
.room-copy .big { font-size: clamp(64px, 10vw, 190px); }
.room-copy .copy { color: var(--bone); }
.b-right { right: max(var(--edge), var(--gr)); top: 50%; --ty: -50%; width: min(31vw, 470px); }
.b-right .mid { font-size: clamp(34px, 3.8vw, 66px); }
.b-left { left: max(var(--edge), var(--gl)); top: 50%; --ty: -50%; width: min(36vw, 560px); }
.num { font: 100 clamp(96px, 15vw, 260px)/.8 var(--display); letter-spacing: -.01em; font-variant-numeric: tabular-nums lining-nums; margin: 0; }
.num-label { font: 400 12px/1.4 var(--mono); letter-spacing: .2em; text-transform: uppercase; color: var(--bone-2); margin-top: 22px; }
.b-portrait-copy { right: max(var(--edge), var(--gr)); top: 50%; --ty: -50%; width: min(34vw, 520px); }
/* words that sit on the paper sky are set in ink */
.beat.ink, .beat.ink .copy { color: var(--night); }
.beat.ink .label { color: var(--night-2); }
.b-contact { left: 50%; bottom: 10vh; width: min(90vw, 1100px); --tx: -50%; text-align: center; }
.b-contact .big { font-size: clamp(56px, 9vw, 170px); }
.mailrow { position: relative; display: inline-block; margin-top: 26px; }
/* a button, so that clicking copies rather than opening a mail client, but it has
   to read as the address itself: no control chrome of any kind */
.mail { font: 400 12px/1 var(--mono); letter-spacing: .2em; text-transform: uppercase; color: inherit;
  appearance: none; -webkit-appearance: none; background: transparent; border: 0; border-radius: 0;
  padding: 6px 0; margin: 0; cursor: pointer; }
.mail:hover { color: #fff; }
/* Out of flow on purpose: in the flow it widened the row, and since the row is centred
   the address slid sideways when the note appeared and stayed there once it faded. */
.copied { position: absolute; left: calc(100% + 14px); top: 50%; transform: translateY(-50%);
  white-space: nowrap; pointer-events: none;
  font: 400 10px/1 var(--mono); letter-spacing: .18em; text-transform: uppercase;
  color: var(--bone-3); opacity: 0; transition: opacity .25s ease; }
.copied.on { opacity: 1; color: var(--bone-2); }
.social { display: flex; justify-content: center; gap: 28px; margin-top: 22px; font: 400 11px/1 var(--mono); letter-spacing: .18em; text-transform: uppercase; }
.social a { opacity: .75; } .social a:hover { opacity: 1; }

/* portrait in the open sky */
.portrait { position: absolute; left: 13vw; top: 13vh; height: 100vh; aspect-ratio: 1024 / 1372; z-index: 2; pointer-events: none; }


/* drums: the research reports, and the numbers */
.drum { position: absolute; left: max(var(--edge), var(--gl)); top: 0; bottom: 0; width: min(52vw, 860px); z-index: 20; }
.drum .item { position: absolute; left: 0; top: 50%; width: 100%; transform-origin: 0 50%; will-change: transform, opacity; visibility: hidden; }
.drum.nums { pointer-events: none; }
.drum.nums .num { font-size: clamp(64px, 8.6vw, 156px); }
.drum.nums .num-label { margin-top: 14px; }
.drum .item .t { display: block; font: 200 clamp(32px, 4.4vw, 78px)/.9 var(--display); text-transform: uppercase; text-wrap: balance; transition: font-weight .3s; }
.drum .item .m { display: block; margin-top: 10px; font: 400 11px/1 var(--mono); letter-spacing: .18em; text-transform: uppercase; color: var(--bone-2); }
.drum .item.on .t { font-weight: 400; }
.drum .item:not(.on) { pointer-events: none; }
.drum .item.on:hover .t { color: #fff; }
.b-rintro { left: max(var(--edge), var(--gl)); top: 50%; --ty: -50%; width: min(40vw, 640px); }
.b-rintro .big { font-size: clamp(72px, 11vw, 210px); }
.stats { display: flex; gap: 44px; margin-top: 30px; }
.stats b { display: block; font: 200 clamp(40px, 4.2vw, 72px)/.9 var(--display); }
.stats span { display: block; font: 400 10px/1.4 var(--mono); letter-spacing: .2em; text-transform: uppercase; color: var(--bone-2); margin-top: 10px; }

/* rooms: what is not a link, and the closing line */
.drum .item.still .m { color: var(--bone-3); }
.drum .item.coda .t { font-size: clamp(22px, 2.2vw, 36px); color: var(--bone-2); }
.b-rintro.low { top: auto; bottom: 12vh; --ty: 0%; }
/* the paper room: prints hung low on the dark terrace, so the paper sky stays open */
.drum.plates { top: 44vh; bottom: 0; }
.drum.plates .item { display: grid; grid-template-columns: auto 1fr; column-gap: clamp(18px, 2vw, 34px); align-items: center; }
.drum.plates .cover { grid-row: 1 / 3; height: clamp(150px, 30vh, 300px); aspect-ratio: 4 / 5; object-fit: cover; display: block; }
.drum.plates .item .t, .drum.plates .item .m { grid-column: 2; }
.drum.plates .item .t { align-self: end; }
.drum.plates .item .m { align-self: start; }
.drum.ink .item .t { color: var(--night); }
.drum.ink .item .m { color: var(--night-2); }
.drum.ink .item.coda .t { color: var(--night-2); }
.drum.ink .item.on:hover .t { color: #000; }

/* a walk past pictures */
.b-strip-intro { left: max(var(--edge), var(--gl)); top: 50%; --ty: -50%; width: min(44vw, 680px); }
.b-strip-intro .big { font-size: clamp(72px, 11vw, 210px); }
.strip-track { position: absolute; inset: 0; z-index: 10; pointer-events: none; }
.strip-track figure { position: absolute; left: 0; top: 0; margin: 0; transform-origin: 50% 50%; will-change: transform, opacity; visibility: hidden; }
.strip-track img { width: 100%; height: 100%; object-fit: cover; display: block; }
.b-strip-end { left: 50%; top: 50%; --tx: -50%; --ty: -50%; width: min(80vw, 900px); text-align: center; }
.b-strip-end .mid { font-size: clamp(34px, 4.2vw, 72px); }

/* an article: its painting first, then the words in the open sky */
.b-piece { left: max(var(--edge), var(--gl)); bottom: 12vh; width: min(58vw, 900px); }
.b-piece .big { font-size: clamp(48px, 6.4vw, 124px); }
.piece-body { position: relative; z-index: 2; max-width: 700px; margin: -8vh auto 0; padding: 0 max(var(--edge), var(--gl)) 26vh; }
.piece-body p { font: 300 clamp(17px, 1.3vw, 20px)/1.72 var(--body); color: var(--bone); margin: 0 0 1.25em; }
.piece-body h2 { font: 300 clamp(32px, 3.4vw, 56px)/.95 var(--display); text-transform: uppercase; margin: 1.5em 0 .55em; }
.piece-end { margin-top: 16vh; display: flex; justify-content: space-between; gap: 24px; flex-wrap: wrap; }

.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* Between the phone layout and a roomy desktop (a small window, or a zoomed-in
   browser) the hero kept its desktop type in a 56vw column, which packs the
   lines tight and runs them into the tower. Give it a wider column and smaller
   type through that range. */
@media (min-width: 761px) and (max-width: 1200px) {
  .b-hero { width: min(66vw, 760px); --hero-fs: clamp(38px, 5.6vw, 76px); }
  .b-hero-foot { width: min(46vw, 420px); }
}

@media (max-width: 760px) {
  /* no room beside it on a phone, so the note sits under the address */
  .copied { left: 50%; top: calc(100% + 4px); transform: translateX(-50%); }
  .nav > .links { display: none; }
  .nav > .menu-btn { display: block; }
  /* The tower's lit windows and their labels land on top of the headline on a
     narrow screen. The menu already reaches every room, so drop them here. */
  .door { display: none; }
  .b-hero { top: 13vh; width: calc(100vw - 2 * var(--edge)); --hero-fs: clamp(44px, 13vw, 76px); }
  .b-hero-foot { bottom: 9vh; width: calc(100vw - 2 * var(--edge)); }
  .b-hero-foot { --foot-size: clamp(16px, 4.5vw, 20px); }
  .b-street { bottom: 10vh; }
  .room-copy { width: calc(100vw - 2 * var(--edge)); bottom: 10vh; }
  .room-copy .big { font-size: clamp(56px, 17vw, 96px); }
  .b-right, .b-left, .b-portrait-copy, .b-rintro { left: max(var(--edge), var(--gl)); right: auto; top: auto; bottom: 10vh; --ty: 0%; width: calc(100vw - 2 * var(--edge)); }
  .drum.nums .num { font-size: clamp(64px, 22vw, 116px); }
  .drum.nums { top: 38vh; }
  .drum:not(.nums):not(.plates) { top: 22vh; }
  .drum.plates { top: 46vh; }
  .drum.plates .cover { height: 22vh; }
  .b-strip-intro, .b-piece { width: calc(100vw - 2 * var(--edge)); }
  .b-strip-intro { top: auto; bottom: 12vh; --ty: 0%; }
  .b-piece .big { font-size: clamp(40px, 11vw, 64px); }
  .portrait { left: calc(50vw - 27vh * 1024 / 1372); top: 8vh; height: 54vh; }
  .drum { width: calc(100vw - 2 * var(--edge)); }
  .drum .item .t { font-size: clamp(30px, 9vw, 48px); }
  .stats { gap: 28px; }
}
/* A browser zoomed past about 150%, and a phone turned on its side, both leave
   a viewport that is short rather than narrow. Every display size here is set
   in vw, so zooming in grew the type while shrinking the room for it, and the
   headline ran down into the paragraph beneath it. Below this height the sizes
   are capped against the height as well. A phone held upright is taller than
   this, and so is a laptop, so none of these rules reach them. */
@media (max-height: 580px) {
  /* Short and wide: the whole painting fits, tower included, so the headline is
     held to the left column where the sky is. That keeps it off the stone and
     leaves a strip of open sky for the moon to find. */
  .b-hero { --hero-cap: 11vh; top: 11vh; width: min(58vw, 560px); }
  .b-hero-foot { bottom: 13vh; width: min(56vw, 520px); }
  .b-hero-foot { --foot-size: min(clamp(15px, 1.5vw, 23px), 4.2vh); }
  .mid { font-size: min(clamp(34px, 4.4vw, 76px), 10vh); }
  .b-street .mid, .b-right .mid, .b-strip-end .mid { font-size: min(clamp(32px, 4.2vw, 72px), 10vh); }
  .room-copy .big { font-size: min(clamp(56px, 13vw, 190px), 15vh); }
  .b-rintro .big, .b-strip-intro .big { font-size: min(clamp(56px, 11vw, 210px), 17vh); }
  .b-piece .big { font-size: min(clamp(40px, 6.4vw, 124px), 14vh); }
  .b-contact .big { font-size: min(clamp(44px, 9vw, 170px), 15vh); }
  .drum.nums .num { font-size: min(clamp(64px, 8.6vw, 156px), 24vh); }
  .drum .item .t { font-size: min(clamp(30px, 4.4vw, 78px), 11vh); }
  .drum.plates .cover { height: clamp(100px, 26vh, 300px); }
  .copy { font-size: clamp(13px, 2.6vh, 17px); }
  .portrait { top: 6vh; height: 74vh; left: calc(50vw - 37vh * 1024 / 1372); }
}
@media (prefers-reduced-motion: reduce) { .go .arr, .door span { transition: none; } }
