/* ---------- fonts ---------- */
@font-face{
  font-family:'Darker Grotesque';
  src:url('../fonts/darker-grotesque-latin.woff2') format('woff2');
  font-weight:300 700; font-style:normal; font-display:swap;
}
/* Drop garet-book.woff2 into assets/fonts/ and uncomment. Commented out so the site never
   404s for a font that isn't there - the stack below falls back until it exists.
@font-face{
  font-family:'Garet';
  src:url('../fonts/garet-book.woff2') format('woff2');
  font-weight:400; font-style:normal; font-display:swap;
}
*/

/* ---------- tokens ---------- */
:root{
  --ink:#1A1A1A; --sheet:#FFFFFF; --liner:#EFE9F6;
  --lilac:#B497D6; --lilac-deep:#7B5EA7; --lilac-deepest:#5C4180;
  --blossom:#FAD8DD; --blossom-core:#C66564;
  --hairline:#CFC7DE; --muted:#6B6B6B;

  --xs:4px; --sm:8px; --md:16px; --lg:24px; --xl:40px;
  --r-sheet:3px;

  --display:'Darker Grotesque','Avenir Next',system-ui,sans-serif;
  --ui:'Garet','Avenir Next','Century Gothic',system-ui,-apple-system,'Segoe UI',Roboto,sans-serif;

  --ease:cubic-bezier(.22,.61,.36,1);
  --dur:420ms;
  --dur-fast:220ms;

  --safe-t:env(safe-area-inset-top,0px);
  --safe-b:env(safe-area-inset-bottom,0px);
}

*,*::before,*::after{box-sizing:border-box}
[hidden]{display:none!important}

html,body{
  margin:0; padding:0; height:100%;
  overflow:hidden;                 /* the page never scrolls, swiping is handled in JS */
  overscroll-behavior:none;
  background:var(--liner);
  color:var(--ink);
  font-family:var(--ui);
  -webkit-text-size-adjust:100%;
  -webkit-tap-highlight-color:transparent;
}

/* ---------- shared type ---------- */
.date{
  font-family:var(--ui); font-size:.6875rem; letter-spacing:.14em;
  text-transform:uppercase; margin:var(--md) 0 0; color:var(--ink);
}
/* ---------- screens ---------- */
.screen{
  position:fixed; left:0; right:0; top:0;
  height:100vh; height:100svh;     /* svh keeps the nav visible when browser chrome shows */
  display:flex; flex-direction:column;
  margin:0 auto;
}
/* Frame the layout only on screens that aren't being held. Width can't tell an unfolded
   Fold (673px) from a small laptop, but the pointer can - anything handheld reports a
   coarse pointer at any width. Landscape gets framed too: this layout is portrait-only. */
@media (pointer:fine),(orientation:landscape){ .screen{ max-width:420px } }

/* ---------- surface ---------- */
.app{ z-index:20; background:var(--liner) }

.viewport{
  flex:1 1 auto; position:relative; overflow:hidden; min-height:0;
  padding-top:var(--safe-t);       /* there's no top bar to keep the notch off the content */
}
.track{
  display:flex; height:100%; width:100%;
  touch-action:none;               /* pinch, pan and swipe are handled in JS */
  will-change:transform;
}
.track.is-animating{ transition:transform var(--dur) var(--ease) }
.pane{
  flex:0 0 100%; height:100%; position:relative;
  display:flex; align-items:center; justify-content:center;
  padding:var(--sm);
}
/* width/height auto so offsetWidth is the painted size - the pan clamp depends on it */
.pane__img{
  max-width:100%; max-height:100%; width:auto; height:auto;
  display:block; transform-origin:center center;
  background:var(--sheet); border:1px solid var(--hairline);
  -webkit-user-select:none; user-select:none; -webkit-user-drag:none;
  will-change:transform;
  transition:filter var(--dur) var(--ease);   /* for the hint dim */
}
.pane__img.is-settling{ transition:transform var(--dur) var(--ease),filter var(--dur) var(--ease) }

/* Three rows, outer two equal, so the name lockup lands on the exact vertical centre
   whatever the copy below it does. No bottom padding: row 3 has to end at the nav. */
.pane--home{
  display:grid; grid-template-rows:1fr auto 1fr; justify-items:center;
  padding:0 var(--md);
  overflow:hidden;                 /* the branch hangs off the corner and is clipped */
}
/* Pivot sits near where the branch leaves the corner, so the sway never drags the cut
   end into view - points at the origin barely move. */
.home__branch{
  position:absolute; top:0; left:-3%;   /* clears the edge without burying the blossoms */
  width:91%;                            /* ratio not px, so the art grows with the screen */
  pointer-events:none;
  transform-origin:5% 17%;
  animation:branch-sway 9s ease-in-out infinite;
  animation-play-state:paused;
}
.pane--home.is-active .home__branch{ animation-play-state:running }
.home__branch img{
  display:block; width:100%; height:auto;
  transform:scaleX(-1);                 /* artwork faces left, it hangs from the other corner */
  -webkit-user-select:none; user-select:none;
}
/* Rotation alone swings it like a rigid plank. The out-of-phase skew makes the far end
   lag and recover, which is what reads as a breeze. Just over a degree, ~9px at the tip. */
@keyframes branch-sway{
  0%,100%{ transform:rotate(0deg)     skewY(0deg)    }
  30%    { transform:rotate(1.05deg)  skewY(.48deg)  }
  55%    { transform:rotate(.28deg)   skewY(-.34deg) }
  78%    { transform:rotate(-.72deg)  skewY(-.24deg) }
}
/* names-fit.png has its own alpha (make-fit.ps1 keys the white plate out), so no blend
   mode and no backdrop needed behind it. */
.home__names{ grid-row:2; width:87%; height:auto; display:block }
/* positioned so they can take a z-index at all - the petals are positioned and would
   otherwise paint over them */
.home__names,.home__below{ position:relative; z-index:1 }
/* The 2fr:3fr rows either side of the lead put it two fifths of the way from the date to
   the nav. Both rows need naming: on auto-placement the lead drops into the first fr
   and stretches through it. */
.home__below{
  grid-row:3; width:100%; align-self:stretch; text-align:center;
  display:grid; grid-template-rows:auto 2fr auto 3fr; justify-items:center;
}
.home__below .date{ grid-row:1; font-size:.9375rem }
.home__below .lead{ grid-row:3 }
/* One line, never wrapped - short enough to hold on a single row at 320px, and a two-line
   block competed with the date for weight. */
.lead{
  margin:0; white-space:nowrap;
  /* The rem is the intended size; the vw only takes over below 355px or if the default
     font size has been enlarged - a slightly smaller line beats a clipped one, and nowrap
     leaves no wrap to relieve it. The coefficient tracks the letter-spacing: at .06em the
     line exactly filled its column at 320px, so 3.1vw buys back ~10% headroom. */
  font-size:min(.6875rem,3.1vw); line-height:1.5; letter-spacing:.06em; color:var(--ink);
}

/* ---------- drifting petals ---------- */
/* Behind the branch and the copy, and inert - never a tap target, never read through. */
.petals{
  position:absolute; inset:0; overflow:hidden;
  pointer-events:none; z-index:0;
}
.petal{
  position:absolute; top:0; height:auto;
  --sway:16px;                     /* horizontal wander, overridden per petal below */
  --from:24vh;                     /* spawn height, never above the branch band */
  opacity:0;                       /* the keyframe owns visibility */
  animation:petal-drift 13s linear infinite;
  /* All four panes share one track, so without this the petals keep animating and
     compositing behind whichever sheet is open. */
  animation-play-state:paused;
}
.pane--home.is-active .petal{ animation-play-state:running }

/* One fall reused nine times. Vertical steps are measured from --from, not the top of the
   pane, so changing a spawn point doesn't distort the path below it. The sway reverses at
   the halfway mark so a petal reads as caught by air, not sliding down a diagonal. */
@keyframes petal-drift{
  0%   { transform:translate3d(0,var(--from),0) rotate(0deg); opacity:0 }
  18%  { opacity:.9 }
  25%  { transform:translate3d(var(--sway),calc(var(--from) + 22vh),0) rotate(90deg) }
  50%  { transform:translate3d(calc(var(--sway) * -.6),calc(var(--from) + 44vh),0) rotate(175deg) }
  74%  { opacity:.9 }
  75%  { transform:translate3d(calc(var(--sway) * .85),calc(var(--from) + 66vh),0) rotate(260deg) }
  95%  { opacity:0 }
  100% { transform:translate3d(0,calc(var(--from) + 88vh),0) rotate(345deg); opacity:0 }
}

/* Spawn points sit inside the branch's band rather than above the pane, so a petal looks
   like it came off the blossoms instead of arriving from off-screen - which makes the fade
   load-bearing. Mostly negative delays, so there are already petals in the air on the
   first frame instead of the pane filling up over ten seconds. */
.petals .petal:nth-child(1){ left:6%;  width:13px; --sway:14px; --from:22vh; animation-duration:12s;   animation-delay:-7s }
.petals .petal:nth-child(2){ left:19%; width:17px; --sway:22px; --from:17vh; animation-duration:15s;   animation-delay:-2s }
.petals .petal:nth-child(3){ left:31%; width:11px; --sway:10px; --from:30vh; animation-duration:10.5s; animation-delay:-11s }
.petals .petal:nth-child(4){ left:44%; width:15px; --sway:18px; --from:20vh; animation-duration:13.5s; animation-delay:-4.5s }
.petals .petal:nth-child(5){ left:57%; width:12px; --sway:13px; --from:34vh; animation-duration:16s;   animation-delay:0s }
.petals .petal:nth-child(6){ left:68%; width:18px; --sway:24px; --from:16vh; animation-duration:11.5s; animation-delay:-9s }
.petals .petal:nth-child(7){ left:79%; width:13px; --sway:12px; --from:27vh; animation-duration:14s;   animation-delay:-1s }
.petals .petal:nth-child(8){ left:88%; width:15px; --sway:20px; --from:19vh; animation-duration:12.5s; animation-delay:-6s }
.petals .petal:nth-child(9){ left:92%; width:11px; --sway:9px;  --from:32vh; animation-duration:17s;   animation-delay:-3s }

/* ---------- home entrance ---------- */
/* The lockup wipes in left to right. It's a wipe, not a traced pen stroke - names-fit.png
   is raster, and a real trace would need SVG centreline paths. At this speed it passes. */
@keyframes home-write{ from{ clip-path:inset(0 100% 0 0) } to{ clip-path:inset(0 0 0 0) } }
@keyframes home-fade{ from{ opacity:0 } to{ opacity:1 } }

/* Each step waits for the one before it, with a 100ms beat between - that gap is what makes
   it read as three events instead of one blur:
     200 write starts -> 1320 write ends -> 1420 date in -> 2020 date done
     -> 2120 lead starts -> 2820 settled. */
.home__names{ animation:home-write 1120ms linear 200ms both }
.home__below .date{ animation:home-fade 600ms var(--ease) 1420ms both }
.home__below .lead{ animation:home-fade 700ms var(--ease) 2120ms both }

/* Inert - anyone who already knows the gesture can pinch straight through it. */
.zoomhint{
  position:absolute; inset:0; z-index:30;
  display:flex; align-items:center; justify-content:center;
  padding:var(--xl) var(--lg);
  color:var(--sheet);
  opacity:0; pointer-events:none;
  transition:opacity var(--dur) var(--ease);
}
/* Dim the sheet itself rather than laying a scrim over the screen. The sheets are different
   shapes (Seating is 2304x3456, the others aren't) and a screen-sized scrim would dim the
   liner and nav too. As a filter it stops exactly at the sheet edge at any size or zoom,
   with nothing to measure and nothing to resync while panning. */
.track.is-hinting .pane__img{ filter:brightness(.3) }
.zoomhint.is-shown{ opacity:1 }
/* dim lands first, words follow - the pause registers before the copy does */
.zoomhint__inner{
  position:relative; text-align:center;
  opacity:0; transition:opacity var(--dur-fast) var(--ease);
}
.zoomhint.is-shown .zoomhint__inner{ opacity:1; transition-delay:var(--dur-fast) }
.zoomhint__icon{ width:40px; height:40px; display:block; margin:0 auto var(--md) }
/* pre-line: hard breaks, so the copy stacks the same way on every screen */
.zoomhint__text{
  margin:0; white-space:pre-line;
  font-size:.9375rem; line-height:1.5; letter-spacing:.02em;
}

/* the icon performs the gesture it names: two presses, then a rest */
@keyframes zoomhint-tap{
  0%,48%,100%{ transform:none }
  12%,36%    { transform:translateY(3px) scale(.9) }
  24%        { transform:none }
}
.zoomhint.is-shown .zoomhint__icon{ animation:zoomhint-tap 1600ms var(--ease) infinite }

.nav{
  flex:0 0 auto; display:flex; background:var(--sheet);
  border-top:1px solid var(--hairline);
  padding-bottom:var(--safe-b);
}
.nav__item{
  flex:1; min-height:44px; padding:var(--sm) var(--xs);
  background:none; border:0; cursor:pointer;
  font-family:var(--ui); font-size:.6875rem; letter-spacing:.14em;
  text-transform:uppercase; color:var(--muted);
  border-top:2px solid transparent; margin-top:-1px;
  transition:color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
/* selected state is colour + rule, never weight - there's only one body weight */
.nav__item[aria-selected="true"]{ color:var(--lilac-deep); border-top-color:var(--lilac-deep) }
.nav__item:focus-visible{ outline:2px solid var(--lilac-deep); outline-offset:-2px }

/* ---------- reduced motion ---------- */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    transition-duration:1ms!important; animation-duration:1ms!important;
    /* delays too, or a staggered entrance leaves content invisible with motion off */
    transition-delay:0ms!important; animation-delay:0ms!important;
  }
  /* the blanket 1ms above turns the looping icon into a flicker instead of stilling it */
  .zoomhint.is-shown .zoomhint__icon{ animation:none!important }
  /* Petals are motion and nothing else - stilling them strands nine of them frozen in
     mid-air, which looks broken rather than quiet. */
  .petals{ display:none }
  /* The branch is artwork, so it stays and just stops swaying. Without this the 1ms above
     cycles it through the keyframe several times a second. */
  .home__branch{ animation:none!important }
}
