/* Yanze Li portfolio: the base every page stands on. The language of the site is in worlds.css. */
@font-face{font-family:"Geist";src:url(../fonts/geist-latin-wght-normal.woff2) format("woff2");font-weight:100 900;font-style:normal;font-display:swap}
@font-face{font-family:"Geist Mono";src:url(../fonts/geist-mono-latin-400-normal.woff2) format("woff2");font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:"Geist Mono";src:url(../fonts/geist-mono-latin-500-normal.woff2) format("woff2");font-weight:500;font-style:normal;font-display:swap}

:root{
  --bg:#ffffff;--ink:#141311;--fg:var(--ink);
  --mute:#6a655e;
  --gut:clamp(20px,5.6vw,92px);
  --ease:cubic-bezier(.19,1,.22,1);
  --ease-io:cubic-bezier(.65,.05,.2,1);
  --mono:"Geist Mono",ui-monospace,Menlo,monospace;
  --sans:"Geist",system-ui,-apple-system,"Helvetica Neue",sans-serif;
  color-scheme:light;
}
[data-page=about]{--bg:#ffffff}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;text-size-adjust:100%;background:var(--bg)}
html.lenis,html.lenis body{height:auto}
.lenis.lenis-smooth{scroll-behavior:auto!important}
.lenis.lenis-stopped{overflow:hidden}
body{margin:0;background:var(--bg);color:var(--fg);font:400 clamp(15px,1.08vw,17px)/1.55 var(--sans);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility;overflow-x:clip}
img,video,canvas,svg{display:block;max-width:100%}
img,video{height:auto}
picture{display:contents}
a{color:inherit;text-decoration:none}
h1,h2,h3,p,dl,dd,figure,ul,ol{margin:0;padding:0}
ul,ol{list-style:none}
em,i{font-style:normal}
button{font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer}
:focus-visible{outline:2px solid var(--fg);outline-offset:3px}
.nav a:focus-visible{outline-color:currentColor} /* the nav's own ink, light in a dark passage */
.is-night :focus-visible{outline-color:var(--night-ink)}
::selection{background:#141311;color:#ffffff}
.skip{position:fixed;left:var(--gut);top:-60px;z-index:100;background:var(--fg);color:var(--bg);padding:8px 12px}
.skip:focus{top:var(--gut)}
.vh{position:absolute!important;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
figcaption,h1,h2,h3{text-wrap:balance}
button:active,.nav a:active{opacity:.72}

/* Between pages, a plain cross-fade. */
@media (prefers-reduced-motion:no-preference){@view-transition{navigation:auto}}
::view-transition-old(root),::view-transition-new(root){animation-duration:.5s;animation-timing-function:var(--ease-io)}
/* A page change that does not continue one object (a home link, the nav) fades the old page out first and brings the
   new one up after it, so two objects never share the screen at partial opacity. Onward arrivals keep the cross-fade. */
@keyframes yl-out{to{opacity:0}}
@keyframes yl-in{from{opacity:0}}
html:not(.arrive)::view-transition-old(root){animation:yl-out .24s var(--ease-io) both}
html:not(.arrive)::view-transition-new(root){animation:yl-in .45s var(--ease-io) .28s both}
/* Restoring mid-page (reload, back, forward): the content waits for its layout (core.mjs head script). */
html.restoring #main,html.restoring .nav{visibility:hidden}

/* The nav stays on screen the whole way down, with no band of its own: only the words. They are drawn in white and
   take the difference with whatever lies under them, so they read dark on the pale wall, light on the night and on any
   photograph, with no colour of their own. */
.nav{position:fixed;inset:0 0 auto 0;z-index:50;display:flex;align-items:baseline;gap:clamp(12px,1.4vw,20px);padding:clamp(18px,2vw,28px) var(--gut);line-height:1;pointer-events:none;
  color:#fff!important;mix-blend-mode:difference}
/* Under the words, a light veil: 8% of the page's own wall and a soft blur, strongest at the top of the screen and easing
   away toward its foot, so it draws no edge.
   It is a separate layer, so the words' difference blend is not applied to it. */
.nav-veil{position:fixed;inset:0 0 auto 0;z-index:49;height:calc(2*clamp(18px,2vw,28px) + 1.4em + 40px);pointer-events:none;font-size:var(--cap,16px);
  background:color-mix(in srgb,var(--w-bg,var(--bg)) 8%,transparent);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
  -webkit-mask-image:linear-gradient(#000 0%,rgba(0,0,0,.82) 30%,rgba(0,0,0,.45) 62%,rgba(0,0,0,.14) 84%,transparent 100%);mask-image:linear-gradient(#000 0%,rgba(0,0,0,.82) 30%,rgba(0,0,0,.45) 62%,rgba(0,0,0,.14) 84%,transparent 100%)}
html.restoring .nav-veil{visibility:hidden}
.nav a{pointer-events:auto;position:relative;padding:12px 8px;margin:-12px -8px}
@media (pointer:coarse){.nav a{padding:15px 10px;margin:-15px -10px}} /* a 44px target for a finger, the same layout */
.nav__home{flex:none;white-space:nowrap;letter-spacing:-.01em}
.nav__links{display:flex;gap:clamp(18px,2.4vw,36px);margin-left:auto}
@media (hover:hover){.nav__home:hover{opacity:.6}}

/* Words that rise once. */
html.motion [data-rise]{opacity:0;transform:translateY(22px)}

/* A 3D scene pinned by a page. */
.stage{position:absolute;inset:0;width:100%;height:100%;touch-action:pan-y}
.stage canvas{width:100%!important;height:100%!important;display:block}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important}
}
