/* ==========================================================================
   sumeet — site styles
   Single stylesheet: tokens, layout, hero scene, work section, chrome.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Test Söhne Breit — the display/copy face across the site.
   SF Pro stays the UI face; everything that used to be Poppins, Inter or
   Circular now resolves to this. Klim's German weight names map to the CSS
   scale: Leicht 300 · Buch 400 · Kräftig 500 · Halbfett 600 · Dreiviertelfett
   700. swap keeps text visible in a fallback until the face arrives.
   -------------------------------------------------------------------------- */
@font-face{font-family:'Test Sohne Breit';font-style:normal;font-weight:300;font-display:swap;src:url("../fonts/sohne-breit-300.woff2") format("woff2")}
@font-face{font-family:'Test Sohne Breit';font-style:italic;font-weight:300;font-display:swap;src:url("../fonts/sohne-breit-300i.woff2") format("woff2")}
@font-face{font-family:'Test Sohne Breit';font-style:normal;font-weight:400;font-display:swap;src:url("../fonts/sohne-breit-400.woff2") format("woff2")}
@font-face{font-family:'Test Sohne Breit';font-style:italic;font-weight:400;font-display:swap;src:url("../fonts/sohne-breit-400i.woff2") format("woff2")}
@font-face{font-family:'Test Sohne Breit';font-style:normal;font-weight:500;font-display:swap;src:url("../fonts/sohne-breit-500.woff2") format("woff2")}
@font-face{font-family:'Test Sohne Breit';font-style:italic;font-weight:500;font-display:swap;src:url("../fonts/sohne-breit-500i.woff2") format("woff2")}
@font-face{font-family:'Test Sohne Breit';font-style:normal;font-weight:600;font-display:swap;src:url("../fonts/sohne-breit-600.woff2") format("woff2")}
@font-face{font-family:'Test Sohne Breit';font-style:normal;font-weight:700;font-display:swap;src:url("../fonts/sohne-breit-700.woff2") format("woff2")}

:root{
  /* palette */
  --coral:#E4573D;
  --coral-deep:#D0442A;
  --cream:#F2DEA2;
  --paper:#FAFAF8;
  --red:#E4573D;
  --ash:#57534E;
  --ash-deep:#38352F;
  --iris:#EBD79C;          /* rendered-eye amber, shared by both themes */
  --iris-deep:#C9A85E;

  /* ---- dark (the default) ---- */
  --bg:#2E398C;
  --ink:#E5FE78;               /* body type            */
  --accent:#FFFFFF;            /* the word "see"       */
  --copy-ink:#FFFFFF;          /* the lines under it   */
  --stroke:#E5FE78;            /* drawn lid            */
  --iris-fill:#FFFFFF;
  --pupil-fill:#2E398C;
  --sclera:#F6F3EA;
  --ball-ring:rgba(8,12,44,.30);
  --ball-shadow:rgba(8,12,44,.45);
  --nav:#98A1DB;
  --nav-mark:#C9CFF2;
  --hint:#6B76C0;
  --ui-bg:rgba(255,255,255,.08);
  --ui-line:rgba(255,255,255,.17);
  --ui-fg:#A9B1E4;
  --tile:#252F7C;
  --tile-fg:#E5FE78;
  --tile-line:rgba(255,255,255,.13);
  --font-display:'Test Sohne Breit',-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;
  --font-copy:'Test Sohne Breit',-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;
  /* SF Pro renders natively on Apple platforms; Söhne Breit stands in
     everywhere SF Pro is unavailable */
  --font-ui:'SF Pro Text','SF Pro Display','SF Pro Icons',-apple-system,
            BlinkMacSystemFont,system-ui,'Test Sohne Breit','Helvetica Neue',Arial,sans-serif;
}
/* ---- light: white ground, the same blue and green as dark ---- */
:root[data-theme="light"]{
  --bg:#FFFFFF;
  --ink:#2E398C;
  --accent:var(--red);
  --copy-ink:#2E398C;
  --stroke:#2E398C;
  /* the iris carries the colour that lands on the word, so it matches */
  --iris-fill:var(--red);
  --pupil-fill:#2E398C;
  --sclera:#FFFFFF;
  --ball-ring:rgba(46,57,140,.24);
  --ball-shadow:rgba(46,57,140,.16);
  --nav:#8990BC;
  --nav-mark:#2E398C;
  --hint:#AEB3D0;
  --ui-bg:rgba(46,57,140,.05);
  --ui-line:rgba(46,57,140,.16);
  --ui-fg:#6E76A8;
  --tile:#F1F2F9;
  --tile-fg:#2E398C;
  --tile-line:rgba(46,57,140,.12);
}
*{margin:0;padding:0;box-sizing:border-box}
html,body{min-height:100%}
body{
  background:var(--bg);
  transition:background-color .45s ease;
  overflow:hidden;                 /* released once the intro finishes */
  font-family:var(--font-copy);
  -webkit-font-smoothing:antialiased;
}
body.scrollable{overflow:auto;overflow-x:hidden}

/* ---------- stage ---------- */
#hero{position:relative;height:100svh;min-height:520px}
#stage{position:absolute;inset:0;overflow:hidden}

/* ---------- nav: reachable during the intro ---------- */
nav{
  position:fixed;top:0;left:0;right:0;z-index:60;
  display:flex;justify-content:space-between;align-items:center;
  padding:26px clamp(20px,4vw,52px);
  font-size:13.5px;letter-spacing:.005em;font-weight:400;
  color:var(--nav);
}
nav{transition:color .22s ease}   /* fast enough to stay in step with the section edge */
nav a{color:inherit;text-decoration:none;transition:color .3s ease;
      font-family:var(--font-ui);letter-spacing:-.006em}
nav .links a{position:relative;padding-bottom:3px}
nav .links a::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:1.5px;
  background:var(--ink);
  transform:scaleX(0);transform-origin:0 50%;
  transition:transform .42s cubic-bezier(.3,.75,.25,1);
}
nav .links a:hover,
nav .links a:focus-visible{color:var(--ink)}
nav .links a:hover::after,
nav .links a:focus-visible::after{transform:scaleX(1)}
nav .links a:focus-visible{outline:none}
nav .links{display:flex;gap:clamp(14px,2.4vw,30px)}
nav .mark{color:var(--nav-mark)}

/* ---------- copy ---------- */
#copy{
  position:absolute;
  left:50%;top:50%;
  transform:translate(-50%,-50%);
  width:max-content;max-width:92vw;
  z-index:20;
  padding:0 clamp(12px,3vw,28px);
}
.line{
  font-family:var(--font-display);
  font-size:clamp(1rem,2.0vw,1.9rem);
  line-height:1.5;
  font-weight:300;
  letter-spacing:.002em;
  color:var(--ink);
  opacity:0;
  transform:translateY(11px);
  transition:opacity 1.5s ease,transform 1.5s cubic-bezier(.16,.78,.26,1),color .45s ease;
  white-space:nowrap;
}
.line.in{opacity:1;transform:none}

/* reserved space — the reveal never reflows the block */
/* the reveal is a soft-edged wipe — ink spreading, not a shutter */
#reveal{
  position:relative;
  font-weight:700;
  letter-spacing:-.008em;
  opacity:1;
  transform:none;
  transition:none;
  visibility:hidden;
  /* opaque half is exactly one line-width wide, so mask-position maps
     linearly onto "how much of the line is showing" */
  --mask:linear-gradient(90deg,
    #000 0 50%,
    rgba(0,0,0,.5) 54%,
    transparent 58%);
  -webkit-mask-image:var(--mask); mask-image:var(--mask);
  -webkit-mask-size:200% 100%;   mask-size:200% 100%;
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
  -webkit-mask-position:116% 0;  mask-position:116% 0;
}
#reveal.armed{visibility:visible}
#reveal.wipe{
  -webkit-mask-position:0% 0; mask-position:0% 0;
  -webkit-transition:-webkit-mask-position 1.7s cubic-bezier(.35,.05,.25,1);
  transition:mask-position 1.7s cubic-bezier(.35,.05,.25,1);
}
/* "see" only catches the light once the wipe has reached it */
#reveal .hl{color:var(--ink);transition:color .8s ease 1.15s}
#reveal.lit .hl{color:var(--accent)}
#reveal.instant, #reveal.instant .hl{
  -webkit-transition:none!important; transition:none!important;
}

/* ---------- the supporting lines ----------
   Typed on the same keyboard as the statement, so the hero finishes the way
   it started rather than switching gesture halfway through. The differences
   from the lines above are deliberate: a UI face instead of the display one,
   and wrapping instead of nowrap, so these read as the answer to the
   statement rather than as more of it. */
.line.sub{
  /* #copy is width:max-content, sized by the nowrap lines above. A wrapping
     line's max-content contribution is the whole sentence on one line, so
     left alone these would drag #copy out to its 92vw ceiling and the
     statement would slide left of where it was composed. width:0 makes them
     contribute nothing to that measurement; min-width:100% then fills
     whatever width the statement settled on. The measure that falls out of
     that is around sixty characters, which is where you want it anyway. */
  width:0;
  min-width:100%;
  white-space:normal;
  font-family:var(--font-ui);
  font-size:clamp(.875rem,1.1vw,1.05rem);
  line-height:1.62;
  font-weight:400;
  letter-spacing:.004em;
  color:var(--copy-ink);
}
.line.sub:first-of-type{margin-top:clamp(16px,2.4vh,32px)}
.line.sub + .line.sub{margin-top:.8em}

/* The untyped remainder is held in the box as hidden text, so every line is
   already its final size on the very first character. Without it a wrapping
   line grows a row at a time, and a nowrap statement grows #copy itself —
   either way the centred composition walks up or down the screen while the
   sentence is still being typed. */
.line .rest{visibility:hidden;font-style:normal}
.line .done{font-style:normal}

/* #stage clips, and the hero is only ever one viewport tall. On a short
   window these are the part that has to give. */
@media (max-height:760px){
  .line.sub{font-size:clamp(.8rem,1vw,.94rem);line-height:1.54}
  .line.sub:first-of-type{margin-top:14px}
  .line.sub + .line.sub{margin-top:.6em}
}

#copy.jolt{animation:jolt .42s cubic-bezier(.3,1.6,.4,1)}
@keyframes jolt{
  0%{transform:translate(-50%,-50%)}
  22%{transform:translate(-50%,calc(-50% + 5px))}
  55%{transform:translate(-50%,calc(-50% - 2px))}
  100%{transform:translate(-50%,-50%)}
}


/* ---------- the small witness ---------- */
/* the footprint stays 1em tall so the head never pushes the lines
   apart; the image itself overflows it, above and below */
.head{
  display:inline-block;
  position:relative;
  width:1.95em;height:1em;
  vertical-align:-.12em;
  margin-left:.9em;
  transform-origin:50% 76%;
  cursor:pointer;
  will-change:transform;
  outline:none;
}
.head img{
  position:absolute;left:0;bottom:-.62em;
  width:100%;height:auto;display:block;
  -webkit-user-drag:none;user-select:none;
  filter:drop-shadow(0 3px 10px rgba(0,0,0,.28));
}
.head:hover, .head:focus-visible{ animation:nod 1.45s cubic-bezier(.42,0,.4,1) infinite; }
.head:focus-visible img{ filter:drop-shadow(0 0 0 2px var(--accent)) drop-shadow(0 3px 10px rgba(0,0,0,.28)); }
@keyframes nod{
  0%  {transform:rotate(0deg)}
  18% {transform:rotate(-14deg)}
  46% {transform:rotate(12deg)}
  72% {transform:rotate(-7deg)}
  88% {transform:rotate(3deg)}
  100%{transform:rotate(0deg)}
}
@media (prefers-reduced-motion:reduce){
  .head:hover, .head:focus-visible{animation:none}
}


/* ---------- typing ---------- */
.sr-only{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;
}
/* a typed line reveals itself by being typed — it doesn't also fade in */
.line.typing{opacity:1;transform:none;transition:color .45s ease}
.caret{
  display:inline-block;
  width:2px;height:1.02em;
  vertical-align:-.16em;
  /* It costs nothing horizontally: the negative right margin gives back
     exactly what the width and the left margin take. One caret is shared
     by every line, so without this each line would be 3px wider while the
     caret was in it and 3px narrower the moment it left — and #copy is
     width:max-content and centred, so the whole composition would twitch
     sideways at each handover. It sits over the head of the hidden
     remainder, which nobody can see. */
  margin-left:.05em;margin-right:calc(-2px - .05em);
  background:var(--ink);
  animation:caret 1.06s steps(1) infinite;
  transition:background-color .45s ease;
}
@keyframes caret{0%,49%{opacity:1}50%,100%{opacity:0}}

/* the kid arrives once the sentence he's listening to is finished */
.head{opacity:0;transition:opacity .9s ease}
.head.in{opacity:1}
@media (prefers-reduced-motion:reduce){
  .head{opacity:1!important}
  .caret{animation:none;opacity:0}
}

/* ---------- eyes ---------- */
.eye{
  position:absolute;left:0;top:0;
  width:var(--s);height:var(--s);
  z-index:5;              /* eyes always travel behind the copy */
  will-change:transform,opacity;
  pointer-events:none;
}
.ball{
  position:absolute;inset:0;
  border-radius:50%;
  background:
    radial-gradient(circle at 38% 32%, #fbf6ea 0%, var(--sclera) 46%, #ddd3bf 80%, #b3a892 100%);
  overflow:hidden;
  box-shadow:0 0 0 1px var(--ball-ring), 0 6px 22px var(--ball-shadow);
}
.iris{
  position:absolute;left:50%;top:50%;
  width:52%;height:52%;
  border-radius:50%;
  background:
    radial-gradient(circle at 50% 50%,
      var(--iris-deep) 0%, var(--iris) 42%, #b8964e 84%, #6f5828 100%);
  box-shadow:inset 0 0 0 1px rgba(80,60,20,.35);
  transform:translate(-50%,-50%);
  will-change:transform;
  transition:background .4s ease;
}
.pupil{
  position:absolute;left:50%;top:50%;
  width:42%;height:42%;
  border-radius:50%;
  background:radial-gradient(circle at 50% 50%, #0d0b09 60%, #1e1913 100%);
  transform:translate(-50%,-50%);
}
.glint{
  position:absolute;left:31%;top:25%;
  width:13%;height:13%;
  border-radius:50%;
  background:rgba(255,255,255,.95);
  filter:blur(.3px);
}
.lid{
  position:absolute;left:-6%;right:-6%;height:56%;
  background:var(--bg);
  will-change:transform;
  transform:scaleY(0);
}
.lid.top{top:0;transform-origin:top center}
.lid.bot{bottom:0;transform-origin:bottom center}

/* ---------- geometric mode ---------- */
body.geo .ball{
  background:none;
  box-shadow:none;
  overflow:visible;
  transform-origin:50% 50%;
  display:flex;align-items:center;justify-content:center;
}
body.geo .ball svg{width:100%;height:100%;overflow:visible}
/* sharpie: two passes per lid, the second lighter and offset —
   the way a marker line gets gone over twice */
.g-stroke{
  fill:none;
  stroke:var(--stroke);
  stroke-linecap:round;
  stroke-linejoin:round;
  vector-effect:non-scaling-stroke;
}
.g-stroke.a{stroke-width:3.3px;opacity:.96}
.g-stroke.b{stroke-width:1.9px;opacity:.34}
.g-iris{fill:var(--iris-fill);opacity:.93}
.g-pupil{fill:var(--pupil-fill)}
.g-look{will-change:transform}


/* ---------- nav controls + clock ---------- */
nav .right{display:flex;align-items:center;gap:clamp(14px,2.6vw,30px)}
nav .tools{display:flex;gap:9px;align-items:center}
#sndHint{
  font-family:var(--font-ui);font-size:11.5px;letter-spacing:.01em;
  color:var(--nav);opacity:0;pointer-events:none;
  margin-right:2px;white-space:nowrap;
  transition:opacity .6s ease;
}
#sndHint.show{opacity:.85}
@media (max-width:700px){ #sndHint{display:none} }
.ctl{
  font-family:var(--font-ui);
  width:38px;height:38px;border-radius:11px;
  display:grid;place-items:center;
  background:var(--tile);color:var(--tile-fg);
  border:1px solid var(--tile-line);
  cursor:pointer;padding:0;
  -webkit-appearance:none;appearance:none;
  transition:background-color .22s ease,color .22s ease,
             border-color .22s ease,transform .2s cubic-bezier(.3,1.4,.5,1);
}
.ctl:hover{transform:translateY(-1.5px)}
.ctl:active{transform:translateY(0) scale(.94)}
.ctl:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.ctl svg{width:19px;height:19px;display:block;grid-area:1/1}
:root[data-theme="dark"]  #themeBtn .moon{display:none}
:root[data-theme="light"] #themeBtn .sun{display:none}
#soundBtn .cross{opacity:0;transition:opacity .2s ease}
#soundBtn.muted .wave{opacity:0}
#soundBtn.muted .cross{opacity:1}
#soundBtn .wave{transition:opacity .2s ease}
/* breathes until the browser lets the ambience actually start */
#soundBtn.pending{animation:breathe 2.6s ease-in-out infinite}
@keyframes breathe{0%,100%{opacity:1}50%{opacity:.45}}

#clock{
  position:fixed;left:clamp(20px,4vw,52px);bottom:22px;z-index:70;
  /* The mono stack was doing a job — a clock is a number that changes, and
     tabular figures stop the minute from nudging the city sideways. SF Pro
     Text does the same job without changing typeface: font-variant-numeric
     asks for the tabular set, which is exactly the part of a mono face a
     clock actually needs. */
  font-family:var(--font-ui);
  font-variant-numeric:tabular-nums;
  font-size:11px;letter-spacing:.14em;text-transform:uppercase;
  font-weight:500;
  color:var(--hint);
  opacity:0;transition:opacity .9s ease,color .45s ease;
  pointer-events:none;
}
#clock.in{opacity:1}
#clock .sep{opacity:.45;margin:0 .5em}

@media (max-width:560px){
  nav{padding:20px 18px;font-size:12px}
  nav .links{gap:15px}
  nav .right{gap:15px}
  .ctl{width:34px;height:34px;border-radius:10px}
  .ctl svg{width:17px;height:17px}
  #clock{font-size:10px;letter-spacing:.12em;bottom:58px}
}


/* ===================== second fold: work =====================
   Each project is a full-bleed plate with its background keyed out, laid
   over a flat section colour. The list sits underneath the plates, so the
   artwork can crop into it exactly the way it does in the designs. */
:root{ --pbg:#FEFDED; --cream-ink:#1C1C1C; --cream-mute:#A5A5A5; }
#work{
  position:relative;
  min-height:100svh;
  overflow:hidden;
  background:var(--pbg);
  transition:background-color .55s ease;
}
.proj-frame{
  position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:max(100%, calc(100svh * 1440 / 1024));
  aspect-ratio:1440 / 1024;
  container-type:inline-size;
}
.proj-plates{position:absolute;inset:0;z-index:2;pointer-events:none}
.proj-plate{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:fill;
  opacity:0;transition:opacity .5s ease;
}
.proj-plate.on{opacity:1}

/* the four still plates now open their case study. The anchor itself stays
   transparent to the pointer so it never covers the project list underneath
   (which is what the hover swap and its sound live on); a hotspot over the
   artwork on the right is the only live part, and only while the plate is the
   one on screen. Mirrors how optivento's tablet is the only live thing there. */
a.proj-plate{pointer-events:none;cursor:pointer}
a.proj-plate>img{position:absolute;inset:0;width:100%;height:100%;object-fit:fill}
.plate-hot{
  position:absolute;inset:0 0 0 50%;
  pointer-events:none;visibility:hidden;cursor:pointer;
  -webkit-tap-highlight-color:transparent;
}
a.proj-plate.on .plate-hot{pointer-events:auto;visibility:visible}

/* ---------- optivento: the plate that answers back ----------
   The drawing labels its own iPad "click/hover to access live order
   dashboard", so this plate is built rather than drawn: a layer for the
   sheet, a layer for the bubble, and a link that lifts the real dashboard
   out over the top of both. Its own container-type means every cq unit in
   here measures against the plate, which is the frame on a desktop and the
   540px card on a phone -- so one set of numbers covers both. */
.proj-plate.op{
  container-type:inline-size;
  /* The frame is deliberately bigger than the viewport on anything squarer
     than 1.40625:1, and #work crops the overflow. These say how much is
     being cropped off each edge, which is what keeps the dashboard inside
     the window rather than inside the artboard. */
  --fw:max(100vw, calc(100svh * 1440 / 1024));
  --fh:max(100svh, calc(100vw * 1024 / 1440));
  --crop-x:calc((var(--fw) - 100vw) / 2);
  --crop-y:calc((var(--fh) - 100svh) / 2);
  /* the dashboard's right edge: whichever margin bites first, the plate's
     or the window's */
  --dev-r:max(3.2%, calc(var(--crop-x) + 2.6vw));

  /* ---------- the size of the drawing ----------
     The other four plates are single images that are meant to be cropped;
     this one is a composition with a tablet you have to be able to aim at,
     so it has to fit the window instead. The artboard says the sheet is
     49.36% of the frame wide, which is 90.13% of the frame tall — but the
     frame is taller than the window on every screen wider than 1.40625:1,
     so on a 16:9 laptop that fills the window and then some, and the top
     and bottom of the drawing get cropped away.
     So the sheet is whichever is smaller: the size the artboard asks for,
     or the size that leaves 28px of air above and below it in the actual
     window. Because the frame's aspect ratio is fixed, the same length can
     be written two ways -- as a share of the frame's width or of its
     height -- and the pair below are the same number of pixels expressed
     for the two kinds of property. That is what lets the tablet hotspot
     and the dashboard be placed against the drawing rather than against
     the artboard, and stay placed at every size. */
  --draw-w:min(49.36%, calc((100svh - 56px) * 912 / 1184));
  --draw-h:min(90.13%, calc(100svh - 56px));
  --draw-r:max(4.42%, calc(var(--crop-x) + 3vw));
  /* the dashboard, at the share of the drawing it holds in the design, so
     the two shrink together and the composition keeps its proportions */
  --dev-w:calc(var(--draw-w) * .8104);
  --dev-h:calc(var(--draw-h) * .4417);
}

/* the sheet — centred on the window rather than hung off the artboard's top */
.op-draw{
  position:absolute;
  right:var(--draw-r);top:50%;
  width:var(--draw-w);height:auto;
  transform:translateY(-50%);transform-origin:50% 50%;
  box-shadow:0 1px 2px rgba(28,28,28,.05), 0 14px 40px rgba(28,28,28,.06);
  transition:transform .6s cubic-bezier(.18,.86,.3,1),
             opacity   .45s ease,
             filter    .45s ease;
}

/* ---------- the bubble ----------
   It sits in the artboard's bottom-left corner, which on a cropped frame is
   somewhere below the bottom of the window. Anchored to the window's own
   edges instead, and capped in height so that on a short screen it shrinks
   rather than climbing into the project list above it. */
.op-bubble{
  position:absolute;
  left:max(1%, calc(var(--crop-x) + 2vw));
  bottom:max(1.2%, calc(var(--crop-y) + 46px));
  width:min(19%, 32.7svh);
  aspect-ratio:1000 / 854.8;
  /* its own container, so the sentence inside is sized against the bubble
     and not against the plate — otherwise capping the width above would
     leave full-size type in a smaller shape */
  container-type:inline-size;
  transition:opacity .45s ease;
}
.op-bubble-shape{
  position:absolute;inset:0;width:100%;height:100%;
  fill:#E3E1DB;stroke:#1C1C1C;stroke-width:8;
  stroke-linejoin:round;stroke-linecap:round;
}
.op-bubble-text{
  position:absolute;left:16.5%;right:9%;top:15.5%;
  font-family:var(--font-display);
  font-size:5.37cqw;line-height:1.44;font-weight:400;
  color:#1C1C1C;letter-spacing:.002em;
}

/* ---------- the link ----------
   Full-plate so the dashboard can be positioned against the plate, but
   transparent to the pointer: only the tablet and the dashboard are live.
   Hidden outright until the plate is the one on screen, which also keeps it
   out of the tab order while it is invisible. */
.op-hot{
  position:absolute;inset:0;display:block;
  pointer-events:none;visibility:hidden;
  -webkit-tap-highlight-color:transparent;
}
.proj-plate.op.on .op-hot{visibility:visible}

/* ---------- the tablet in the drawing ----------
   Measured off the artwork as a share of the sheet, not of the plate: the
   tablet is a thing inside the drawing, so it has to move and scale with
   the drawing rather than sit at a fixed spot on the artboard. Both edges
   are quoted from the drawing's right edge and its vertical centre, which
   are the two things the rule above pins down. */
.op-tap{
  position:absolute;
  right:calc(var(--draw-r) + .3643 * var(--draw-w));
  width:calc(.2654 * var(--draw-w));
  top:calc(50% - .1503 * var(--draw-h));
  height:calc(.1431 * var(--draw-h));
  pointer-events:auto;cursor:pointer;border-radius:1.2%/1.4%;
}

/* ---------- the dashboard ----------
   Anchored by its right edge to whichever margin bites first, the plate's
   or the window's, and sized as a share of the drawing so the two stay in
   proportion. Vertically it keeps the offset from the drawing's centre
   that it has in the design. */
.op-dev{
  position:absolute;
  right:var(--dev-r);
  top:calc(50% - .2712 * var(--draw-h));
  width:var(--dev-w);
  height:var(--dev-h);
  pointer-events:none;cursor:pointer;
  opacity:0;
  /* the origin sits where the tablet falls inside this box, so shrinking
     the dashboard collapses it back into the drawing rather than into
     nowhere */
  transform-origin:35% 44%;
  transform:translate(-2%, 7%) scale(.8);
  filter:drop-shadow(0 18px 38px rgba(28,28,28,.18));
  transition:opacity .2s ease, transform .34s cubic-bezier(.4,0,.2,1);
}

.op-hot:hover .op-dev,
.op-hot:focus-visible .op-dev{
  opacity:1;transform:none;pointer-events:auto;
  transition:opacity .3s ease, transform .62s cubic-bezier(.18,.86,.3,1);
}
/* attention transfers rather than competes: the sheet steps back as the
   dashboard comes forward */
.proj-plate.op:has(.op-hot:hover) .op-draw,
.proj-plate.op:has(.op-hot:focus-visible) .op-draw{
  /* the translate has to be restated: it is what centres the sheet, and a
     transform list replaces the whole list rather than adding to it */
  transform:translateY(-50%) scale(.955);opacity:.72;filter:saturate(.85)
}
.proj-plate.op:has(.op-hot:hover) .op-bubble,
.proj-plate.op:has(.op-hot:focus-visible) .op-bubble{opacity:.4}

.op-hot:focus-visible{outline:none}
.op-hot:focus-visible .op-tap{
  outline:2px solid var(--cream-ink);outline-offset:3px;border-radius:4px;
}

/* the list never moves */
.proj-nav{
  position:absolute;left:21.7%;top:49.2%;transform:translateY(-50%);
  z-index:1;
  font-family:var(--font-display);line-height:1.38;
}
.proj-label{
  font-size:1.55cqw;font-weight:300;color:var(--cream-mute);
  margin-bottom:1.38em;
}
.proj-list{list-style:none}
.proj{
  display:inline-flex;align-items:center;gap:.42em;
  font-size:1.55cqw;font-weight:300;
  color:var(--cream-mute);text-decoration:none;white-space:nowrap;
  transition:color .3s ease;
}
.proj.on{color:var(--cream-ink);font-weight:700}

/* the marker: the same eye, still following you */
.marker{
  width:1.02em;height:1.02em;border-radius:50%;position:relative;flex:none;
  background:radial-gradient(circle at 38% 32%, #fbf6ea 0%, #F1EBDA 46%, #ddd3bf 80%, #b3a892 100%);
  box-shadow:0 0 0 1px rgba(0,0,0,.16), 0 2px 5px rgba(0,0,0,.16);
  overflow:hidden;opacity:0;transition:opacity .3s ease;
}
.proj.on .marker{opacity:1}
.marker i{position:absolute;left:50%;top:50%;border-radius:50%;transform:translate(-50%,-50%)}
.marker .mi{width:56%;height:56%;will-change:transform;
  background:radial-gradient(circle at 50% 50%, #7C9455 0%, #6E8C4A 44%, #4E6531 86%, #33421F 100%)}
.marker .mp{width:44%;height:44%;background:#14120E}
.marker .mg{left:30%;top:26%;width:16%;height:16%;transform:none;background:rgba(255,255,255,.9)}

/* the fixed chrome has to survive a light section */
body.nav-cream nav{color:#8C887E}
body.nav-cream nav .mark{color:var(--cream-ink)}
body.nav-cream nav .links a:hover,
body.nav-cream nav .links a:focus-visible{color:var(--cream-ink)}
body.nav-cream nav .links a::after{background:var(--cream-ink)}
body.nav-cream .ctl{background:rgba(0,0,0,.05);color:var(--cream-ink);border-color:rgba(0,0,0,.12)}
body.nav-cream #sndHint{color:#8C887E}
body.on-cream #clock{color:#B4AF9E}
body.on-cream #panel button{background:rgba(0,0,0,.05);color:#8C887E;border-color:rgba(0,0,0,.12)}
body.on-cream #panel button:hover{color:var(--cream-ink);border-color:var(--cream-ink)}
body.on-cream #panel button.sel{background:var(--cream-ink);color:#fff;border-color:var(--cream-ink)}
body.on-cream #panel .sep{background:rgba(0,0,0,.14)}

/* on a phone the full-bleed frame would push the list off-screen,
   so it stacks instead */
@media (max-width:820px){
  #work{display:grid;align-content:center;padding:clamp(84px,11vh,110px) 0 clamp(112px,15vh,140px)}
  .proj-frame{
    position:static;transform:none;
    width:100%;aspect-ratio:auto;
    display:grid;gap:clamp(20px,4vh,34px);justify-items:center;
  }
  .proj-nav{position:static;transform:none;text-align:center}
  .proj-label{font-size:1.05rem;margin-bottom:1.1em;letter-spacing:.02em}
  /* the list is the primary control on a phone, so give every option a real
     tap target: bigger type, and vertical padding between rows so a thumb
     lands on one name at a time instead of a cramped stack */
  .proj-list{display:grid;justify-items:center;gap:.2rem}
  .proj{font-size:1.4rem;padding:.42em .3em;line-height:1.15}
  /* the plate art sits on the right of each landscape artboard (on desktop
     the list fills the left). With the list moved above on mobile, a square
     card plus object-fit:cover crops each plate down to its own artwork, and
     a per-plate object-position centres that artwork instead of leaving it
     hanging off to one side. */
  .proj-plates{position:relative;width:min(90vw,440px);aspect-ratio:1/1;inset:auto}
  .proj-plate{object-fit:cover}
  a.proj-plate>img{object-fit:cover}
  a.proj-plate[data-key="nirvana"] >img{object-position:67% 50%}
  a.proj-plate[data-key="uniform"] >img{object-position:50% 48%}
  a.proj-plate[data-key="nirvana2"]>img{object-position:75% 50%}
  a.proj-plate[data-key="unsmoke"] >img{object-position:63% 52%}
  /* the list is its own block above the card here, not laid over it, so the
     whole card is a safe tap target */
  .plate-hot{inset:0}

  /* There is no hover to hang the reveal on and no room for four lines of
     bubble at this size, so the plate resolves into its own end state: the
     sheet and the dashboard it opens, both there from the start, the whole
     card a link. The frame is no longer wider than the window here, so the
     cropping arithmetic goes back to a plain margin. */
  .proj-plate.op{--dev-r:12%}
  .op-bubble{display:none}
  .op-tap{display:none}
  .op-hot{pointer-events:auto}
  /* The card is a fitted 1440x1024 box inside the viewport rather than a
     frame overflowing it, so nothing is cropped and none of the window
     arithmetic above applies: the drawing goes back to sitting on the
     artboard, and the dashboard sits where the hover would have left it. */
  .op-draw{
    right:auto;left:22%;top:4.88%;width:49.36%;transform:none;
    opacity:.92;box-shadow:0 1px 2px rgba(28,28,28,.05), 0 6px 18px rgba(28,28,28,.07);
  }
  .op-dev{
    opacity:1;transform:none;pointer-events:auto;
    top:34%;width:34%;height:auto;aspect-ratio:684 / 484;
    filter:drop-shadow(0 8px 18px rgba(28,28,28,.16));
  }
}

/* impact ring */
#ring{
  position:absolute;left:0;top:0;
  width:20px;height:20px;margin:-10px 0 0 -10px;
  border-radius:50%;
  border:1.5px solid var(--accent);
  opacity:0;z-index:25;pointer-events:none;
}
#ring.go{animation:ring .6s cubic-bezier(.15,.85,.3,1) forwards}
@keyframes ring{
  0%{opacity:.7;transform:scale(.3)}
  100%{opacity:0;transform:scale(6.5)}
}

/* ---------- cursor pupil (the transfer) ---------- */
/* after the eye is gone, the cursor is what's left watching */
#cursor{
  position:fixed;left:0;top:0;width:42px;height:42px;
  margin:-21px 0 0 -21px;
  z-index:80;pointer-events:none;opacity:0;
  transform:translate(-300px,-300px);
  transition:opacity .6s ease;
}
#cursor i{
  display:block;width:100%;height:100%;
  background:url("../img/cursor-sun.png") center/contain no-repeat;
  animation:sunspin 30s linear infinite;
  scale:1;
  transition:scale .2s cubic-bezier(.3,1.6,.5,1);
  filter:drop-shadow(0 2px 7px rgba(0,0,0,.28));
}
#cursor.press i{scale:.8}
@keyframes sunspin{to{transform:rotate(360deg)}}
#cursor.on{opacity:1}
@media (prefers-reduced-motion:reduce){
  #cursor i{animation:none}
}

/* ---------- prototype controls (not part of the design) ---------- */
#panel{
  position:fixed;right:16px;bottom:14px;z-index:90;
  display:flex;gap:8px;align-items:center;
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;
}
#panel button{
  font-family:var(--font-ui);
  font-size:11.5px;line-height:1;letter-spacing:.012em;
  background:var(--ui-bg);color:var(--ui-fg);
  border:1px solid var(--ui-line);
  padding:7px 12px;border-radius:99px;cursor:pointer;
  transition:.2s;
}
#panel button:hover{color:var(--ink);border-color:var(--ink)}
#panel button.sel{color:var(--bg);background:var(--ink);border-color:var(--ink)}
#panel .sep{width:1px;height:14px;background:var(--ui-line);display:inline-block}
#panel #replay{padding:6px;width:27px;height:27px;display:grid;place-items:center}
#panel #replay svg{width:14px;height:14px}
#hint{
  position:fixed;left:50%;bottom:16px;transform:translateX(-50%);
  z-index:70;color:var(--hint);font-size:11px;letter-spacing:.14em;
  text-transform:uppercase;font-family:ui-monospace,monospace;
  transition:opacity .5s ease;
}
#hint.gone{opacity:0}

@media (max-width:560px){
  .line{white-space:normal}
}

@media (prefers-reduced-motion:reduce){
  .line{opacity:1!important;transform:none!important;transition:none!important}
  #reveal{visibility:visible!important;
    -webkit-mask-image:none!important;mask-image:none!important}
  #reveal .hl{color:var(--accent)!important}
  /* nothing is typed in this mode, so the remainder must not stay hidden */
  .line .rest{visibility:visible!important}
  .eye{display:none}
  #hint{display:none}
  #clock{opacity:1!important;transition:none!important}
  #soundBtn.pending{animation:none}

  /* The optivento reveal is information, not decoration, so it stays --
     it just arrives instead of travelling, and the sheet dims without
     moving. */
  .op-draw,.op-dev,.op-bubble{transition:opacity .18s ease!important}
  .op-dev{transform:none!important}
  /* the sheet dims without moving — but the translate stays, because it is
     what centres it rather than part of the gesture */
  .proj-plate.op:has(.op-hot:hover) .op-draw,
  .proj-plate.op:has(.op-hot:focus-visible) .op-draw{transform:translateY(-50%)!important}
}

/* ===================== third fold: meanwhile =====================
   The panel is one artboard, 1320 x 938 in the design. Every element is
   placed as a percentage of that, and type is sized in cqw, so the whole
   composition scales as a single picture instead of reflowing. */
#meanwhile{
  --mw-top:96px;                     /* the fixed nav owns this much */
  --mwbg:#2E398C;
  --mw-ink:#17181C;
  --mw-mark:#2F4BE8;                 /* the sharpie */
  position:relative;
  min-height:100svh;
  overflow:hidden;
  background:var(--mwbg);
  transition:background-color .55s ease;
}
/* Unlike the work plates this fold is not full-bleed: the artboard is
   fitted whole into the space under the nav, so every photo, sticker and
   caption stays inside the fold at any window shape. The section colour
   fills whatever is left over. */
.mw-frame{
  position:absolute;left:50%;
  top:calc(var(--mw-top) + (100svh - var(--mw-top)) / 2);
  transform:translate(-50%,-50%);
  width:min(100%, calc((100svh - var(--mw-top)) * 1320 / 938));
  aspect-ratio:1320 / 938;
  container-type:inline-size;
}
.mw-panels{position:absolute;inset:0}
.mw-panel{
  position:absolute;inset:0;
  opacity:0;visibility:hidden;
  transition:opacity .45s ease, visibility 0s linear .45s;
}
.mw-panel.on{opacity:1;visibility:visible;transition:opacity .45s ease}
.mw-panel img{position:absolute;display:block}

/* --- shared bits --- */
.mw-cap{
  position:absolute;
  font-family:var(--font-ui);
  font-size:1.06cqw;line-height:1.42;letter-spacing:-.004em;
  color:var(--mw-ink);margin:0;
}
.mw-arrow{width:7.1cqw;height:auto;filter:drop-shadow(0 1px 2px rgba(0,0,0,.10))}
.mw-photo, .mw-panel .rounded{border-radius:1.05cqw}

/* --- intro --- */
.mw-lockup{left:59.77%;top:4.7%;width:35.2%;height:auto}
.mw-sub{
  position:absolute;right:3.94%;top:15.1%;margin:0;
  font-family:var(--font-display);font-weight:300;
  font-size:1.44cqw;letter-spacing:.002em;color:#E5FE78;
  white-space:nowrap;
}
.mw-caret{
  display:inline-block;width:.07em;height:1em;margin-left:.06em;
  background:#E5FE78;vertical-align:-.12em;
  animation:mwblink 1s steps(1,end) infinite;
}
.mw-sub.done .mw-caret{display:none}
@keyframes mwblink{0%,50%{opacity:1}50.01%,100%{opacity:0}}
.mw-hint{
  position:absolute;right:3.94%;top:22.4%;margin:0;
  /* lowercase, the way the rest of the page talks — the tracking that made
     the caps legible is dialled back to suit it */
  font-family:var(--font-ui);font-size:.86cqw;letter-spacing:.03em;
  color:#98A1DB;
  opacity:0;transition:opacity .7s ease .3s;
}
.mw-panel.on .mw-hint.in{opacity:1}
#meanwhile.picked .mw-hint{opacity:0;transition-delay:0s}
/* She is the one thing meant to run off the screen. The artboard is fitted,
   so it can be narrower than the window — anchor her to the window's own
   left edge and grow her by exactly that difference, which keeps her the
   same share of the screen that she has in the design. */
.mw-girl{
  --gap:max(0px, (100vw - 100%) / 2);
  left:calc(-1 * var(--gap));top:31.9%;width:calc(46.2% + var(--gap));height:auto;
  transform:translateY(16%);opacity:0;
  transition:transform 1.05s cubic-bezier(.18,.72,.24,1), opacity .7s ease;
}
.mw-panel.on .mw-girl.up{transform:none;opacity:1}

/* --- cooking --- */
.mw-cook-cap{
  left:0;right:0;top:13.9%;text-align:center;
  font-size:1.14cqw;font-weight:700;color:#E1503A;letter-spacing:-.01em;
}
.mw-cook-grid{
  position:absolute;left:13.33%;top:20.8%;width:73.5%;
  display:grid;grid-template-columns:repeat(3,1fr);aspect-ratio:970/551;
}
.mw-cook-grid img{position:relative;width:100%;height:100%;object-fit:cover}
.mw-cook-sticker{left:2.4%;top:59.5%;width:18.2%;height:auto;z-index:2}

/* --- art --- */
.mw-art-canvas{left:11.36%;top:12.3%;width:32.9%;height:auto;border-radius:1.05cqw;
  box-shadow:0 .9cqw 1.8cqw rgba(20,22,40,.13)}
.mw-art-stall {left:47.88%;top:7.0%;width:20.6%;height:auto;border-radius:1.05cqw;
  box-shadow:0 .8cqw 1.5cqw rgba(20,22,40,.13)}
.mw-art-fair  {left:64.92%;top:15.3%;width:19.9%;height:auto;border-radius:1.05cqw;
  box-shadow:0 .8cqw 1.5cqw rgba(20,22,40,.13)}
.mw-art-merch {left:67.58%;top:42.6%;width:18.7%;height:auto;border-radius:1.05cqw;
  box-shadow:0 .9cqw 1.8cqw rgba(20,22,40,.16);z-index:2}
.mw-art-a1{left:42.6%;top:48.8%;width:7.1%;z-index:3}
.mw-art-c1{left:46.06%;top:56.9%;width:13.5%}
.mw-art-a2{left:69.6%;top:71.6%;width:5.0%;z-index:3;transform:rotate(-118deg)}
.mw-art-c2{left:58.18%;top:79.6%;width:11.5%}

/* --- podcast --- */
.mw-pod-room{left:10.76%;top:16.3%;width:33.9%;height:auto;border-radius:1.05cqw;
  box-shadow:0 .9cqw 1.7cqw rgba(20,22,40,.12)}
.mw-pod-cube{left:39.6%;top:20.6%;width:30.4%;height:auto;z-index:2;
  filter:drop-shadow(0 1cqw 1.6cqw rgba(20,22,40,.18))}
.mw-pod-card{
  position:absolute;left:60.4%;top:20.1%;width:17.0%;z-index:3;display:block;
  border-radius:.8cqw;overflow:hidden;
  transition:transform .25s cubic-bezier(.3,1.4,.5,1), box-shadow .25s ease;
}
.mw-pod-card img{position:relative;width:100%;height:auto;display:block}
.mw-pod-card:hover{transform:translateY(-2px);box-shadow:0 .7cqw 1.4cqw rgba(20,22,40,.22)}
.mw-pod-card:focus-visible,.mw-pod-link:focus-visible{outline:2px solid var(--mw-mark);outline-offset:3px;border-radius:.4cqw}
.mw-pod-blob{
  position:absolute;left:61.3%;top:69.0%;width:5.2%;aspect-ratio:1;
  background:#FBE7AE;border-radius:50%;
}
.mw-pod-link{position:absolute;z-index:2;display:block;transition:transform .25s cubic-bezier(.3,1.4,.5,1)}
.mw-pod-link img{position:relative;width:100%;height:auto}
.mw-pod-link:hover{transform:translateY(-2px)}
.mw-pod-spotify{left:63.7%;top:71.4%;width:7.1%}
.mw-pod-apple  {left:63.7%;top:76.7%;width:9.8%}

/* --- sport --- */
.mw-sp-cluster{left:17.73%;top:13.2%;width:29.0%;height:auto;border-radius:1.05cqw}
.mw-sp-tennis {left:46.36%;top:22.9%;width:30.8%;height:auto;border-radius:1.05cqw;
  box-shadow:0 .9cqw 1.7cqw rgba(20,22,40,.12)}
.mw-sp-cap{left:52.27%;top:13.2%;width:18.5%}
.mw-sp-a1{left:49.0%;top:20.8%;width:4.6%;z-index:3;transform:rotate(-105deg) scaleY(-1)}
.mw-sp-a2{left:29.8%;top:62.6%;width:4.8%;z-index:3;transform:rotate(150deg)}
.mw-sp-counter{left:9.7%;top:66.6%;width:24%}
.mw-sp-counter b{display:block;margin-top:.5em;font-weight:700}
.mw-sp-badge{left:32.73%;top:71.6%;width:22.9%;height:auto;z-index:2}

/* --- the rail --- */
.mw-rail{
  position:absolute;right:4.2%;top:36%;
  display:grid;gap:3.1cqw;justify-items:center;
  z-index:6;
}
.mw-tab{
  position:relative;display:grid;place-items:center;
  width:5.2cqw;height:5.2cqw;padding:0;border:0;background:none;
  cursor:pointer;-webkit-appearance:none;appearance:none;
  transition:transform .3s cubic-bezier(.3,1.5,.5,1);
}
.mw-tab img{
  position:relative;width:auto;height:auto;
  max-width:2.6cqw;max-height:2.6cqw;
  transition:transform .3s cubic-bezier(.3,1.5,.5,1);
}
.mw-tab:hover img, .mw-tab:focus-visible img, .mw-tab.sel img{transform:scale(1.12)}
.mw-tab:focus-visible{outline:none}
/* The word sits under the icon, outside the ring rather than inside it:
   the ring is inset:0 on the button, so anything added to the button's
   flow would push the ring out around it and the sharpie would stop
   being a circle. Absolute keeps the ring exactly the size it was drawn
   at and drops the label into the gap between tabs, which is already
   3.1cqw of nothing. It carries the sharpie's own colour so it inverts
   with the panel the same way the ring does — quiet at rest, full
   strength on the one you're looking at. */
.mw-tab-label{
  position:absolute;left:50%;top:calc(100% + .1cqw);
  transform:translateX(-50%);
  font-family:var(--font-ui);
  /* the cqw size alone renders around 10px on a laptop — under the readable
     floor — so hold it at 16px and only let it grow past that on very tall or
     very wide screens where the artboard is genuinely large */
  font-size:max(16px, .82cqw);line-height:1;letter-spacing:.01em;font-weight:500;
  color:var(--mw-mark);opacity:.62;white-space:nowrap;pointer-events:none;
  transition:opacity .25s ease,color .45s ease;
}
.mw-tab:hover .mw-tab-label,
.mw-tab:focus-visible .mw-tab-label{opacity:.85}
.mw-tab.sel .mw-tab-label{opacity:1}
/* the sharpie ring: drawn on, wiped off */
.mw-ring{
  position:absolute;inset:0;
  overflow:visible;pointer-events:none;
}
.mw-ring path{
  fill:none;stroke:var(--mw-mark);
  stroke-width:2.6;stroke-linecap:round;stroke-linejoin:round;
  opacity:0;
  stroke-dasharray:var(--len);stroke-dashoffset:var(--len);
  transition:stroke-dashoffset .42s cubic-bezier(.35,.85,.3,1), opacity .18s ease;
}
.mw-tab:hover .mw-ring path,
.mw-tab:focus-visible .mw-ring path{opacity:.62;stroke-dashoffset:0}
.mw-tab.sel .mw-ring path{opacity:1;stroke-dashoffset:0}
.mw-tab.sel .mw-ring path:not(.b){stroke-width:3.1}
.mw-tab .mw-ring path.b{stroke-width:1.5;opacity:0;transition-delay:.06s}
.mw-tab:hover .mw-ring path.b,
.mw-tab:focus-visible .mw-ring path.b{opacity:.34}
.mw-tab.sel .mw-ring path.b{opacity:.6}
/* on the blue panel the sharpie has to be lighter than the ground */
#meanwhile[data-chrome="dark"]{--mw-mark:#7FB4FF}

/* --- phone: the artboard stops being full-bleed and just fits --- */
@media (max-width:820px){
  /* mobile: the intro fold stops being a fitted landscape picture and becomes
     a vertical stack — sticker at the top, the four tabs across the middle,
     then the girl large underneath. The frame is made a normal, tall block
     (position:relative so it is the containing block for everything inside,
     which is why the rail no longer resolves against the section and vanishes
     off the top). container-type stays, so cqw is still frame-width based. */
  #meanwhile{display:block;padding:0}
  .mw-frame{
    position:relative; left:auto; right:auto; top:auto; transform:none;
    width:100%; max-width:none;
    aspect-ratio:auto;
    min-height:calc(100svh - var(--mw-top));
    margin-top:var(--mw-top);
  }

  /* MEANWHILE sticker — front and centre, up top */
  .mw-lockup{left:50%; transform:translateX(-50%); top:5%; width:60%}

  /* the typed line centres under the sticker; the hover/click hint is dropped
     since there is no hover on touch */
  .mw-sub{
    left:0; right:auto; width:100%; top:12.5%;
    text-align:center; white-space:normal;
    font-size:clamp(14px, 4.4cqw, 19px);
  }
  .mw-hint{display:none}

  /* the tabs: a horizontal bar under the sticker, four even columns so every
     label sits centred beneath its own icon and nothing clips at the edge */
  .mw-rail{
    top:19%; bottom:auto;
    left:0; right:auto; width:100%;
    grid-auto-flow:column; grid-auto-columns:1fr;
    justify-items:center; gap:0;
    z-index:7;
  }
  .mw-tab{width:64px; height:64px}
  .mw-tab img{max-width:32px; max-height:32px}
  .mw-tab-label{font-size:15px; top:calc(100% + 4px)}

  /* the girl, large, anchoring the fold underneath the tabs. She centres on
     her own width instead of bleeding off the left edge on mobile. */
  .mw-girl{
    --gap:0px;
    left:6%; width:88%; top:36%;
  }

  /* the tab bar is pinned near the top for every panel, so the four content
     panels (cooking, art, podcast, sport) have to start below it or the
     labels sit on top of the photos. Shift each one down as a whole — a plain
     translate, so their internal composition is untouched — to clear the bar
     with room to spare. (The intro is excluded; it has its own stack above.) */
  .mw-panel:not([data-key="intro"]){transform:translateY(26%)}
}
@media (prefers-reduced-motion:reduce){
  .mw-girl{transition:none}
  .mw-ring path{transition:opacity .2s ease}
  .mw-caret{animation:none}
}

/* ===================== fourth fold: the sign-off =====================
   Unlike the three folds above it this one is not an artboard: it is a short
   piece of writing and five links, so it is set in real type at real sizes
   and allowed to reflow. Scaling a paragraph as a picture is what gives you
   8px body copy on a laptop and 30px on a television.

   One colour is doing the work of the whole design. In the dark theme it is
   the green the hero already speaks in; in the light theme the green would
   vanish against white, so it becomes the red the rest of the light theme
   uses -- and everything else stays exactly where it was. */
.ft{
  --ft-accent:var(--ink);
  --ft-line:rgba(255,255,255,.42);
  position:relative;
  background:var(--bg);
  color:var(--copy-ink);
  /* the bottom is deep on purpose: the clock is fixed 22px off the foot of
     the window and lands in this corner when the page is scrolled home */
  padding:clamp(72px,12vh,140px) clamp(24px,6vw,110px) clamp(96px,14vh,150px);
  display:grid;align-content:space-between;
  /* the sentence and the links are two separate thoughts, and the design
     leaves about a quarter of the fold empty between them */
  gap:clamp(56px,13vh,150px);
  min-height:min(82svh,720px);
  transition:background-color .45s ease,color .45s ease;
}
:root[data-theme="light"] .ft{
  --ft-accent:var(--red);
  --ft-line:rgba(46,57,140,.34);
}

.ft-line{
  font-family:var(--font-display);
  font-size:clamp(1.02rem,1.72vw,1.62rem);
  line-height:1.36;font-weight:700;letter-spacing:-.008em;
  color:var(--ft-accent);
  /* wide enough to hold the sentence on one line on a laptop, which is how
     it is drawn, and narrow enough that it breaks rather than running the
     width of a very wide window */
  max-width:64ch;
  transition:color .45s ease;
}
.ft-note{
  margin-top:1.05em;
  font-family:var(--font-ui);
  font-size:clamp(.8rem,1.02vw,.95rem);
  line-height:1.66;letter-spacing:-.004em;
  color:var(--copy-ink);
}
.ft-open{
  margin-top:2.6em;
  font-family:var(--font-display);
  font-size:clamp(.95rem,1.45vw,1.38rem);
  line-height:1.3;font-weight:700;letter-spacing:-.006em;
  color:var(--ft-accent);
  transition:color .45s ease;
}
.ft-roles{
  display:flex;flex-wrap:wrap;gap:.62em;
  margin-top:1.15em;list-style:none;
}
.ft-roles li{
  font-family:var(--font-ui);
  font-size:clamp(.78rem,.95vw,.9rem);line-height:1;letter-spacing:-.004em;
  padding:.82em 1.25em;
  border:1px solid var(--ft-line);border-radius:99px;
  color:var(--copy-ink);
  transition:border-color .45s ease,color .45s ease;
}

/* --- the five links --- */
.ft-links{list-style:none;display:grid;justify-items:start;gap:clamp(13px,1.7vh,20px)}
.ft-links a,
.ft-copy{
  position:relative;display:inline-block;
  font-family:var(--font-ui);
  font-size:clamp(.8rem,1.02vw,.95rem);line-height:1.2;
  font-weight:600;letter-spacing:-.006em;
  color:var(--copy-ink);text-decoration:none;
  padding-bottom:4px;
  /* a <button> centres its own label, which nothing else in this column
     does — on a narrow screen the copy line would wrap into a centred stack
     beside four left-aligned links */
  text-align:left;
  background:none;border:0;cursor:pointer;
  transition:color .3s ease;
}
/* the same underline that wipes in under the nav links, so the two lists
   behave like one another */
.ft-links a::after,
.ft-copy::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:1.5px;
  background:var(--ft-accent);
  transform:scaleX(0);transform-origin:0 50%;
  transition:transform .42s cubic-bezier(.3,.75,.25,1),background-color .45s ease;
}
.ft-links a:hover,.ft-links a:focus-visible,
.ft-copy:hover,.ft-copy:focus-visible{color:var(--ft-accent)}
.ft-links a:hover::after,.ft-links a:focus-visible::after,
.ft-copy:hover::after,.ft-copy:focus-visible::after{transform:scaleX(1)}
.ft-links a:focus-visible,.ft-copy:focus-visible{outline:none}

/* "copied" arrives beside the address rather than replacing it, so the line
   does not change width and shove the underline about while you read it */
.ft-said{
  margin-left:.7em;font-style:normal;font-weight:500;
  color:var(--ft-accent);
  opacity:0;transform:translateX(-4px);
  transition:opacity .2s ease,transform .3s cubic-bezier(.2,.9,.3,1);
}
.ft-copy.said .ft-said{opacity:1;transform:none}

/* the fold arrives once, from just below where it settles */
.ft-say,.ft-links{
  opacity:0;transform:translateY(14px);
  transition:opacity .9s ease,transform .9s cubic-bezier(.16,.78,.26,1);
}
.ft-links{transition-delay:.14s}
.ft.in .ft-say,.ft.in .ft-links{opacity:1;transform:none}

/* the live region that announces the copy: heard, never seen */
.sr-only{
  position:absolute;width:1px;height:1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;
}

@media (max-width:820px){
  .ft{min-height:0;gap:clamp(40px,7vh,64px)}
  .ft-line{max-width:none}
}
@media (prefers-reduced-motion:reduce){
  .ft-say,.ft-links{opacity:1!important;transform:none!important;transition:none!important}
  .ft-said{transition:opacity .12s ease}
}


/* ===================== the about page =====================
   Prose, like the sign-off above it and unlike the three artboard folds:
   real type at real sizes, allowed to reflow. Everything here is prefixed
   .ab- so it can share a stylesheet with the homepage without either page
   having to know the other exists.

   One page-wide gutter, set once, so the eyebrow, the title, the paragraphs
   and the CV dates all hang off the same line down the left edge. It is the
   same measurement the sign-off uses.                                      */
:root{
  --ab-gutter:clamp(24px,6vw,110px);
  /* The quiet type -- the eyebrow, the dates, the sub-labels. It cannot be
     --hint: that token is tuned for the clock, which is decoration, and it
     lands at 2.4:1 on the blue. Dates and job subtitles are content, so this
     is the lowest either theme can go and still clear 4.5:1. */
  --ab-mute:rgba(255,255,255,.72);
}
:root[data-theme="light"]{ --ab-mute:rgba(46,57,140,.72); }

/* the first thing a keyboard reaches, and the only thing that shows it */
.skip{
  position:fixed;top:8px;left:8px;z-index:200;
  transform:translateY(-160%);
  font-family:var(--font-ui);font-size:13px;font-weight:500;
  color:var(--bg);background:var(--ink);
  padding:10px 16px;border-radius:10px;text-decoration:none;
  transition:transform .2s ease;
}
.skip:focus{transform:none}

.ab-head,.ab-story,.ab-do,.ab-cv{
  background:var(--bg);
  color:var(--copy-ink);
  padding:0 var(--ab-gutter);
  transition:background-color .45s ease,color .45s ease;
}
/* the nav is fixed, so the first fold has to clear it on its own */
.ab-head{padding-top:clamp(132px,21vh,230px);padding-bottom:clamp(56px,9vh,110px)}
.ab-story{padding-top:clamp(56px,9vh,104px);padding-bottom:clamp(40px,6vh,72px)}
.ab-do{padding-top:clamp(40px,6vh,72px);padding-bottom:clamp(40px,6vh,72px)}
/* the sign-off starts immediately below, and it brings its own deep top pad */
.ab-cv{padding-top:clamp(40px,6vh,72px);padding-bottom:clamp(24px,4vh,48px)}

.ab-eyebrow{
  font-family:var(--font-ui);
  font-size:11px;font-weight:500;
  letter-spacing:.14em;text-transform:uppercase;
  color:var(--ab-mute);
  margin-bottom:clamp(14px,2.4vh,26px);
  transition:color .45s ease;
}
.ab-title{
  font-family:var(--font-display);
  font-size:clamp(1.6rem,4.1vw,3.3rem);
  line-height:1.13;font-weight:700;letter-spacing:-.021em;
  color:var(--ink);
  transition:color .45s ease;
}
.ab-lead{
  margin-top:clamp(20px,3.2vh,38px);
  font-family:var(--font-ui);
  font-size:clamp(.95rem,1.32vw,1.16rem);
  line-height:1.66;font-weight:400;letter-spacing:.002em;
  color:var(--copy-ink);
  max-width:58ch;
}

/* ---------- the board ----------
   Full-bleed and edge to edge: it is a wall, not an illustration. The ground
   is the image's own paper white, so the fold has no visible seam at either
   side however wide the window gets. */
.ab-building{
  background:#F5F5F5;
  padding:0 0 clamp(20px,3.4vh,40px);
}
.ab-fig{display:grid;justify-items:center}
/* the whole picture is the control — at page size the hand-lettering is
   texture rather than writing, and the only useful thing to offer is more of
   it */
.ab-zoom{
  display:block;width:100%;padding:0;border:0;background:none;
  cursor:zoom-in;position:relative;
  -webkit-appearance:none;appearance:none;
}
.ab-zoom img{display:block;width:100%;height:auto}
.ab-cue{
  position:absolute;right:clamp(14px,3vw,34px);bottom:clamp(14px,3vw,34px);
  font-family:var(--font-ui);font-style:normal;
  font-size:11px;font-weight:500;letter-spacing:.12em;text-transform:uppercase;
  color:#3A3733;background:rgba(255,255,255,.86);
  border:1px solid rgba(0,0,0,.10);
  padding:8px 14px;border-radius:99px;
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  opacity:0;transform:translateY(5px);
  transition:opacity .3s ease,transform .3s cubic-bezier(.16,.78,.26,1);
  pointer-events:none;
}
.ab-zoom:hover .ab-cue,
.ab-zoom:focus-visible .ab-cue{opacity:1;transform:none}
/* nothing hovers on a touch screen, so there the invitation is simply on */
@media (hover:none){ .ab-cue{opacity:1;transform:none} }
.ab-zoom:focus-visible{outline:2px solid #3A3733;outline-offset:-4px}
.ab-fig figcaption{
  margin-top:clamp(14px,2.4vh,26px);
  font-family:var(--font-ui);
  font-size:clamp(.78rem,.95vw,.9rem);letter-spacing:.004em;
  color:#6F6B62;text-align:center;
  padding:0 var(--ab-gutter);
}

/* ---------- the writing ---------- */
.ab-col{max-width:min(66ch,100%)}
.ab-story p,.ab-cv .ab-row p{
  font-family:var(--font-ui);
  font-size:clamp(.92rem,1.14vw,1.05rem);
  line-height:1.72;font-weight:400;letter-spacing:.003em;
  color:var(--copy-ink);
}
.ab-story p + p{margin-top:1.15em}
.ab-story strong{font-weight:600;color:var(--ink);transition:color .45s ease}

.ab-h2{
  font-family:var(--font-display);
  font-size:clamp(1.06rem,1.85vw,1.6rem);
  line-height:1.3;font-weight:700;letter-spacing:-.012em;
  color:var(--ink);
  margin-bottom:clamp(18px,3vh,32px);
  transition:color .45s ease;
}
/* a heading arriving in the middle of a column needs air above it that the
   first one does not */
.ab-h2-later{margin-top:clamp(48px,8vh,96px)}

/* the ten things, set as the same pills the sign-off uses for the three roles */
.ab-tags{
  list-style:none;display:flex;flex-wrap:wrap;
  gap:clamp(7px,.9vw,11px);
  max-width:64ch;
}
.ab-tags li{
  font-family:var(--font-ui);
  font-size:clamp(.76rem,.94vw,.88rem);line-height:1;
  font-weight:500;letter-spacing:.004em;
  color:var(--copy-ink);
  border:1px solid var(--ui-line);border-radius:99px;
  padding:9px 15px 10px;
  transition:color .45s ease,border-color .45s ease;
}
.ab-tools{
  margin-top:clamp(18px,2.6vh,28px);
  font-family:var(--font-ui);
  font-size:clamp(.8rem,1vw,.93rem);line-height:1.62;
  color:var(--ab-mute);
  max-width:64ch;
}
.ab-tools + .ab-tools{margin-top:.45em}

/* ---------- the CV ----------
   Wider than the prose measure on purpose: the dates hang in their own
   column off the same left line, and the rhythm of that column is most of
   what makes a list of jobs readable at a glance. */
.ab-cv .ab-col{max-width:min(86ch,100%)}
.ab-row{
  display:grid;
  grid-template-columns:11.5rem minmax(0,1fr);
  gap:clamp(14px,2.6vw,40px);
  padding:clamp(20px,3vh,30px) 0;
  border-top:1px solid var(--ui-line);
  transition:border-color .45s ease;
}
.ab-row:first-of-type{border-top:0;padding-top:0}
.ab-when{
  font-family:var(--font-ui);
  font-size:11.5px;font-weight:500;
  letter-spacing:.1em;text-transform:uppercase;
  color:var(--ab-mute);
  padding-top:.42em;         /* optically level with the cap height beside it */
  transition:color .45s ease;
}
.ab-row h3{
  font-family:var(--font-display);
  font-size:clamp(.98rem,1.3vw,1.14rem);
  line-height:1.35;font-weight:700;letter-spacing:-.008em;
  color:var(--ink);
  transition:color .45s ease;
}
.ab-where{
  margin-top:5px;
  font-family:var(--font-ui);
  font-size:clamp(.78rem,.94vw,.86rem);line-height:1.5;
  color:var(--ab-mute);
}
.ab-row .ab-where + p{margin-top:.9em}
.ab-link{
  display:inline-block;position:relative;
  margin-top:.85em;
  font-family:var(--font-ui);
  font-size:clamp(.78rem,.94vw,.88rem);line-height:1.2;
  font-weight:600;letter-spacing:-.004em;
  color:var(--ink);text-decoration:none;
  padding-bottom:3px;
  transition:color .45s ease;
}
.ab-link::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:1.5px;
  background:currentColor;
  transform:scaleX(0);transform-origin:0 50%;
  transition:transform .42s cubic-bezier(.3,.75,.25,1);
}
.ab-link:hover::after,
.ab-link:focus-visible::after{transform:scaleX(1)}
.ab-link:focus-visible{outline:none;text-decoration:underline}

/* ---------- the board, full size ----------
   Fit-to-window would be no larger than the page already shows it, so this
   opens the image well past the width of the viewport and lets the visitor
   move around inside it. That is the whole point of asking to look closer. */
.ab-lightbox{
  position:fixed;inset:0;z-index:150;
  background:rgba(9,12,44,.95);
  overflow:auto;overscroll-behavior:contain;
  -webkit-overflow-scrolling:touch;
  cursor:grab;
  opacity:0;transition:opacity .3s ease;
}
.ab-lightbox[hidden]{display:none}
.ab-lightbox.in{opacity:1}
.ab-lightbox.drag{cursor:grabbing}
.ab-lightbox img{
  display:block;
  /* wide enough that the hand-lettering is type again rather than texture:
     the smallest writing on the board is around 20px at the image's native
     2589, so anything under about 1700 puts it back under reading size */
  width:min(2589px,max(1700px,172vw));
  max-width:none;height:auto;
  /* margin:auto centres it in the scroll box on screens wide enough that it
     fits, and does nothing on the ones where it does not */
  margin:auto;
  user-select:none;-webkit-user-drag:none;
}
.ab-close{
  position:fixed;top:clamp(12px,2vw,22px);right:clamp(12px,2vw,22px);z-index:2;
  display:grid;place-items:center;
  width:42px;height:42px;padding:0;
  color:#fff;background:rgba(255,255,255,.12);
  border:1px solid rgba(255,255,255,.22);border-radius:99px;
  cursor:pointer;
  -webkit-appearance:none;appearance:none;
  transition:background-color .25s ease,transform .25s cubic-bezier(.3,1.4,.5,1);
}
.ab-close svg{width:19px;height:19px}
.ab-close:hover{background:rgba(255,255,255,.22);transform:scale(1.06)}
.ab-close:focus-visible{outline:2px solid #fff;outline-offset:3px}
/* the page underneath must not scroll while the board is open */
body.boarded{overflow:hidden}

/* ---------- back to the start ----------
   Bottom left, stacked above the clock in the same gutter, so the corner
   reads as one small cluster rather than two floating objects. It appears
   only once there is something to go back up to. */
.totop{
  position:fixed;left:clamp(20px,4vw,52px);bottom:52px;z-index:70;
  display:grid;place-items:center;
  width:34px;height:34px;padding:0;
  color:var(--ui-fg);background:var(--ui-bg);
  border:1px solid var(--ui-line);border-radius:99px;
  cursor:pointer;
  -webkit-appearance:none;appearance:none;
  opacity:0;transform:translateY(6px);pointer-events:none;
  transition:opacity .4s ease,transform .4s cubic-bezier(.16,.78,.26,1),
             color .45s ease,background-color .45s ease,border-color .45s ease;
}
.totop svg{width:16px;height:16px}
.totop.in{opacity:1;transform:none;pointer-events:auto}
.totop:hover{color:var(--ink);border-color:var(--ink)}
.totop:focus-visible{outline:2px solid var(--ink);outline-offset:3px}
/* over a cream fold it has to invert with the rest of the bottom chrome */
body.on-cream .totop{background:rgba(0,0,0,.05);color:#8C887E;border-color:rgba(0,0,0,.12)}
body.on-cream .totop:hover{color:var(--cream-ink);border-color:var(--cream-ink)}

@media (max-width:820px){
  .ab-row{grid-template-columns:1fr;gap:9px}
  .ab-when{padding-top:0}
  .ab-lead,.ab-tags,.ab-tools{max-width:none}
}
@media (max-width:560px){
  /* the clock drops to bottom:58px there, so the arrow steps up with it */
  .totop{bottom:100px}
}
@media (prefers-reduced-motion:reduce){
  .ab-cue,.ab-lightbox,.totop,.ab-close{transition:none}
  .ab-link::after{transition:none}
}

/* ===================== the case studies =====================
   A case study is a long read on a page of paper, and paper does not have a
   dark mode. The work fold on the homepage already settled this: the plates
   sit on their own ground whichever theme the site is in, because the
   project is the project. So everything from the masthead down to the card
   here is theme-independent, and the only fold that answers to the toggle is
   the sign-off at the bottom, which is shared with every other page.

   Every class is prefixed .cst- (case study) rather than .cs-, which is what
   the original stylesheet at assets/site.css calls its own version of these
   parts. The two systems run side by side while the studies are ported over,
   and a shared name between them would be a trap for whoever ports the next
   one.                                                                     */
.cst{
  /* Every colour below was sampled off the mockup rather than chosen, so the
     page is the mockup and not a reading of it. */
  --cst-paper:#FFFFFF;
  --cst-ink:#000000;          /* headings, labels, the bold lines           */
  --cst-body:#696969;         /* every paragraph on the page                */
  --cst-line:#E7E7E7;         /* card edges and the rules between options   */
  --cst-plate:#CFCFCF;        /* the grey the device shots are mounted on   */
  --cst-lime:#DFFF5E;
  --cst-red:#F13F36;
  --cst-green:#7BEE8A;
  --cst-blue:#0086FF;
  /* The shell is set so the content column lands on the 1208px the mockup
     measures at a 1440 viewport, gutter included. */
  --cst-shell:86.5rem;
  /* Söhne Breit is the display face across the site, including the case-study
     headings that were originally drawn in Circular. */
  --cst-display:'Test Sohne Breit',var(--font-display);
  /* A case study is a long read, so it is given more air at the edges than the
     rest of the site: the page gutter is widened past --ab-gutter to keep the
     imagery clear of the screen edge on a laptop without letting the margin
     eat the page on a phone. */
  --cst-gutter:clamp(30px,10.6vw,200px);
  background:var(--cst-paper);
  color:var(--cst-ink);
}
/* one gutter for the whole page */
.cst-shell{
  max-width:var(--cst-shell);
  margin-inline:auto;
  padding-inline:var(--cst-gutter);
}
/* The mockup holds its prose to a much shorter measure than its imagery: the
   folds that are only words sit inside about 800px while the plates, the
   drawing and the black band run the full shell. That difference is the page's
   rhythm, so it is a modifier rather than something the sections improvise. */
.cst-shell--text{max-width:calc(50rem + 2 * var(--cst-gutter))}
/* The folds are separated by air rather than by rules, so the padding is the
   only thing telling you one idea has ended and the next has started. It is
   set generously on purpose: a case study read at length wants the pauses. */
.cst-sec{padding-block:clamp(96px,17vh,210px)}
.cst-sec--tight{padding-block:clamp(60px,10.5vh,128px)}

/* ---------- type ----------
   Two families and nothing else. Circular sets the headings, the card labels
   and the buttons; the UI face sets every paragraph. The mockup never mixes
   them inside a line, so neither does this.
   Every size below was measured off the mockup at its own scale and written
   back as the size it works out to on a 1440 viewport, with a vw term so it
   travels down to narrow screens without redrawing the relationships. */
.cst-wordmark{
  font-family:var(--cst-display);
  font-size:clamp(1.35rem,2.08vw,1.875rem);
  font-weight:400;letter-spacing:-.022em;line-height:1;
  text-align:center;color:var(--cst-ink);
}
.cst-kicker{
  font-family:var(--cst-display);
  font-size:clamp(1.45rem,2.08vw,1.875rem);
  line-height:1.16;font-weight:500;letter-spacing:-.03em;
  color:var(--cst-ink);
}
.cst-h2{
  font-family:var(--cst-display);
  font-size:clamp(1.45rem,2.08vw,1.875rem);
  line-height:1.16;font-weight:500;letter-spacing:-.03em;
  color:var(--cst-ink);
}
/* the bold line that states the question, tight under the heading */
.cst-q{
  font-family:var(--font-ui);
  font-size:clamp(.94rem,1.11vw,1rem);
  line-height:1.55;font-weight:700;letter-spacing:-.002em;
  color:var(--cst-ink);
}
.cst-h3{
  font-family:var(--font-ui);
  font-size:clamp(.94rem,1.18vw,1.0625rem);
  line-height:1.5;font-weight:700;letter-spacing:-.002em;
  color:#1C1C1C;
}
.cst-p,.cst-lead{
  font-family:var(--font-ui);
  font-size:clamp(.875rem,1.04vw,.9375rem);
  line-height:1.6;letter-spacing:.001em;
  color:var(--cst-body);
  max-width:34em;
}
.cst-p + .cst-p{margin-top:1.55em}
/* the assumption runs as one block of prose in the mockup, with no gap
   between its paragraphs at all, so that case gets its own modifier */
.cst-flow .cst-p + .cst-p{margin-top:0}
.cst-p strong{font-weight:700;color:var(--cst-ink)}

/* ---------- the sticker dots ----------
   Flat circles of colour, dropped behind the first word of a heading and
   sized off that heading's own type size so they travel with it. They are
   the artwork from the mockup, not a redraw of it. */
.cst-mark{position:relative;isolation:isolate}
.cst-mark::before{
  content:"";position:absolute;z-index:-1;
  width:3.72em;height:3.72em;
  left:-1.92em;top:-1.5em;
  background:var(--dot) center/contain no-repeat;
}
.cst-mark--sun{--dot:url("../img/nirvana/nv-dot-sun.png")}
.cst-mark--coral{--dot:url("../img/nirvana/nv-dot-coral.png")}
/* the coral one sits higher than the yellow ones on the sheet: it clears the
   bold line under the heading instead of tinting it */
.cst-mark--coral::before{top:-2.35em}

/* ---------- the head ----------
   The claim on the left with the dot behind it, the facts about the project
   on a card beside it, the way the mockup lays them out. */
.cst-head{padding-top:clamp(118px,17vh,196px);padding-bottom:clamp(26px,4vh,52px)}
.cst-head .cst-wordmark{margin-bottom:clamp(64px,17vh,152px)}
.cst-head-grid{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);
  gap:clamp(24px,5.1vw,74px);
  align-items:start;
}
/* the card hangs lower than the claim in the mockup, and stays there */
.cst-head-grid > .cst-meta{margin-top:clamp(28px,12vh,108px)}
.cst-head .cst-lead{margin-top:.5em}

/* the buttons: one filled in the green the site speaks in, one outlined */
.cst-btns{display:flex;flex-wrap:wrap;gap:12px;margin-top:clamp(22px,3.4vh,38px)}
.cst-btn{
  display:inline-flex;align-items:center;gap:.5em;
  font-family:var(--cst-display);
  font-size:clamp(.9rem,1.06vw,1rem);font-weight:400;letter-spacing:-.012em;
  line-height:1;
  padding:14px 22px;border-radius:99px;
  color:var(--cst-ink);text-decoration:none;
  border:1.4px solid transparent;
  transition:transform .25s cubic-bezier(.3,1.4,.5,1),
             background-color .25s ease,border-color .25s ease;
}
.cst-btn--go{background:var(--cst-lime)}
.cst-btn--go:hover{transform:translateY(-2px);background:#D5FA46}
.cst-btn--line{border-color:#1C1C1C}
.cst-btn--line:hover{transform:translateY(-2px);background:#F4F4F4}
.cst-btn:focus-visible{outline:2px solid var(--cst-ink);outline-offset:3px}

/* the facts card, with the pen sticker pinned in its corner */
.cst-meta{
  background:#FFFFFF;
  border:1px solid var(--cst-line);
  border-radius:14px;
  padding:clamp(20px,2.4vw,30px);
  position:relative;
}
.cst-pen{
  position:absolute;top:clamp(14px,1.7vw,20px);right:clamp(14px,1.7vw,20px);
  width:clamp(38px,4.2vw,54px);height:auto;
}
.cst-meta dl{display:grid;gap:clamp(16px,2.2vh,24px)}
.cst-meta dt{
  font-family:var(--cst-display);
  font-size:clamp(.9rem,1.06vw,1rem);font-weight:700;letter-spacing:-.014em;
  color:var(--cst-ink);
  margin-bottom:.55em;
}
.cst-meta dd{
  font-family:var(--font-ui);
  font-size:clamp(.9rem,1.08vw,1rem);line-height:1.58;
  color:var(--cst-body);
}
.cst-meta dd span{display:block}

/* ---------- the device shots ----------
   Every one of these shots was exported with its own ground already on it,
   grey behind the devices or white behind the chat windows. So the frame
   adds no padding of its own: it rounds the corners and otherwise gets out
   of the way. Padding here would put a second, slightly different grey
   around the first one, which is exactly the seam it is meant to avoid. */
.cst-plateshot{
  background:var(--cst-plate);
  border-radius:clamp(12px,1.4vw,20px);
  overflow:hidden;
}
.cst-plateshot img{display:block;width:100%;height:auto}
/* the WhatsApp sheet arrived as one flat export on its own white, so it goes
   down as it is, with no frame around it at all */
.cst-shot{display:block;width:100%;height:auto}
.cst-cap{
  margin-top:clamp(10px,1.6vh,16px);
  font-family:var(--font-ui);
  font-size:clamp(.875rem,1.04vw,.9375rem);line-height:1.6;
  color:var(--cst-body);
  max-width:46em;
}

/* ---------- the problem, and what else could have answered it ----------
   Side by side on purpose: the objection and the answer to it should not be
   a scroll apart. */
.cst-two{
  display:grid;
  grid-template-columns:minmax(0,.85fr) minmax(0,1fr);
  gap:clamp(26px,4.6vw,66px);
  align-items:start;
}
.cst-two .cst-p,.cst-two .cst-q{max-width:none}
/* the right column starts lower than the left one, as it does on the sheet */
.cst-two > *:last-child{margin-top:clamp(40px,17.4vw,250px)}
.cst-opts{margin-top:clamp(24px,4vh,52px);display:grid;gap:clamp(24px,3.4vh,38px)}
.cst-opt + .cst-opt{border-top:1px solid var(--cst-line);padding-top:clamp(24px,3.4vh,38px)}
.cst-opt p{
  margin-top:.5em;
  font-family:var(--font-ui);
  font-size:clamp(.875rem,1.04vw,.9375rem);line-height:1.6;
  color:var(--cst-body);
}
/* the verdict is the point of the option, so it is a pill and not a sentence.
   It stays on one line the way it does on the sheet, even where that runs it
   past the column, and only wraps once the screen is too narrow to allow it. */
.cst-verdict{
  display:inline-flex;align-items:center;gap:.62em;
  margin-top:1.1em;
  font-family:var(--font-ui);
  font-size:clamp(.875rem,1.04vw,.9375rem);font-weight:400;line-height:1;
  padding:13px 20px;border-radius:99px;
  white-space:nowrap;
}
@media (max-width:640px){
  .cst-verdict{white-space:normal;line-height:1.35}
}
.cst-verdict::before{
  content:"";width:1.05em;height:1.05em;flex:none;
  background:currentColor;
  -webkit-mask:var(--gl) center/contain no-repeat;
          mask:var(--gl) center/contain no-repeat;
}
.cst-verdict--out{
  color:var(--cst-red);border:1.4px solid #1C1C1C;
  --gl:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2 2l8 8M10 2l-8 8' stroke='%23000' stroke-width='1.7' stroke-linecap='round' fill='none'/%3E%3C/svg%3E");
}
.cst-verdict--in{
  color:#1C1C1C;background:var(--cst-green);
  --gl:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M1.8 6.4l2.8 2.8L10.2 3.2' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E");
}

/* ---------- the loop ----------
   Drawn by hand on paper and kept that way. A tidy boxes-and-arrows diagram
   would claim more certainty than a sketch does, and a sketch is what this
   was. */
/* the drawing does not run the width of the fold in the mockup: it sits
   centred at about two thirds of it, so it is sized to the width the
   handwriting itself measures rather than stretched to the shell */
.cst-loop{display:block;width:min(100%,802px);height:auto;margin-inline:auto}

/* the three mechanisms, ruled off with one green line across the row */
.cst-three{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(20px,3.4vw,54px);
  border-top:3px solid var(--cst-lime);
  padding-top:clamp(18px,2.6vh,26px);
}
.cst-three p{margin-top:.5em;max-width:none}

/* ---------- what the testing indicated ----------
   The one fold on the page that is not paper. The numbers are projections,
   and putting them on black with the caveat attached is the only honest way
   to give them the size they deserve. */
.cst-figures{background:#000000;color:#fff;padding-block:clamp(52px,8vh,104px)}
.cst-figures h2{
  font-family:var(--font-ui);
  font-size:clamp(1.55rem,2.7vw,2.4375rem);
  font-weight:700;letter-spacing:-.022em;line-height:1.1;
  color:#fff;
}
.cst-stats{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(22px,3.4vw,54px);
  margin-top:clamp(30px,4.6vh,56px);
}
.cst-num{
  font-family:var(--font-ui);
  font-size:clamp(2.6rem,5.7vw,5.125rem);
  line-height:1;font-weight:700;letter-spacing:-.035em;
  color:var(--cst-blue);
}
.cst-stat p:last-child{
  margin-top:clamp(14px,2vh,22px);
  font-family:var(--font-ui);
  font-size:clamp(.8rem,.94vw,.84375rem);line-height:1.7;
  color:#E8E8E8;
}
.cst-note{
  margin-top:clamp(30px,4.6vh,58px);
  padding-left:clamp(14px,1.6vw,20px);
  border-left:2px solid var(--cst-blue);
  font-family:var(--font-ui);
  font-size:clamp(.7rem,.8vw,.71875rem);line-height:1.7;
  color:#CFCFCF;
  max-width:36em;
}
.cst-note b{color:#FFFFFF;font-weight:700;letter-spacing:0}

/* ---------- the close ----------
   Part one worked, and the reward for it was a second problem. The sticker
   and the suit are the mockup's own jokes about that, so they arrive as the
   artwork they are. */
.cst-dude{
  display:block;height:auto;
  width:clamp(120px,13vw,175px);
  margin-left:clamp(-136px,-9.5vw,-40px);
  margin-bottom:clamp(6px,1vh,12px);
}
.cst-close .cst-p{max-width:38em}
/* the send-off: the line, the button and the figure it is being said to */
.cst-off{
  display:grid;grid-template-columns:minmax(0,1fr) auto;
  gap:clamp(16px,2.6vw,40px);
  align-items:center;
  margin-top:clamp(56px,9vh,120px);
}
.cst-off-say{text-align:right}
.cst-off h2{margin-bottom:.5em}
.cst-off .cst-btns{justify-content:flex-end;margin-top:0}
.cst-suit{display:block;height:auto;width:clamp(150px,19vw,250px)}

/* ===================== part two: the additions =====================
   Nirvana 2.0 is the same paper as part one and reuses almost all of it. What
   it adds is a different kind of image. Part one's screens arrived already
   mounted on their grey; part two's arrive as a photograph and a device that
   have to be put together on the page, and as a prototype that is not an
   image at all. Everything below is that, and nothing else.                */

/* ---------- the photographic bands ----------
   Two folds on the sheet run edge to edge in a landscape rather than sitting
   inside the gutter. They are the only places the page leaves its margin, so
   the break has to be complete: no shell, no radius, no seam. */
.cst-band{position:relative;overflow:hidden;background:#7E9A86}
.cst-band img{display:block;width:100%;height:auto}
/* The first band is assembled here rather than exported flat, because the
   phone on it is the product and wants to stay sharp at every width while the
   water behind it can be cropped freely. So the landscape is given a height
   and told to cover, and the device is placed on top of it. */
.cst-band--set{height:clamp(300px,46vw,660px)}
.cst-band--set .cst-band-bg{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
}
/* two classes deep on purpose: .cst-band img above is width:100%, which
   out-specifies a single class and would blow the device up to the width of
   the landscape it is standing in */
.cst-band .cst-band-phone{
  position:absolute;left:50%;bottom:0;transform:translateX(-50%);
  width:auto;height:88%;
}

/* ---------- the two models, ruled off in their own colour ----------
   The library and the match are the same kind of list, and the only thing
   separating them is which one the page is arguing for. A red rule and a green
   one say that in less space than a sentence would. */
/* wider than the prose above it, narrower than the shell it sits in: the two
   lists are the argument's evidence, not its imagery */
.cst-models{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(24px,4.4vw,64px);
  margin-top:clamp(30px,5vh,64px);
  max-width:62rem;margin-inline:auto;
}
.cst-model{border-top:3px solid var(--cst-line);padding-top:clamp(14px,2vh,20px)}
.cst-model--out{border-top-color:var(--cst-red)}
.cst-model--in{border-top-color:var(--cst-green)}
.cst-model ul{list-style:none;margin:0;padding:0;margin-top:.9em;display:grid;gap:.7em}
.cst-model li{
  position:relative;padding-left:1.05em;
  font-family:var(--font-ui);
  font-size:clamp(.875rem,1.04vw,.9375rem);line-height:1.55;
  color:var(--cst-body);
}
.cst-model li::before{
  content:"";position:absolute;left:0;top:.62em;
  width:.34em;height:.34em;border-radius:50%;background:currentColor;
}

/* the small blue infinity that sits between the two columns on the sheet */
.cst-inf{
  display:block;height:auto;width:clamp(52px,6.4vw,92px);
  margin-inline:auto;
}

/* ---------- the engine, and the hand it is reasoning about ----------
   The explanation is prose and the mudra beside it is a photograph with
   handwriting on it. Neither is a caption for the other, so they sit as two
   columns rather than as a figure. */
.cst-aside{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.72fr);
  gap:clamp(24px,4.4vw,60px);
  align-items:center;
}
.cst-aside img{display:block;width:100%;height:auto}
/* the engine diagram was drawn wide and reads at its own size, so it runs the
   whole shell rather than the prose measure */
.cst-diagram{display:block;width:100%;height:auto}

/* ---------- the decisions, next to the thing they produced ----------
   The three calls on the left, the prototype they add up to on the right. The
   argument and the evidence for it stay on one screen, and the prototype holds
   its place while the decisions scroll past it. */
.cst-dec{
  display:grid;grid-template-columns:minmax(0,.86fr) minmax(0,1fr);
  gap:clamp(28px,5.2vw,76px);
  align-items:start;
}
/* the thin lilac rule the mockup runs above this heading, and only this one */
.cst-ruled{border-top:3px solid #CFC6E0;padding-top:clamp(14px,2vh,20px)}
.cst-proto{position:sticky;top:clamp(88px,11vh,116px)}
/* The prototype draws its own device frame, so this adds none: it is a window
   of the right proportion and nothing more. A second frame around the first
   read as two stacked phones. 410 x 920 is its natural size -- the smallest box
   the prototype renders its 390 x 844 device in at full scale, padding included.

   It is tempting to size this off the viewport height so the whole phone lands
   inside one fold, and that was tried. It does not work. The prototype scales
   its frame to fit but does NOT reflow its internals -- padding, chip sizes and
   most of its type are fixed pixels -- so squeezing the frame much below its
   drawn size crushes the screens inside it. Frame integrity wins over fitting
   the fold, so the stage stays width-first and only comes down a little from
   the natural 410: enough to lighten the column, not enough to compromise
   anything the prototype draws. */
.cst-proto-stage{
  width:100%;max-width:372px;
  aspect-ratio:410 / 920;
  margin-inline:auto;
  border:1px solid var(--cst-line);border-radius:clamp(12px,1.4vw,20px);
  overflow:hidden;background:#FBFBFD;
}
.cst-proto-stage iframe{display:block;width:100%;height:100%;border:0}
.cst-proto-note{
  margin-top:clamp(10px,1.6vh,16px);
  font-family:var(--font-ui);
  font-size:clamp(.8rem,.94vw,.84375rem);line-height:1.6;
  color:var(--cst-body);text-align:center;
}
.cst-proto-note a{color:var(--cst-ink);text-underline-offset:3px}

/* the honesty note, on paper rather than on the black band: part two has a
   working prototype and no cohort behind it, and that is worth saying plainly
   instead of dressing it up as a result */
.cst-caveat{
  margin-top:clamp(26px,4vh,48px);
  padding-left:clamp(14px,1.6vw,20px);
  border-left:2px solid var(--cst-blue);
  font-family:var(--font-ui);
  font-size:clamp(.75rem,.86vw,.78125rem);line-height:1.7;
  color:#7A7A7A;max-width:38em;
}
.cst-caveat b{color:var(--cst-ink);font-weight:700}

/* ---------- the last fold ----------
   The page closes by asking you to do the thing it has spent the whole scroll
   describing. It is centred, it is one gesture and one instruction, and there
   is nothing to click. */
.cst-breath{text-align:center}
/* the tilt is the mockup's: the sculpture was shot square and set down on the
   sheet at an angle, which is what stops it reading as a product photograph */
.cst-breath-hand{
  display:block;height:auto;width:clamp(240px,42vw,560px);
  margin-inline:auto;
  transform:rotate(-5deg);
}
.cst-breath .cst-inf{margin-top:clamp(-10px,-.8vw,0px)}
.cst-breath-note{
  margin-top:clamp(18px,2.6vh,30px);
  margin-inline:auto;
  font-family:var(--font-ui);
  font-size:clamp(.8rem,.94vw,.84375rem);line-height:1.75;
  color:var(--cst-body);max-width:42em;
}

@media (max-width:900px){
  .cst-models,.cst-aside,.cst-dec{grid-template-columns:minmax(0,1fr)}
  .cst-aside img{max-width:420px;margin-inline:auto}
  /* sticky needs a column taller than the thing stuck inside it, and once the
     grid is one column there is no such column left */
  .cst-proto{position:static}
  .cst-band--set{height:clamp(260px,58vw,420px)}
  .cst-head-grid,.cst-two{grid-template-columns:minmax(0,1fr)}
  .cst-head-grid > .cst-meta,.cst-two > *:last-child{margin-top:0}
  .cst-three{grid-template-columns:minmax(0,1fr);gap:clamp(20px,3vh,28px)}
  .cst-stats{grid-template-columns:minmax(0,1fr);gap:clamp(22px,3vh,32px)}
  .cst-p,.cst-lead,.cst-two .cst-p,.cst-two .cst-q{max-width:none}
  .cst-off{grid-template-columns:minmax(0,1fr) auto;gap:16px;margin-top:clamp(40px,6vh,72px)}
}
@media (max-width:560px){
  /* the dots hang off the left of their heading, which the gutter can take on
     a desktop and cannot on a phone, so they pull in rather than get cropped */
  .cst-mark::before,.cst-mark--coral::before{left:-1.05em}
  .cst-off{grid-template-columns:minmax(0,1fr)}
  .cst-off-say{text-align:left}
  .cst-off .cst-btns{justify-content:flex-start}
  .cst-suit{margin-left:auto}
}
@media (prefers-reduced-motion:reduce){
  .cst-btn{transition:none}
}
