/* The shared language of the site. A quiet studio wall with a little warmth in it, one object on it, a few words.
   One typeface. No colour of its own: the only colour on a page belongs to the product.
   Pages differ by their wall's tone, their relief, their material and the way they move. */

html[data-world]{--w-bg:#ffffff;--w-ink:#141311;--w-ink2:#6a655e;--w-line:rgba(20,19,17,.14);--w-acc:var(--w-ink);--display:var(--sans);--dw:400;--nav-ink:#141311;--night:#0f0e0d;--night-ink:#f2efea;--night-ink2:#a59f97;--cap:clamp(15px,1.06vw,18px);background:var(--w-bg)}
html[data-world] body{background:transparent;color:var(--w-ink)}
#field{position:fixed;inset:0;width:100vw;height:100lvh;z-index:-2;max-width:none}
html[data-world] .nav{font-size:var(--cap)}
html[data-world] .nav::before{display:none}
html[data-world] .nav__home{font-weight:500}
html[data-world] .nav__home span{margin-left:.7em;font-weight:400;opacity:.62}
@media (max-width:560px){html[data-world] .nav__home span{display:none}}
/* Which project this is, and where it stands among the five. */
.nav__where{margin:0;display:flex;align-items:baseline;gap:.7em;white-space:nowrap;letter-spacing:-.01em}
.nav__where::before{content:"";align-self:center;width:clamp(14px,1.6vw,26px);height:1px;background:currentColor;opacity:.4}
.nav__where b{font-weight:400}
.nav__where i{opacity:.62;font-variant-numeric:tabular-nums}
@media (max-width:760px){html[data-world] .nav__home span{display:none}}
@media (max-width:460px){.nav__where b{display:none}.nav__where::before{display:none}}
html[data-world] .nav__links a{color:inherit;opacity:.62;transition:opacity .3s}
html[data-world] .nav__links a:hover,html[data-world] .nav__links a[aria-current]{opacity:1;color:inherit}

/* One project on screen: a home section, a project's first screen, or the next project at a page's end.
   Its photograph hangs on the wall as a plate; the name stays under it, on the wall, never across the picture. */
.world{position:relative;height:250svh;color:var(--wi,var(--w-ink))}
[data-hero].world{height:340svh}
html[data-world] [data-hero].world.world--photo{height:215svh!important}
.world__pin{position:sticky;top:0;height:100svh;display:block;overflow:hidden;color:inherit}
.world__name{position:absolute;left:var(--gut);bottom:calc(clamp(26px,5svh,52px) + 1.72em*.5);margin:0;z-index:4;font-weight:400;font-size:clamp(28px,3vw,52px);line-height:1;letter-spacing:-.032em;white-space:nowrap;max-width:calc(100vw - 2*var(--gut))}
.world__name span{display:block}
.world__line{position:absolute;left:var(--gut);bottom:clamp(26px,5svh,52px);margin:0;z-index:4;max-width:30em;color:var(--w-ink2);font-size:clamp(15px,1.18vw,19px);line-height:1.3;letter-spacing:-.008em}
.world__stage{position:absolute;inset:0;z-index:3;pointer-events:none}
.world__stage canvas{width:100%!important;height:100%!important;opacity:0;transition:opacity .6s linear}
.world__stage.is-ready canvas{opacity:1} /* the object fades in once it has loaded, rather than appearing in one frame */
html.arrive .world__stage canvas{transition:none}
.world__drag{position:absolute;inset:0;z-index:2;cursor:grab;touch-action:pan-y}
.world__drag:active{cursor:grabbing}
.world__poster{display:none;position:absolute;inset:0;margin:0;z-index:1}
.world__poster img{width:100%;height:100%;object-fit:cover}
/* A link the size of the screen draws its focus ring off screen: ring the name instead. */
.world__pin:focus-visible,.onward:focus-visible{outline:none}
.world__pin:focus-visible .world__name,.onward:focus-visible .world__name{outline:2px solid currentColor;outline-offset:10px}
@media (max-width:720px){
  .world{height:220svh}
  [data-hero].world{height:280svh}
  html[data-world] [data-hero].world.world--photo{height:190svh!important}
  .world__line{max-width:calc(100vw - 2*var(--gut))}
}

/* The cover. --i (set on the pin by the page's script): 1 while the plate hangs on the wall, 0 once it has opened to the
   whole screen. The picture is laid out on the whole screen and seen through the plate, so nothing reflows as it opens;
   at rest it is drawn a little smaller (--ck, the share the gutters take, set by cover.js), so the plate shows the
   picture's whole width. The second photograph lies exactly over the first and comes up with the scroll (--b). */
.cover{position:absolute;inset:0;margin:0;z-index:1;overflow:hidden;--ct:13svh;--cb:25svh;--cx:var(--gut);background:var(--w-bg);
  clip-path:inset(calc(var(--i,1)*var(--ct)) calc(var(--i,1)*var(--cx)) calc(var(--i,1)*var(--cb)) calc(var(--i,1)*var(--cx)));will-change:clip-path}
.cover__a,.cover__b{position:absolute;inset:0}
.cover img{width:100%;height:100%;object-fit:cover;object-position:var(--at,50% 50%);transform-origin:50% calc((var(--ct) + 100svh - var(--cb))/2);transform:translate3d(0,calc(var(--py,0px) + var(--i,1)*var(--oy,0px)),0) scale(calc(1 - var(--i,1)*var(--ck,.08)));will-change:transform}
.cover__b{opacity:var(--b,0)} /* the other state comes up with the scroll, never under the pointer */
html.motion .cover img:not(.is-in){opacity:0}
html.motion .cover img{transition:opacity .45s linear}
html.arrive .cover img{transition:none}
/* Under a plate the name and its line are one block, so a line that wraps on a narrow screen never runs into the name. */
.world__cap{position:absolute;left:var(--gut);right:calc(var(--gut) + 44px);bottom:clamp(26px,5svh,52px);z-index:4;display:flex;flex-direction:column;gap:clamp(8px,1.3svh,14px)}
.world__cap .world__name,.world__cap .world__line{position:static;max-width:none}
.world__cap .world__line{max-width:30em}
/* The name and the line belong to the wall: they go as the plate opens over them. */
.world--photo .world__name,.world--photo .world__line{opacity:calc((var(--i,1) - .5)*2)}
@media (max-width:720px){.cover{--ct:11svh;--cb:27svh}}

/* Pain into sweet point: one statement, read at the pace of the scroll. */
.say{position:relative;height:210svh}
.say__pin{position:sticky;top:0;height:100svh;display:flex;flex-direction:column;justify-content:center;padding:0 var(--gut)}
.say p{font-family:var(--display);font-weight:400;font-size:clamp(29px,min(4vw,7.8svh),74px);line-height:1.12;letter-spacing:-.03em;max-width:17em;text-wrap:balance}
.say__pain{color:var(--w-ink2)}
.say__sweet{color:var(--w-ink);margin-top:.5em!important}
.say__ask{font-family:var(--sans)!important;font-size:clamp(16px,1.3vw,21px)!important;letter-spacing:-.01em!important;line-height:1.35!important;margin-top:clamp(24px,5svh,52px)!important;color:var(--w-ink2);max-width:28em!important}
html.motion .say .w{opacity:calc(.1 + .9*var(--on,0))}

/* Process: sideways, in cold black and white, until you look at one. */
.reel{position:relative;height:calc(var(--n,6)*46svh + 100svh)}
.reel__pin{position:sticky;top:0;height:100svh;overflow:hidden;display:flex;align-items:center}
.reel__track{display:flex;align-items:center;gap:clamp(20px,3.4vw,64px);padding:0 var(--gut);will-change:transform}
.reel__head{flex:none;width:min(70vw,7.4em);font-family:var(--display);font-weight:400;font-size:clamp(28px,3.4vw,60px);line-height:1.08;letter-spacing:-.03em}
.reel__item{flex:none;height:min(66svh,62vw);margin:0;position:relative;isolation:isolate;background:var(--w-bg)}
.reel__item img{display:block;height:100%;width:auto;max-width:none} /* in colour from the start: nothing waits for the pointer */
.reel__item figcaption{position:absolute;left:0;top:100%;margin-top:12px;color:var(--w-ink2);font-size:var(--cap);letter-spacing:-.005em;white-space:nowrap}
@media (max-width:720px){.reel__item{height:54svh}}

/* A real scene opens from a window to the whole screen. */
.grow{position:relative;height:230svh}
.grow__pin{position:sticky;top:0;height:100svh;overflow:hidden}
.grow__win{position:absolute;inset:0;clip-path:inset(calc(var(--i,1)*22%) calc(var(--i,1)*30%));will-change:clip-path}
.grow__win img{width:100%;height:100%;object-fit:cover;transform:scale(calc(1 + var(--i,1)*.12));will-change:transform}
html.motion .grow__win img:not(.is-in){opacity:0}
html.motion .grow__win img{transition:opacity .35s linear}
/* On a portrait screen a scene opens across the whole width and without the zoom, so a subject that spans the screen is
   never sliced by the window's sides while it opens. */
@media (max-aspect-ratio:1/1){.grow__win{clip-path:inset(calc(var(--i,1)*14%) 0 calc(var(--i,1)*30%) 0)}.grow__win img{transform:none}}
.grow__say{position:absolute;left:var(--gut);bottom:clamp(26px,5svh,52px);z-index:2;color:var(--gs,var(--w-ink));font-family:var(--display);font-size:clamp(22px,2.3vw,40px);line-height:1.1;letter-spacing:-.024em;opacity:var(--o,0);max-width:16em}

/* Pictures at slightly different speeds, with room around them. */
.drift{position:relative;display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:0 var(--gut);padding:clamp(80px,14svh,180px) var(--gut)}
.drift figure{margin:0;position:relative}
.drift img{width:100%;height:auto}
.drift figcaption{margin-top:12px;color:var(--w-ink2);font-size:var(--cap)}
.big{font-family:var(--display);font-weight:400;font-size:clamp(27px,3.2vw,58px);line-height:1.12;letter-spacing:-.03em}

/* The next project hangs on the same wall, exactly as its own first screen hangs it. */
.onward{position:relative;display:block;height:135svh;color:var(--wi,var(--w-ink))}
.onward__pin{position:sticky;top:0;height:100svh;overflow:hidden}
.onward .world__line{bottom:clamp(26px,5svh,52px)}
.onward .world__name,.onward .world__line,.onward__pin::after{opacity:calc((var(--i,1) - .5)*2);transition:none}
.world--cover .world__name,.world--cover .world__line,.world--cover .world__pin::after{opacity:calc((var(--i,1) - .5)*2)}
.onward__pin::after{content:"";position:absolute;right:var(--gut);bottom:clamp(26px,5svh,52px);width:26px;height:26px;z-index:4;background:currentColor;-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1'%3E%3Cpath d='M2 12h19M14 5l7 7-7 7'/%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1'%3E%3Cpath d='M2 12h19M14 5l7 7-7 7'/%3E%3C/svg%3E") center/contain no-repeat;transition:translate .5s var(--ease)}
@media (hover:hover){.onward:hover .onward__pin::after{translate:8px 0}}

/* Dark passages inside a page. */
.is-night{background:var(--night);color:var(--night-ink);--w-bg:var(--night);--w-ink:var(--night-ink);--w-ink2:var(--night-ink2);--w-line:rgba(242,239,234,.16)}

/* Without WebGL the wall is the page colour; the covers need nothing more. */
html.no-gl .world:not(.world--photo):not(.world--cover),html.no-gl .onward:not(.world--photo){height:100svh}
html.no-gl .world__stage,html.no-gl .world__drag{display:none}
html.no-gl .world__poster{display:block}

/* The first name settles in; everything after it is driven by the scroll. */
@keyframes settle{from{opacity:0;translate:0 12px}}
@media (prefers-reduced-motion:no-preference){
  [data-hero] .world__name,[data-hero] .world__line,section.world:first-of-type .world__name,section.world:first-of-type .world__line{animation:settle 1.4s var(--ease) backwards .15s}
  html.arrive [data-hero] .world__name,html.arrive [data-hero] .world__line{animation:settle 1.1s var(--ease) backwards .75s} /* the plate settles first, then the name comes up */
}

/* A film beside its words: a silent loop that plays by itself. The picture is dark, hung on the wall like a plate. */
.film{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:0 clamp(16px,2vw,32px);align-items:center;padding:clamp(90px,15svh,170px) var(--gut) 0}
.film__pic{grid-column:1/7;margin:0;justify-self:start;width:min(100%,calc(84svh*(var(--ar))))}
.film__pic video{display:block;width:100%;height:auto;aspect-ratio:var(--ar);background:#0a0a0b;cursor:pointer}
.film__pic video:focus-visible{outline:2px solid var(--w-ink);outline-offset:4px}
.film--round .film__pic video{border-radius:50%;clip-path:circle(49.1%);background:none} /* the mirror's own dark rim, kept thin */
.film__txt{grid-column:8/-1}
.film--flip .film__pic{grid-column:7/-1;grid-row:1;justify-self:end}
.film--flip .film__txt{grid-column:1/6;grid-row:1}
.film__txt h2{font-weight:400;font-size:clamp(28px,3.4vw,60px);line-height:1.08;letter-spacing:-.03em;max-width:11em}
.film__txt p{margin-top:1.1em;max-width:27em;color:var(--w-ink2);font-size:clamp(16px,1.32vw,21px);line-height:1.46;letter-spacing:-.006em}
.film__txt .film__note{margin-top:1.4em;font-size:var(--cap);line-height:1.35;letter-spacing:-.005em}
@media (max-width:900px){
  .film{display:block}
  .film__pic{width:min(100%,calc(78svh*(var(--ar))));margin:0 auto}
  .film__txt{margin-top:clamp(24px,4svh,40px)}
}

/* The process. Closed: a heading, a button and one row of small pictures, each at its own proportion (--a), so the row
   fills the width at one height. Open: the same pictures in place, whole, the button stays in reach
   while they are read. site.js moves each picture from one place to the other. */
.proc{position:relative;z-index:1;display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:clamp(16px,2vw,32px);padding:clamp(40px,7svh,88px) var(--gut) clamp(56px,9svh,104px);--gx:clamp(16px,2vw,32px)}
.proc__h{grid-column:1;grid-row:1;align-self:end;font-weight:400;font-size:clamp(28px,3.2vw,56px);line-height:1.04;letter-spacing:-.03em;text-wrap:balance}
.proc__btn{grid-column:2;grid-row:1/3;align-self:start;position:relative;z-index:3;display:inline-flex;align-items:center;gap:14px;min-height:44px;margin-top:clamp(0px,.9vw,14px);padding:0 16px;border:1px solid var(--w-ink);background:var(--w-bg);color:var(--w-ink);font:inherit;font-size:var(--cap);line-height:1;letter-spacing:-.008em;white-space:nowrap;cursor:pointer}
.proc.is-open .proc__btn{position:sticky;top:clamp(64px,9svh,92px)}
.proc__shut,.proc.is-open .proc__open{display:none}
.proc.is-open .proc__shut{display:inline}
.proc__btn i{position:relative;flex:none;width:13px;height:13px}
.proc__btn i::before,.proc__btn i::after{content:"";position:absolute;left:0;top:6px;width:13px;height:1px;background:currentColor;transition:transform .5s var(--ease)}
.proc__btn i::after{transform:rotate(90deg)}
.proc.is-open .proc__btn i::after{transform:none}
@media (hover:hover){.proc__btn:hover{background:var(--w-ink);color:var(--w-bg)}}
.proc__list{grid-column:1/-1;grid-row:2;display:flex;gap:8px;margin-top:clamp(20px,3.4svh,36px);list-style:none;cursor:zoom-in}
.proc__i{flex:var(--a) 1 0;min-width:0}
.proc__i figure{margin:0}
.proc__i img{display:block;width:100%;height:auto;transform-origin:0 0}
.proc.is-open .proc__list{flex-wrap:wrap;gap:clamp(28px,4.4svh,48px) var(--gx);cursor:auto}
/* a hair under its share, so three or four of them always fit their row; what is left over is handed back by the same shares */
.proc.is-open .proc__i{flex:var(--a) 1 calc((100% - (var(--n) - 1)*var(--gx))*var(--f) - 1px)}
@media (max-width:1000px){
  .proc.is-open .proc__i{flex:0 0 calc(50% - var(--gx)/2)}
}
@media (max-width:900px){
  /* closed on a narrow screen: the row keeps a height a finger can read and runs on under the thumb */
  .proc__list{overflow-x:auto;overscroll-behavior-x:contain;scrollbar-width:none;margin-inline:calc(-1*var(--gut));padding-inline:var(--gut);scroll-padding-inline:var(--gut)}
  .proc__list::-webkit-scrollbar{display:none}
  .proc__i{flex:0 0 calc(var(--a)*clamp(72px,11vw,96px))}
  .proc.is-open .proc__list{overflow:visible;margin-inline:0;padding-inline:0}
}
@media (max-width:600px){
  /* the button stands under the heading; its own row is a fixed step, and its area runs on through the list so it can stay in reach */
  .proc{grid-template-columns:minmax(0,1fr);grid-template-rows:auto 76px auto}
  .proc__btn{grid-column:1;grid-row:2/4;justify-self:start;margin-top:16px}
  .proc__list{grid-row:3;margin-top:0}
  .proc.is-open .proc__i{flex:0 0 100%}
}

