/* ============================================================
   v4. 2026-10-02.
   Dirty Trip's full-bleed stage, rebuilt on the design guide
   (FOUNDATION.md), set like an edgier fashion magazine.

   type, one job each:
   - Bodoni Moda: the Didone of Vogue and Harper's Bazaar, drawn
     with optical sizes so its hairlines hold at display size.
     the hero line, headings, the pull quote, the form's questions.
   - Archivo: a grotesk with a width axis. body copy at normal
     width; eyebrows, the name and details stretched wide, the
     tension between a high-contrast serif and a wide grotesk is
     the edge (the Document Journal / i-D move).

   spacing from the 8px steps: 8 16 24 32 48 64 96 128 192.
   contrast measured, WCAG 2.2 AA: body #c8c1b7 on #0d0d0e is
   11.6:1; control borders at .45 alpha are 3.6:1 (1.4.11 asks 3).
   ============================================================ */

:root{
  --ground:#0d0d0e;
  --paper:#ece7df;
  --dim:#c8c1b7;
  --line:rgba(236,231,223,.45);
  --hair:rgba(236,231,223,.14);
  --warn:#e9b07a;                       /* errors: warm, not alarm red. 9.9:1 */
  --serif:'Bodoni Moda', 'Didot', 'Bodoni 72', Georgia, serif;
  --sans:'Archivo', 'Helvetica Neue', system-ui, sans-serif;
  --pad:24px;
  --ease:cubic-bezier(.22,.61,.36,1);
  --ease-out:cubic-bezier(.16,1,.3,1);
}
@media (min-width:900px){ :root{--pad:64px} }
@media (min-width:1440px){ :root{--pad:96px} }

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%; scroll-behavior:smooth; overflow-x:clip}
body{
  margin:0; background:var(--ground); color:var(--paper);
  font-family:var(--sans); font-size:17px; line-height:28px; font-weight:400;
  -webkit-font-smoothing:antialiased; overflow-x:clip;
}
img{display:block; max-width:100%}
a{color:inherit}
.wrap{width:100%; max-width:calc(1760px + 2 * var(--pad)); margin-inline:auto; padding-inline:var(--pad)}

/* ---------- load: CSS only, so nothing waits on the script ---------- */
.veil{position:fixed; inset:0; z-index:99; background:var(--ground); pointer-events:none;
      animation:veil 700ms var(--ease) forwards}
@keyframes veil{to{opacity:0; visibility:hidden}}

/* ---------- type ---------- */
.eyebrow{
  margin:0; font-family:var(--sans); font-stretch:125%; font-weight:500;
  font-size:11px; line-height:16px; letter-spacing:.32em; text-transform:uppercase;
}
.h2{
  margin:0; font-family:var(--serif); font-weight:400; font-optical-sizing:auto;
  font-size:clamp(36px,4vw,64px); line-height:1.05; letter-spacing:-.02em;
}
.body{margin:0; color:var(--dim); max-width:34em; text-wrap:pretty}
.caption{margin:0; font-size:13px; line-height:20px; color:var(--dim)}
.caption__title{color:var(--paper)}
.caption__line{display:block}

/* ---------- top bar: a fade from the top edge (v1's, kept) ---------- */
.top{
  position:fixed; inset:0 0 auto; z-index:20; pointer-events:none;
  display:flex; justify-content:space-between; align-items:baseline;
  padding:24px var(--pad) 0;
}
@media (min-width:900px){ .top{padding-top:32px} }
.top::before{
  content:""; position:absolute; inset:0 0 auto; height:calc(100% + 72px); z-index:-1;
  background:linear-gradient(to bottom, rgba(13,13,14,.72), rgba(13,13,14,.4) 45%, rgba(13,13,14,0));
}
.top__name{font-stretch:125%; font-weight:300; font-size:13px; letter-spacing:.28em; text-transform:uppercase}
.top__right{display:flex; align-items:baseline; gap:32px}
.top__link, .vswitch a{pointer-events:auto; position:relative; text-decoration:none; font-size:13px;
  border-bottom:1px solid transparent; padding-bottom:2px; transition:border-color .3s var(--ease)}
.top__link{font-stretch:112%; font-weight:500; letter-spacing:.06em}
.top__link::after, .vswitch a::after{content:""; position:absolute; inset:-14px -8px}
.top__link:hover, .vswitch a:hover{border-bottom-color:currentColor}
.vswitch{display:flex; gap:16px}
.vswitch a{color:var(--dim)}
.vswitch a[aria-current]{color:var(--paper); border-bottom-color:currentColor}
@media (max-width:899px){
  .vswitch{position:fixed; left:50%; transform:translateX(-50%); bottom:calc(16px + env(safe-area-inset-bottom));
    padding:10px 24px; background:rgba(13,13,14,.72); -webkit-backdrop-filter:blur(12px); backdrop-filter:blur(12px)}
}

/* ---------- the stage: full-bleed photographs behind the page ---------- */
/* overflow hidden: the photos zoom slightly, and on phones anything fixed that
   pokes past the edge widens the whole page (it laid out at 520px on a 390 screen) */
.stage{position:fixed; inset:0; z-index:0; background:var(--ground); overflow:hidden}
.stage__img{position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
  opacity:0; will-change:opacity, transform}
.stage__img--hero{opacity:1; object-position:70% 50%}
.stage__shade{position:absolute; inset:0;
  background:linear-gradient(to bottom, rgba(13,13,14,.35) 0%, rgba(13,13,14,0) 30%,
    rgba(13,13,14,0) 50%, rgba(13,13,14,.72) 100%)}
main{position:relative; z-index:1}

/* full-bleed sections are see-through onto the stage */
.beat{position:relative; min-height:130svh; display:flex; align-items:center}
.beat--hero{min-height:100svh; align-items:flex-end}

/* copy over a photograph: no box. a soft dark bloom behind the words */
.over{position:relative; max-width:34rem; display:flex; flex-direction:column}
.over > * + *{margin-top:16px}
.over > .eyebrow + *{margin-top:16px}
.over > .caption{margin-top:32px}
/* ---------- contrast over photographs, 2026-10-02 ----------
   measured, not assumed: text was hidden, the photo behind it sampled, and the
   light end (95th percentile) of those pixels compared with the text color.
   heroes were failing (as low as 1.7:1). a gradient behind the copy only: dark
   at the foot where the copy sits, gone by three quarters up, so the top of the
   photograph stays as shot. */
.beat--hero::before{
  content:""; position:absolute; inset:0; z-index:0; pointer-events:none;
  /* halfway (Michael, 2026-10-03) */
  background:linear-gradient(to top, rgba(10,10,11,.43) 0%, rgba(10,10,11,.37) 38%,
    rgba(10,10,11,.23) 56%, rgba(10,10,11,0) 76%);
}
.beat--hero .hero{position:relative; z-index:1}
/* behind copy over the room and the detail: a bloom that holds dark across the
   whole block (to 60% of its reach) before it fades */
.over::before{
  /* halfway between the first bloom and the full one (Michael, 2026-10-03) */
  content:""; position:absolute; inset:-32% -42%; z-index:-1; pointer-events:none;
  background:radial-gradient(closest-side, rgba(10,10,11,.84) 0%, rgba(10,10,11,.68) 50%,
    rgba(10,10,11,.63) 60%, rgba(10,10,11,.38) 80%, rgba(10,10,11,0) 100%);
}
.over .body{color:var(--paper)}
.over--right{margin-left:auto}

/* ---------- hero: the whole line at one size ---------- */
.hero{padding-bottom:96px}
.hero__line{
  margin:0; max-width:15.5em; font-family:var(--serif); font-weight:400; font-optical-sizing:auto;
  font-size:clamp(34px,4.6vw,84px); line-height:1.08; letter-spacing:-.018em; text-wrap:pretty;
}
.hero__line em{font-style:italic}
.hero__place{margin-top:32px}
@media (max-width:899px){ .hero{padding-bottom:96px} }

/* ---------- break-outs sit on the ground, over the stage ---------- */
.ground{position:relative; z-index:2; background:var(--ground)}

/* the weave: a portrait of the edge, the pull quote beside it */
.weave{padding-block:192px}
.weave__grid{display:grid; grid-template-columns:repeat(12,minmax(0,1fr)); column-gap:32px; align-items:center}
.weave__fig{grid-column:1 / span 5; margin:0; aspect-ratio:2 / 3; overflow:hidden}
.weave__img{width:100%; height:100%; object-fit:cover; object-position:30% 50%}
.pullquote{
  grid-column:7 / span 6; margin:0; font-family:var(--serif); font-style:italic; font-weight:400;
  font-optical-sizing:auto; font-size:clamp(28px,3.2vw,52px); line-height:1.16; letter-spacing:-.012em;
  text-wrap:pretty;
}
@media (max-width:899px){
  .weave{padding-block:128px}
  .weave__grid{grid-template-columns:1fr; row-gap:48px}
  .weave__fig, .pullquote{grid-column:1}
  .weave__fig{width:72%}
}

/* on process: the gallery flows sideways while the page scrolls down */
.flow{height:300svh}
.flow__pin{position:sticky; top:0; height:100svh; overflow:hidden; display:flex; align-items:center}
.flow__track{display:flex; align-items:center; gap:96px; padding-inline:var(--pad); will-change:transform}
.flow__copy{flex:none; width:min(26rem, 78vw); display:flex; flex-direction:column; gap:16px}
.flow__item{flex:none; margin:0; aspect-ratio:3 / 2; overflow:hidden; will-change:transform}
.flow__item img{width:100%; height:100%; object-fit:cover}
.flow__item--raw{height:52svh}
.flow__item--palette{height:72svh}
.flow__note{display:none}
.flow__progress{position:absolute; left:var(--pad); right:var(--pad); bottom:48px; height:1px; background:var(--hair)}
.flow__progress span{position:absolute; inset:0 auto 0 0; width:0; background:var(--paper)}
@media (max-width:899px){
  .flow__track{gap:48px}
  .flow__item--raw{height:auto; width:78vw}
  .flow__item--palette{height:auto; width:88vw}
}

/* ---------- the inquiry: one full screen, footer at its foot ---------- */
.inquire{min-height:100svh; display:flex; flex-direction:column; padding-top:128px}
.inquire__grid{display:grid; grid-template-columns:repeat(12,minmax(0,1fr)); column-gap:32px; align-items:start; flex:1}
.inquire__intro{grid-column:1 / span 5; display:flex; flex-direction:column; gap:16px}
.inquire__intro .eyebrow + .h2{margin-top:0}
.inq{grid-column:7 / span 6; position:relative}
@media (max-width:899px){
  .inquire{padding-top:96px}
  .inquire__grid{grid-template-columns:1fr; row-gap:48px}
  .inquire__intro, .inq{grid-column:1}
}

/* the sentence: answers as words you can tap to change.
   its space is reserved so the questions below never move. */
.inq__sentence{
  margin:0 0 24px; min-height:56px; font-size:17px; line-height:28px; color:var(--dim);
}
@media (max-width:899px){ .inq__sentence{min-height:84px} }
.inq__sentence button{
  font:inherit; color:var(--paper); background:none; border:0; padding:0; cursor:pointer;
  text-decoration:underline; text-decoration-color:var(--line); text-underline-offset:5px;
  text-decoration-thickness:1px; transition:text-decoration-color .3s var(--ease);
}
.inq__sentence button:hover{text-decoration-color:var(--paper)}
.inq__sentence button:focus-visible{outline:2px solid var(--paper); outline-offset:3px}
.inq__sentence .w{opacity:0; animation:word .5s var(--ease-out) forwards}
@keyframes word{from{opacity:0; transform:translateY(4px)} to{opacity:1; transform:none}}

/* progress: Goal-Gradient. a hairline that fills, and the count */
.inq__progress{display:flex; align-items:center; gap:16px; margin-bottom:48px}
.inq__bar{position:relative; flex:1; height:1px; background:var(--hair)}
.inq__fill{position:absolute; inset:0 auto 0 0; width:0; background:var(--paper); transition:width .6s var(--ease-out)}
.inq__count{font-size:12px; line-height:16px; font-stretch:112%; letter-spacing:.08em; color:var(--dim); font-variant-numeric:tabular-nums}

/* steps: all stacked in one cell, so the box is always as tall as the
   tallest step and nothing jumps when they cross-fade */
.inq__steps{display:grid}
.step{grid-area:1 / 1; border:0; margin:0; padding:0; min-width:0;
  opacity:0; visibility:hidden; transform:translateY(8px);
  transition:opacity .32s var(--ease), transform .32s var(--ease), visibility 0s .32s}
.step.is-on{opacity:1; visibility:visible; transform:none; transition:opacity .42s var(--ease) .08s, transform .42s var(--ease) .08s}
.step__q{float:left; width:100%; padding:0; margin:0 0 32px;
  font-family:var(--serif); font-weight:400; font-optical-sizing:auto; font-size:clamp(28px,2.6vw,40px); line-height:1.1; letter-spacing:-.015em}
.step > :not(legend){clear:both}

/* numbered choice cards: large targets, the number is also the key to press */
.opts{display:grid; gap:12px}
.opt{position:relative; display:grid; grid-template-columns:28px 1fr 18px; align-items:center; gap:16px;
  min-height:64px; padding:16px 20px; border:1px solid var(--line); cursor:pointer;
  transition:background-color .24s var(--ease), border-color .24s var(--ease), color .24s var(--ease)}
.opt input{position:absolute; inset:0; opacity:0; margin:0; cursor:pointer}
.opt__n{display:grid; place-items:center; width:28px; height:28px; border:1px solid var(--line);
  font-size:12px; font-stretch:112%; font-variant-numeric:tabular-nums; transition:border-color .24s var(--ease)}
.opt__t{font-size:17px; line-height:24px}
.opt__dot{width:18px; height:18px; border:1px solid var(--line); border-radius:50%; position:relative; transition:border-color .24s var(--ease)}
.opt__dot::after{content:""; position:absolute; inset:4px; border-radius:50%; background:var(--ground); transform:scale(0); transition:transform .24s var(--ease-out)}
.opt:hover{border-color:var(--paper)}
.opt:has(input:focus-visible){outline:2px solid var(--paper); outline-offset:3px}
.opt:has(input:checked){background:var(--paper); border-color:var(--paper); color:var(--ground)}
.opt:has(input:checked) .opt__n, .opt:has(input:checked) .opt__dot{border-color:var(--ground)}
.opt:has(input:checked) .opt__dot::after{transform:scale(1)}

/* fields: label above (fastest to complete, per eye-tracking studies),
   a reserved line for the message so an error never pushes the next field */
.avail__note{margin-bottom:24px}
.field{display:block}
.field + .field, .avail + .field{margin-top:8px}
.field__label{display:flex; justify-content:space-between; font-size:13px; line-height:20px; font-weight:500;
  font-stretch:112%; letter-spacing:.04em}
.field__opt{font-weight:400; color:var(--dim); letter-spacing:.02em}
.field__box{position:relative; margin-top:8px}
.field input, .field textarea{
  width:100%; background:transparent; color:var(--paper); border:0; border-bottom:1px solid var(--line);
  border-radius:0; font:inherit; font-size:18px; line-height:28px; padding:8px 40px 8px 0;
  transition:border-color .24s var(--ease), box-shadow .24s var(--ease);
}
.field textarea{resize:vertical; min-height:72px; padding-right:0}
.field input:focus, .field textarea:focus{outline:0; border-bottom-color:var(--paper); box-shadow:0 1px 0 0 var(--paper)}
.field__msg, .field__help{margin:8px 0 0; font-size:13px; line-height:20px}
.field__msg{min-height:20px; color:var(--paper); display:flex; gap:8px; align-items:baseline;
  opacity:0; transform:translateY(-4px); transition:opacity .28s var(--ease), transform .28s var(--ease)}
.field__msg::before{content:""; flex:none; width:6px; height:6px; border-radius:50%; background:var(--warn); transform:translateY(-1px)}
.field__help{color:var(--dim); margin-bottom:24px}
.field.is-error input{border-bottom-color:var(--warn); box-shadow:0 1px 0 0 var(--warn)}
.field.is-error .field__msg{opacity:1; transform:none}

/* the feather: Adam collects them. it draws itself where a checkmark would be */
.feather{position:absolute; right:0; bottom:10px; width:24px; height:24px; fill:none; stroke:var(--paper);
  stroke-width:1.2; stroke-linecap:round; stroke-linejoin:round; opacity:0; pointer-events:none}
.feather path{stroke-dasharray:70; stroke-dashoffset:70}
.field.is-good .feather{opacity:1}
.field.is-good .feather path{stroke-dashoffset:0; transition:stroke-dashoffset 1.1s var(--ease-out)}
.field.is-good .feather .feather__shaft{transition-delay:.25s}

.hp{position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden}

/* send: the one solid control on the page */
.send{margin-top:24px}
.send__btn{position:relative; overflow:hidden; display:inline-flex; align-items:center; justify-content:center;
  min-width:220px; min-height:56px; padding:0 32px; border:0; background:var(--paper); color:var(--ground);
  font:inherit; font-size:14px; font-weight:600; font-stretch:112%; letter-spacing:.12em; text-transform:uppercase;
  cursor:pointer; transition:background-color .24s var(--ease), transform .16s var(--ease)}
.send__btn:hover{background:#fff}
.send__btn:active{transform:scale(.985)}
.send__btn:focus-visible{outline:2px solid var(--paper); outline-offset:4px}
.send__line{position:absolute; left:0; bottom:0; height:3px; width:100%; background:var(--ground);
  transform:scaleX(0); transform-origin:0 50%}
.is-sending .send__btn{pointer-events:none}
.is-sending .send__line{animation:sending 1.4s var(--ease) forwards}
@keyframes sending{to{transform:scaleX(1)}}
.send__status{margin:16px 0 0; min-height:20px; font-size:13px; line-height:20px; color:var(--dim)}

/* back and start over: quiet, always in the same place */
.inq__nav{display:flex; justify-content:space-between; margin-top:32px}
.inq__back, .inq__reset{display:inline-flex; align-items:center; gap:8px; min-height:44px; padding:0;
  background:none; border:0; color:var(--dim); font:inherit; font-size:14px; cursor:pointer;
  transition:color .24s var(--ease), opacity .3s var(--ease)}
.inq__back:hover, .inq__reset:hover{color:var(--paper)}
.inq__back:focus-visible, .inq__reset:focus-visible{outline:2px solid var(--paper); outline-offset:4px}
.inq__back svg, .inq__reset svg{width:16px; height:16px; fill:none; stroke:currentColor; stroke-width:1.6; stroke-linecap:round; stroke-linejoin:round}
.inq__back[hidden], .inq__reset[hidden]{display:inline-flex; visibility:hidden; opacity:0}

/* sent: the same box, so nothing moves. the feather draws, then the note */
.inq__sentence, .inq__progress, .inq__form{transition:opacity .4s var(--ease)}
.sent{position:absolute; inset:0; display:flex; flex-direction:column; align-items:flex-start;
  opacity:0; visibility:hidden; transition:opacity .6s var(--ease) .3s, visibility 0s .9s}
.inq[data-state="sent"] .inq__sentence,
.inq[data-state="sent"] .inq__progress,
.inq[data-state="sent"] .inq__form{opacity:0; pointer-events:none}
.inq[data-state="sent"] .sent{opacity:1; visibility:visible; transition:opacity .6s var(--ease) .3s}
.sent__feather{width:72px; height:72px; fill:none; stroke:var(--paper); stroke-width:.7; stroke-linecap:round; stroke-linejoin:round; margin-bottom:32px}
.sent__feather path{stroke-dasharray:70; stroke-dashoffset:70}
.inq[data-state="sent"] .sent__feather path{stroke-dashoffset:0; transition:stroke-dashoffset 1.8s var(--ease-out) .5s}
.inq[data-state="sent"] .sent__feather .feather__shaft{transition-delay:.9s}
.sent__head{margin:0 0 16px; font-family:var(--serif); font-weight:400; font-size:clamp(28px,2.6vw,40px); line-height:1.1; letter-spacing:-.015em}
.sent__receipt{margin:24px 0 32px; padding-top:24px; border-top:1px solid var(--hair); font-size:15px; line-height:24px; color:var(--dim); max-width:34em}
.sent__receipt b{font-weight:400; color:var(--paper)}

/* footer, at the foot of the last screen */
.foot{display:flex; justify-content:space-between; flex-wrap:wrap; gap:16px 32px; padding-top:96px; padding-bottom:48px;
  font-size:13px; line-height:20px; color:var(--dim)}
.foot a{text-decoration:none; margin-left:24px}
.foot a:hover{color:var(--paper)}

/* reveal */
.reveal{opacity:0; transform:translateY(24px); transition:opacity 1.2s var(--ease-out), transform 1.2s var(--ease-out)}
.reveal.in{opacity:1; transform:none}

@media (prefers-reduced-motion:reduce){
  *{transition-duration:1ms !important; animation:none !important}
  .veil{display:none}
  .reveal{opacity:1; transform:none}
  .flow{height:auto}
  .flow__pin{position:static; height:auto; padding-block:128px}
  .flow__track{flex-direction:column; align-items:flex-start; transform:none !important}
  .flow__progress{display:none}
  .feather path, .sent__feather path{stroke-dashoffset:0}
}
.nobr{white-space:nowrap}

/* phones (Michael, 2026-10-02): the hero crop moves left to the sharp middle
   where the rows recede, so more and smaller beads show; the room centers on
   the piece */
@media (max-width:899px){
  .stage__img--hero{object-position:42% 50%}
  .stage__img--room{object-position:52% 45%}
}

/* ---------- phone hero type, 2026-10-03 (Michael: too small) ----------
   the headline is as large as it can be while "Weaving a world" still holds one
   line at 360px wide (measured per font), growing with wider phones to a cap.
   the line beneath and the location step up with it. */
@media (max-width:899px){
  /* the whole line is the headline here, so it stops short of the max: at 44px it broke
     into eight short lines on a phone */
  /* Bodoni runs large for its size: smaller and a step heavier on phones (Michael, 2026-10-03) */
  .hero__line{font-size:clamp(28px, calc((100vw - 48px) / 11), 34px); font-weight:500; line-height:1.22}
  .hero__place{font-size:13px; line-height:20px}
}

/* phones: the portrait hero is v2b's, IMG_3601 (Michael, 2026-10-03), set a little
   right of center to keep the red column in frame */
@media (max-width:899px){ .stage__img--hero{object-position:58% 50%} }

/* ============================================================
   review only (2026-10-03): three hero treatments, stacked. the
   stage photo stays fixed behind all three, so only the treatment
   behind the words changes. remove once one is chosen.
   ============================================================ */
.hx-tag{position:absolute; top:96px; left:var(--pad); z-index:3;
  font-size:11px; line-height:16px; letter-spacing:.12em; text-transform:uppercase; font-stretch:112%;
  padding:6px 10px; background:rgba(13,13,14,.78); color:var(--paper)}
.beat--alt{min-height:100svh; align-items:flex-end}
.hx{position:relative}
.hx > *{position:relative; z-index:2}

/* A, progressive blur: the bottom of the photo goes soft behind the words and
   sharpens going up, on top of the current scrim. the beads keep their color
   but lose the texture that fights Bodoni's hairlines. */
.hx-blur{position:absolute; left:0; right:0; bottom:0; height:62%; z-index:0; pointer-events:none;
  -webkit-backdrop-filter:blur(14px); backdrop-filter:blur(14px);
  -webkit-mask-image:linear-gradient(to top, #000 0%, #000 45%, rgba(0,0,0,.6) 70%, transparent 100%);
  mask-image:linear-gradient(to top, #000 0%, #000 45%, rgba(0,0,0,.6) 70%, transparent 100%)}

/* B, Candystore Dream (prototype v3.1, hero group, data-glass 3): one field of
   frost behind the words, an eased elliptical falloff, no edge. blur 18,
   saturate 1.18, white veil .05. phone reach 14vw / 10vw / 80px */
.hx--glass{--gsl:300px; --gsr:340px; --gsy:200px}
@media (max-width:899px){ .hx--glass{--gsl:14vw; --gsr:10vw; --gsy:80px} }
.hx--glass::before{content:""; position:absolute; z-index:1; pointer-events:none;
  top:calc(-1 * var(--gsy)); bottom:calc(-1 * var(--gsy)); left:calc(-1 * var(--gsl)); right:calc(-1 * var(--gsr));
  -webkit-backdrop-filter:blur(18px) saturate(1.18); backdrop-filter:blur(18px) saturate(1.18);
  background-color:rgba(255,255,255,.05);
  -webkit-mask-image:radial-gradient(ellipse 50% 50% at 50% 50%, #000 18%, rgba(0,0,0,.86) 44%, rgba(0,0,0,.48) 66%, rgba(0,0,0,.14) 84%, transparent 97%);
  mask-image:radial-gradient(ellipse 50% 50% at 50% 50%, #000 18%, rgba(0,0,0,.86) 44%, rgba(0,0,0,.48) 66%, rgba(0,0,0,.14) 84%, transparent 97%)}

/* C, Dirty Trip (prototype v3.2, the hero's .fx-cyl): the row banding, a 16px
   cycle of shade like the bead rows, inside an eased ellipse. band .93,
   spread 48% / 57%, fade 54% */
.hx--band{isolation:isolate; --spread-x:48%; --spread-y:57%; --band:.93; --fade:54%}
.hx--band::before{content:""; position:absolute; z-index:1; pointer-events:none;
  inset:calc(-1 * var(--spread-y)) calc(-1 * var(--spread-x));
  background-image:repeating-linear-gradient(to bottom,
    rgba(6,6,7,var(--band)) 0px, rgba(6,6,7,var(--band)) 3px,
    rgba(6,6,7,calc(var(--band) * .66)) 7px, rgba(6,6,7,calc(var(--band) * .91)) 12px,
    rgba(6,6,7,var(--band)) 16px);
  -webkit-mask-image:radial-gradient(ellipse var(--fade) calc(var(--fade) - 2%) at 50% 50%,
    #000 5%, rgba(0,0,0,.70) 30%, rgba(0,0,0,.30) 55%, rgba(0,0,0,.08) 75%, transparent 95%);
  mask-image:radial-gradient(ellipse var(--fade) calc(var(--fade) - 2%) at 50% 50%,
    #000 5%, rgba(0,0,0,.70) 30%, rgba(0,0,0,.30) 55%, rgba(0,0,0,.08) 75%, transparent 95%)}

/* the stage stays pinned but sized to the tallest screen height (lvh), so it cannot
   re-scale when iOS collapses its toolbars: that was the zoom jump (2026-10-03) */
.stage{inset:auto; top:0; left:0; right:0; height:100vh; height:100lvh}

/* the top fade ends as far below the name as the name sits below the top of the screen
   (Michael, 2026-10-03) */
.top::before{height:calc(100% + 24px);
  background:linear-gradient(to bottom, rgba(13,13,14,.86) 0%, rgba(13,13,14,.74) 55%,
    rgba(13,13,14,.3) 80%, rgba(13,13,14,0) 100%)}
@media (min-width:900px){ .top::before{height:calc(100% + 32px)} }

/* ---------- the top fade, clean (Michael, 2026-10-03) ----------
   one ease-in-out curve from the top of the screen to its end, no hold and no extra
   stops: the old version held full strength through the name, then dropped steeply,
   which read as a line under the name. it ends as far below the name as the name sits
   below the top of the screen (the bar's own top padding: 24 phones, 32 desktop). */
.top::before{height:calc(100% + 24px); -webkit-mask-image:none; mask-image:none;
  background:linear-gradient(to bottom, rgba(13,13,14,0.860) 0.0%, rgba(13,13,14,0.845) 8.3%, rgba(13,13,14,0.802) 16.7%, rgba(13,13,14,0.734) 25.0%, rgba(13,13,14,0.645) 33.3%, rgba(13,13,14,0.541) 41.7%, rgba(13,13,14,0.430) 50.0%, rgba(13,13,14,0.319) 58.3%, rgba(13,13,14,0.215) 66.7%, rgba(13,13,14,0.126) 75.0%, rgba(13,13,14,0.058) 83.3%, rgba(13,13,14,0.015) 91.7%, rgba(13,13,14,0.000) 100.0%)}
@media (min-width:900px){ .top::before{height:calc(100% + 33px)} }
