/* ══ nomad ══════════════════════════════════════════════════════════════
   White paper, black ink, one motif (the mark's asterisk). Everything
   centred. The only surface allowed its own visual language is the canvas
   of work.
   ────────────────────────────────────────────────────────────────────── */

@font-face{
  font-family:'SF Pro Display'; font-style:normal; font-weight:400;
  font-display:swap; src:url('../assets/fonts/SFProDisplay-Regular.woff2') format('woff2');
}
@font-face{
  font-family:'SF Pro Display'; font-style:normal; font-weight:500;
  font-display:swap; src:url('../assets/fonts/SFProDisplay-Medium.woff2') format('woff2');
}
@font-face{
  font-family:'SF Pro Display'; font-style:normal; font-weight:700;
  font-display:swap; src:url('../assets/fonts/SFProDisplay-Bold.woff2') format('woff2');
}
@font-face{
  font-family:'VCR OSD Mono'; font-style:normal; font-weight:400;
  font-display:block; src:url('../assets/fonts/VCR.woff2') format('woff2');
}

:root{
  --paper:#ffffff;         /* exactly the paper the mark video was shot on */
  --ink:#111014;           /* tinted near-black, never #000 */
  --ink-2:#5d5b63;
  --hair:#e4e2e6;
  --ease-out:cubic-bezier(.16,1,.3,1);          /* expo-out */
  --ease-in-out:cubic-bezier(.65,0,.35,1);
  --t-slow:1100ms;
  --t-mid:620ms;
}

*,*::before,*::after{ box-sizing:border-box; }

html,body{ height:100%; }
/* The address bar's slide is what makes 100vh wrong on a phone. Nothing here
   scrolls, so the bar rarely moves — but dvh is the honest unit and costs
   nothing where it is understood. */
@supports (height:100dvh){ html,body{ height:100dvh; } }
html{ overscroll-behavior:none; }
body{
  margin:0; background:var(--paper); color:var(--ink);
  -webkit-tap-highlight-color:transparent;
  -webkit-user-select:none; user-select:none;
  -webkit-text-size-adjust:100%;
  font-family:'SF Pro Display',-apple-system,BlinkMacSystemFont,'Helvetica Neue',Arial,sans-serif;
  font-weight:400; -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale;
  overflow:hidden; overscroll-behavior:none;
}
body[data-stage="work"], body[data-stage="page"]{ overflow:hidden; }

/* The iPod stands on black, lit only along its edges — see the RIM room in
   js/env.js. The mark before it and the page after it are both paper, so the
   ground tone is animated rather than switched. */
body{ transition:background-color 800ms var(--ease-in-out); }
body.is-dark{ background:#08080a; --ink-2:#8e8c96; }

/* ── the vignette ───────────────────────────────────────────────────── */
.vig{
  position:fixed; inset:0; z-index:50; pointer-events:none;
  opacity:1; will-change:opacity;
  background:radial-gradient(120% 88% at 50% 50%,
    rgba(8,8,10,0) 30%, rgba(8,8,10,.10) 55%,
    rgba(8,8,10,.30) 78%, rgba(8,8,10,.62) 100%);
}
.vig[hidden]{ display:none; }

/* ── the mark ───────────────────────────────────────────────────────── */
.mark{
  position:fixed; inset:0; display:grid; place-items:center;
  background:var(--paper); z-index:40;
  opacity:1; transition:opacity var(--t-mid) var(--ease-in-out);
}
.mark.is-out{ opacity:0; pointer-events:none; }
.mark[hidden]{ display:none; }
.mark__svg{
  /* The mark is a letter now, taller than it is wide, so it is sized off its
     height. Sized off width, as the boxed version was, it grows past the fold
     on a phone in portrait. */
  height:min(44vh,62vw); width:auto; display:block;
  /* the wipe carries the entrance; this only stops it snapping on */
  animation:markIn var(--t-mid) var(--ease-out) both;
}
@keyframes markIn{
  from{ opacity:0; }
  to{ opacity:1; }
}

/* ── webgl surface ──────────────────────────────────────────────────── */
.gl{
  position:fixed; inset:0; width:100%; height:100%; display:block; z-index:30;
  opacity:0; transition:opacity var(--t-mid) var(--ease-in-out);
  touch-action:none;
  /* An invisible full-viewport canvas still hit-tests. Left interactive it
     sits on top of the canvas of work and eats every drag. Only the iPod
     act ever wants the pointer. */
  pointer-events:none;
}
.gl[hidden]{ display:none; }
.gl.is-lit{ opacity:1; }
.gl.is-live{ pointer-events:auto; }
.gl.is-hot{ cursor:pointer; }
.gl.is-turning{ cursor:grabbing; }

/* ── canvas of work ─────────────────────────────────────────────────── */
.work{ position:fixed; inset:0; z-index:10; }
.work[hidden]{ display:none; }
.work__cv{
  position:absolute; inset:0; width:100%; height:100%; display:block;
  cursor:grab; touch-action:none;
}
.work__cv.is-drag{ cursor:grabbing; }
.work__cv.is-hot{ cursor:pointer; }
.work__hint{
  position:absolute; left:50%; transform:translateX(-50%);
  bottom:calc(clamp(18px,3.4vh,34px) + env(safe-area-inset-bottom,0px));
  margin:0; font-size:.6875rem; font-weight:500; letter-spacing:.16em;
  text-transform:uppercase; color:var(--ink-2);
  opacity:0; transition:opacity 900ms var(--ease-in-out);
  pointer-events:none;
}
.work__hint.is-lit{ opacity:.75; }
.work__hint.is-gone{ opacity:0; }

/* ── pages ──────────────────────────────────────────────────────────── */
.page{
  position:fixed; inset:0; z-index:60; background:var(--paper);
  display:grid; place-items:center;
  padding:calc(clamp(28px,6vw,80px) + env(safe-area-inset-top,0px))
          calc(clamp(28px,6vw,80px) + env(safe-area-inset-right,0px))
          calc(clamp(28px,6vw,80px) + env(safe-area-inset-bottom,0px))
          calc(clamp(28px,6vw,80px) + env(safe-area-inset-left,0px));
  overflow-y:auto; -webkit-overflow-scrolling:touch;
  opacity:0; transition:opacity var(--t-mid) var(--ease-in-out);
}
.page[hidden]{ display:none; }
.page.is-lit{ opacity:1; }
.page__in{ width:100%; max-width:34rem; text-align:center; }
.page__t{
  margin:0 0 1.6rem; font-size:clamp(2rem,5vw,3rem); font-weight:500;
  letter-spacing:-.035em; line-height:1.04;
}
.page__p{
  margin:0 auto; max-width:36ch; font-size:1.0625rem; line-height:1.65;
  color:var(--ink-2);
}
.page__cta{
  display:inline-block; margin-top:2.4rem; padding:.85rem 1.9rem;
  border:1px solid var(--ink); border-radius:999px;
  font-size:.9375rem; font-weight:500; letter-spacing:-.01em;
  color:var(--ink); text-decoration:none; background:transparent;
  transition:background var(--t-mid) var(--ease-out), color var(--t-mid) var(--ease-out);
  min-height:44px;
}
.page__cta:focus-visible{ background:var(--ink); color:var(--paper); }
.page__back{
  display:block; margin:3.2rem auto 0; padding:.6rem 1rem; min-height:44px;
  border:0; background:none; cursor:pointer; color:var(--ink-2);
  font-family:inherit; font-size:.6875rem; font-weight:500;
  letter-spacing:.16em; text-transform:uppercase;
}
.page__back:focus-visible{ color:var(--ink); }

/* ── skip ───────────────────────────────────────────────────────────── */
.skip{
  position:fixed;
  right:calc(clamp(14px,2.4vw,26px) + env(safe-area-inset-right,0px));
  bottom:calc(clamp(14px,2.4vh,26px) + env(safe-area-inset-bottom,0px));
  z-index:70; min-height:44px; padding:.55rem .9rem;
  border:0; background:none; cursor:pointer; color:var(--ink-2);
  font-family:inherit; font-size:.625rem; font-weight:500;
  letter-spacing:.18em; text-transform:uppercase;
  opacity:0; transition:opacity var(--t-mid) var(--ease-in-out);
  pointer-events:none;
}
.skip.is-lit{ opacity:.6; pointer-events:auto; }
.skip:focus-visible{ opacity:1; color:var(--ink); }

:focus-visible{ outline:2px solid var(--ink); outline-offset:3px; }

/* ── touch ──────────────────────────────────────────────────────────────
   A sticky :hover is the classic phone bug — the state latches on tap and
   stays until something else is tapped. Every hover rule lives behind a real
   hover; :focus-visible carries the keyboard, and touch gets neither. */
@media (hover:hover) and (pointer:fine){
  .page__cta:hover{ background:var(--ink); color:var(--paper); }
  .page__back:hover{ color:var(--ink); }
  .skip:hover{ opacity:1; color:var(--ink); }
}

@media (pointer:coarse){
  /* 42vw of a 390px screen is a 164px mark — too small to be the first thing
     anyone sees. Portrait gets the width it can afford; landscape is still
     governed by height. */
  /* 42vw of a 390px screen is a 164px mark. Portrait gets the width it can
     afford; landscape is still governed by height. */
  .mark__svg{ height:min(38vh,64vw); }
  /* the canvas is dragged, so nothing on it may be selected or long-pressed */
  .work__cv{ -webkit-touch-callout:none; }
  /* the hint has to clear the home indicator and read at arm's length */
  .work__hint{ font-size:.75rem; letter-spacing:.14em; }
  .skip{ font-size:.6875rem; padding:.7rem 1rem; }
  .page__p{ font-size:1rem; line-height:1.6; }
}

/* a phone on its side has almost no height to spend */
@media (pointer:coarse) and (orientation:landscape) and (max-height:520px){
  .page{ padding-block:calc(18px + env(safe-area-inset-top,0px))
                       calc(18px + env(safe-area-inset-bottom,0px)); }
  .page__t{ margin-bottom:.9rem; font-size:clamp(1.5rem,6vh,2rem); }
  .page__cta{ margin-top:1.4rem; }
  .page__back{ margin-top:1.6rem; }
}

@media (prefers-reduced-motion:reduce){
  /* keep every state reachable, just without the travel */
  .mark,.gl,.page,.work__hint,.skip{ transition-duration:1ms; }
  /* the orbit is the one thing here that actually travels, so it goes; the
     letter itself still has to be on screen, so it only stops fading in */
  .mark__orbit{ display:none; }
  .mark__svg{ animation-duration:1ms; }
}


/* ── the transport ──────────────────────────────────────────────────────
   Borrowed from eugenewan.art: a "Now Playing" pill that pages the site the
   way a transport pages an album. It sits above the pages themselves, so it
   never disappears out from under the hand that is using it, and it is the
   one piece of chrome allowed to persist across every stage after the intro.

   Top right, because the skip button already owns bottom right and the hint
   owns bottom centre. */
.np{
  position:fixed; z-index:80;
  top:calc(clamp(14px,2.2vh,24px) + env(safe-area-inset-top,0px));
  right:calc(clamp(14px,2.4vw,26px) + env(safe-area-inset-right,0px));
  display:flex; align-items:center; gap:.5rem;
  padding:.34rem .38rem .34rem .95rem;
  border-radius:999px;
  background:rgba(244,243,245,.82);
  border:1px solid var(--hair);
  /* the pill floats over photographs as often as over paper */
  backdrop-filter:saturate(1.4) blur(14px);
  -webkit-backdrop-filter:saturate(1.4) blur(14px);
  opacity:0; transform:translateY(-6px);
  transition:opacity var(--t-mid) var(--ease-out), transform var(--t-mid) var(--ease-out);
  pointer-events:none;
}
.np[hidden]{ display:none; }
.np.is-lit{ opacity:1; transform:none; pointer-events:auto; }

.np__label{
  font-size:.8125rem; font-weight:500; letter-spacing:-.01em; color:var(--ink);
  white-space:nowrap;
}
.np__pick{ position:relative; display:inline-flex; align-items:center; }
.np__sel{
  appearance:none; -webkit-appearance:none;
  font-family:inherit; font-size:.8125rem; font-weight:500; letter-spacing:-.01em;
  color:var(--ink); background:var(--paper);
  border:1px solid var(--hair); border-radius:999px;
  padding:.42rem 2rem .42rem 1rem; margin:0;
  cursor:pointer; min-height:34px;
}
.np__sel:focus-visible{ outline:2px solid var(--ink); outline-offset:2px; }
.np__chev{
  position:absolute; right:.72rem; width:10px; height:7px;
  color:var(--ink); pointer-events:none;
}
.np__btn{
  display:grid; place-items:center;
  width:34px; height:34px; padding:0;
  border:1px solid var(--hair); border-radius:50%;
  background:var(--paper); color:var(--ink); cursor:pointer;
  transition:background 180ms var(--ease-out), color 180ms var(--ease-out);
}
.np__btn svg{ width:15px; height:15px; fill:currentColor; }
.np__btn:active{ background:var(--ink); color:var(--paper); }
.np__btn:focus-visible{ outline:2px solid var(--ink); outline-offset:2px; }

/* ── the profile picture ────────────────────────────────────────────── */
.page__pfp{
  display:block; margin:0 auto 1.5rem;
  width:112px; height:112px; border-radius:50%;
  object-fit:cover; background:var(--hair);
}
.page__pfp--lg{ width:148px; height:148px; }

/* ── the links ──────────────────────────────────────────────────────── */
.links{ list-style:none; margin:2.2rem 0 0; padding:0; text-align:left; }
.links li + li{ margin-top:.5rem; }
.link{
  display:flex; align-items:baseline; justify-content:space-between; gap:1.2rem;
  padding:.85rem 1.25rem; min-height:44px;
  border:1px solid var(--hair); border-radius:14px;
  text-decoration:none; color:var(--ink); background:var(--paper);
  transition:border-color 200ms var(--ease-out), background 200ms var(--ease-out);
}
.link__n{ font-size:1rem; font-weight:500; letter-spacing:-.015em; }
.link__h{ font-size:.8125rem; color:var(--ink-2); text-align:right; }
.link:focus-visible{ border-color:var(--ink); outline:none; }

@media (hover:hover){
  .np__btn:hover{ background:var(--ink); color:var(--paper); }
  .link:hover{ border-color:var(--ink); }
}

@media (max-width:560px){
  /* the words go, the transport stays. On a phone the picker is the useful
     half of it and the label is the half that is only there to explain. */
  .np__label{ display:none; }
  .np{ padding:.34rem .38rem; }
}

@media (prefers-reduced-motion:reduce){
  .np{ transition-duration:1ms; }
}

/* ── the colour picker ──────────────────────────────────────────────────
   A button that opens a panel, top left, opposite the transport.

   The panel previews on hover: running a pointer down the list repaints the
   entire site under each ground, on the actual photographs, and leaving puts
   it back. A row of swatches can only ever show you the swatch, and the
   question is never what the colour looks like, it is what the colour does to
   the pictures.

   Under the five is a dial that moves hue and nothing else, so every position
   on it is a ground a photograph can survive. */
.pk{
  position:fixed; z-index:80;
  top:calc(clamp(14px,2.2vh,24px) + env(safe-area-inset-top,0px));
  left:calc(clamp(14px,2.4vw,26px) + env(safe-area-inset-left,0px));
  opacity:0; transform:translateY(-6px);
  transition:opacity var(--t-mid) var(--ease-out), transform var(--t-mid) var(--ease-out);
  pointer-events:none;
}
.pk[hidden]{ display:none; }
.pk.is-lit{ opacity:1; transform:none; pointer-events:auto; }

.pk__btn{
  display:flex; align-items:center; gap:.5rem;
  padding:.34rem .9rem .34rem .38rem; min-height:42px;
  border:1px solid var(--hair); border-radius:999px;
  background:var(--chrome,rgba(244,243,245,.82));
  backdrop-filter:saturate(1.4) blur(14px);
  -webkit-backdrop-filter:saturate(1.4) blur(14px);
  color:var(--ink); font:500 13px/1 inherit; cursor:pointer;
  transition:border-color 180ms var(--ease-out);
}
.pk__now{
  width:26px; height:26px; border-radius:50%;
  border:1px solid var(--hair); flex:none;
}
.pk__cap{ letter-spacing:-.01em; }
.pk__btn:focus-visible{ outline:2px solid var(--ink); outline-offset:2px; }

.pk__panel{
  position:absolute; top:calc(100% + 8px); left:0;
  width:232px; padding:.45rem;
  border:1px solid var(--hair); border-radius:16px;
  background:var(--paper);
  box-shadow:0 18px 44px -18px rgba(0,0,0,.34), 0 2px 8px -4px rgba(0,0,0,.2);
}
.pk__panel[hidden]{ display:none; }

.pk__list{ list-style:none; margin:0; padding:0; }
.pk__row{
  display:flex; align-items:center; gap:.7rem; width:100%;
  padding:.44rem .5rem; min-height:40px;
  border:0; border-radius:10px; background:none; cursor:pointer;
  color:var(--ink); font:500 13.5px/1 inherit; letter-spacing:-.01em;
  text-align:left;
}
.pk__row[aria-pressed="true"]{ background:var(--tile,rgba(128,128,128,.12)); }
.pk__row:focus-visible{ outline:2px solid var(--ink); outline-offset:-2px; }

/* four bars: paper, tile, quiet ink, ink. The whole theme in 44 pixels. */
.pk__chip{
  display:flex; flex:none; width:44px; height:22px;
  border:1px solid var(--hair); border-radius:6px; overflow:hidden;
}
.pk__chip i{ flex:1; }

.pk__own{
  margin-top:.35rem; padding:.55rem .5rem .3rem;
  border-top:1px solid var(--hair);
}
.pk__ownhead{
  display:flex; align-items:center; justify-content:space-between;
  margin-bottom:.55rem;
}
.pk__modes{ display:flex; gap:.25rem; }
.pk__mode{
  padding:.24rem .55rem; min-height:26px;
  border:1px solid var(--hair); border-radius:999px;
  background:none; color:var(--ink-2); cursor:pointer;
  font:500 11px/1 inherit; letter-spacing:.04em;
}
.pk__mode[aria-pressed="true"]{ background:var(--ink); color:var(--paper); border-color:var(--ink); }
.pk__mode:focus-visible{ outline:2px solid var(--ink); outline-offset:2px; }

/* the dial. Its track is the hue ramp it actually produces, mixed in the same
   space, so the control is a picture of its own output. */
.pk__dial{
  -webkit-appearance:none; appearance:none;
  display:block; width:100%; height:22px; margin:0; background:none;
  cursor:pointer;
}
.pk__dial::-webkit-slider-runnable-track{
  height:10px; border-radius:999px;
  background:var(--track); border:1px solid var(--hair);
}
.pk__dial::-moz-range-track{
  height:10px; border-radius:999px;
  background:var(--track); border:1px solid var(--hair);
}
.pk__dial::-webkit-slider-thumb{
  -webkit-appearance:none; appearance:none;
  width:18px; height:18px; margin-top:-5px;
  border-radius:50%; background:var(--thumb);
  border:2px solid var(--paper);
  box-shadow:0 0 0 1px var(--hair);
}
.pk__dial::-moz-range-thumb{
  width:18px; height:18px; border-radius:50%;
  background:var(--thumb); border:2px solid var(--paper);
  box-shadow:0 0 0 1px var(--hair);
}
.pk__dial:focus-visible{ outline:2px solid var(--ink); outline-offset:4px; }

/* the transport's own ground follows the theme too */
.np{ background:var(--chrome,rgba(244,243,245,.82)); }

@media (hover:hover){
  .pk__btn:hover{ border-color:var(--ink); }
  .pk__row:hover{ background:var(--tile,rgba(128,128,128,.12)); }
  .pk__mode:hover{ color:var(--ink); }
}

@media (max-width:560px){
  .pk__cap{ display:none; }
  .pk__btn{ padding:.34rem .38rem; }
}

@media (prefers-reduced-motion:reduce){
  .pk{ transition-duration:1ms; }
}
