/* ---- MERGE PANEL: statement (left); distinction text then comparison table build on the right over scroll ---- */
.merge{position:relative;width:100vw;min-width:100vw;height:100%;overflow:hidden;
  --mpl:calc(var(--rail) + clamp(28px,3.5vw,64px));--mpr:clamp(56px,6vw,120px);--mg:clamp(64px,8vw,160px);}
.htrack > section.merge{padding:0;background:var(--paper-2);}
.merge__grid{height:100%;display:grid;grid-template-columns:1fr 1fr;align-items:stretch;
  gap:var(--mg);padding:clamp(64px,9vh,110px) var(--mpr) clamp(64px,9vh,110px) var(--mpl);}
/* LEFT, vertically centred against the right table (evenly above + below it) */
.merge__left{align-self:center;max-width:620px;}
/* RIGHT, vertically centred: the table is the feature, close + pull-quote below */
.merge__right{align-self:center;max-width:640px;display:flex;flex-direction:column;justify-content:center;}

.merge__headline{font-family:var(--serif);font-weight:700;font-size:clamp(2.1rem,3.8vw,3.8rem);
  line-height:1.04;letter-spacing:-0.02em;color:var(--ink);margin:0;max-width:14ch;}
.merge__sub{margin:clamp(14px,2vh,24px) 0 0;font-family:var(--serif);font-weight:500;
  font-size:clamp(1.25rem,1.9vw,1.7rem);line-height:1.28;letter-spacing:-0.01em;color:var(--ink-2);max-width:30ch;}
/* LEFT copy: the title block (headline + sub) shows on entry; each paragraph then
   reveals on its OWN scroll. Pure opacity+transform with the space reserved up front —
   no max-height animation, so there's zero reflow and the step reads smooth (the old
   max-height:0->62vh on a 3-paragraph block was the jank). Stages: 1=para1, 2=para2, 3=em. */
.merge__prose{margin-top:clamp(26px,3.6vh,46px);max-width:48ch;}
.merge__prose p{font-size:clamp(1.05rem,1.15vw,1.18rem);line-height:1.66;margin:0 0 var(--s3);color:var(--ink-2);}
.merge__prose .em{color:var(--ink);font-weight:600;}
.js .merge__prose p{opacity:0;transform:translateY(18px);
  transition:opacity .7s ease,transform .85s cubic-bezier(.16,1,.3,1);}
/* stages: 0 headline+sub, 1 the argument copy (all of it), 2 boxes appear on the right, 3 zoom to centre */
.merge[data-stage="1"] .merge__prose p,.merge[data-stage="2"] .merge__prose p,.merge[data-stage="3"] .merge__prose p,
.merge[data-stage="1"] .merge__prose .em,.merge[data-stage="2"] .merge__prose .em,.merge[data-stage="3"] .merge__prose .em{opacity:1;transform:none;}

/* STAGE 2: the comparison table appears on the right (stays through the stage-3 zoom) */
.merge__table{opacity:0;transform:translateY(16px);
  transition:opacity .9s ease,transform .9s cubic-bezier(.16,1,.3,1);}
.merge[data-stage="2"] .merge__table,.merge[data-stage="3"] .merge__table{opacity:1;transform:none;}
.vs{display:grid;grid-template-columns:1fr 1fr;gap:clamp(20px,2vw,40px);align-items:stretch;}
.vs__col{padding:var(--s3) var(--s3) var(--s4);border-top:2px solid var(--ink-3);
  opacity:0;transform:translateY(20px);transition:opacity .8s ease,transform .9s cubic-bezier(.16,1,.3,1);}
.merge[data-stage="2"] .vs__col,.merge[data-stage="3"] .vs__col{opacity:1;transform:none;}
.merge[data-stage="2"] .vs__col--a{transition-delay:.10s;}
.merge[data-stage="2"] .vs__col--b{transition-delay:.26s;}
.vs__label{display:block;font-family:var(--sans);font-size:11px;font-weight:700;letter-spacing:.18em;
  text-transform:uppercase;color:var(--ink-2);margin-bottom:var(--s2);}
.vs__statement{font-family:var(--serif);font-size:clamp(1.2rem,1.7vw,1.55rem);line-height:1.32;color:var(--ink-2);margin:0;}
.vs__statement em{font-style:normal;font-weight:700;color:var(--ink);}
/* domain side gets a FAINT box so the pair reads as two cards, not card-vs-floating-text */
.vs__col--a{background:rgba(23,19,16,.035);border-radius:8px;box-shadow:0 0 0 1px rgba(23,19,16,.07);}
/* highlight the ontological side as the key difference: SOLID (opaque) card + pulsing glow */
.vs__col--b{border-top-color:var(--accent);background:#EBDDC6;border-radius:8px;
  animation:vsPulse 2.8s ease-in-out infinite;}
@keyframes vsPulse{0%,100%{box-shadow:0 0 0 1px rgba(142,93,38,0.18),0 0 22px 0 rgba(142,93,38,0.16);}
  50%{box-shadow:0 0 0 1px rgba(142,93,38,0.30),0 0 40px 6px rgba(142,93,38,0.34);}}
@media(prefers-reduced-motion: reduce){.vs__col--b{animation:none;}}
.vs__col--b .vs__label{color:var(--ink-2);}
.vs__col--b .vs__statement{color:var(--ink);}
.vs__col--b .vs__statement em{color:var(--ember);}
/* close copy underneath the table */
.merge__close{margin-top:var(--s4);color:var(--ink-2);font-size:1.02rem;line-height:1.6;max-width:52ch;
  opacity:0;transition:opacity .8s ease .35s;}
.merge[data-stage="2"] .merge__close,.merge[data-stage="3"] .merge__close{opacity:1;}

html:not(.js) .merge__table,html:not(.js) .vs__col,
html:not(.js) .merge__close{opacity:1;transform:none;}

/* ===== Two beats (desktop htrack only): stage 2 = the comparison appears in its RIGHT
   column; stage 3 = it glides to dead-centre and scales up as the feature. The right
   column is absolutely positioned the WHOLE time and only its transform animates, so the
   move to centre is one smooth transition, never a static->absolute jump. ===== */
@media(min-width:901px){
  /* right column sits absolutely at its natural grid position, vertically centred */
  .merge__right{position:absolute;top:50%;max-width:none;margin:0;z-index:6;
    left:calc(50vw + var(--mpl)/2 - var(--mpr)/2 + var(--mg)/2);
    width:calc(50vw - var(--mpl)/2 - var(--mpr)/2 - var(--mg)/2);
    transform:translateY(-50%);transform-origin:center;
    transition:transform .85s cubic-bezier(.16,1,.3,1);}
  /* left copy fades + slides away as the comparison takes the screen */
  .merge__left{transition:opacity .55s ease,transform .7s cubic-bezier(.16,1,.3,1);}
  .merge[data-stage="3"] .merge__left{opacity:0;transform:translateX(-40px);pointer-events:none;}
  /* stage 3: translate the box's centre to viewport centre (exact, via the layout vars) + scale up */
  .merge[data-stage="3"] .merge__right{
    transform:translate(calc(-25vw - var(--mpl)/4 + var(--mpr)*3/4 - var(--mg)/4), -50%) scale(1.5);}
  .merge[data-stage="3"] .merge__close{text-align:center;margin-left:auto;margin-right:auto;}
}
@media(max-width:900px){
  .merge__grid{grid-template-columns:1fr;align-items:start;}
  .merge__left,.merge__right{max-width:none;}
  .merge__right{justify-content:flex-start;margin-top:var(--s4);}
  .vs{grid-template-columns:1fr;}
}

/* ---- CONTINUOUS COLOURFUL BACKGROUND LINES ---- */
.bgfx{position:fixed;inset:0;z-index:0;pointer-events:none;width:100vw;height:100vh;}
/* panels go transparent so the colourful line-field flows behind them; dark panels keep their fill */
.htrack > section{background:transparent;}
.htrack > section.merge{background:transparent;}
.htrack > section.cta,.htrack > footer{background:var(--dark);}
.hero__fx{display:none;}

/* ---- BIO: text left, full-height Filimon cutout on the right (delayed), stats full-width under ---- */
.bio{position:relative;width:100vw;min-width:100vw;height:100%;overflow:hidden;
  padding:clamp(56px,7vh,96px) clamp(48px,6vw,120px) 0 calc(var(--rail) + clamp(28px,3.5vw,64px));}
.bio.reveal{opacity:1;transform:none;}  /* section doesn't block-fade; children stagger instead */

.bio__text{position:relative;z-index:2;max-width:min(35vw,460px);padding-top:clamp(14px,4vh,52px);
  opacity:0;transform:translateY(20px);transition:opacity .9s ease,transform .9s cubic-bezier(.16,1,.3,1);}
/* FF-02 round 3: round 2 reserved a fixed padding-bottom on roomy viewports so the text could
   stay put while the stats band appeared at stage 1. Dropped - a fixed pixel reserve can't clear
   space for a footprint that moves with viewport WIDTH (the stats band's clamp() insets + label
   rewrap shift its top edge) or with the user's browser font-size setting (larger text overruns
   the reserve and .bio's overflow:hidden then clips the eyebrow/button). No fixed number survives
   both variables. Instead: one rule, all desktop widths - the text exits (fades + slides up) when
   the stats band reveals at stage 1, same idiom as .merge__left / .whofor__text going out for
   their next-stage feature. Nothing is left in that space, so nothing can be clipped or collide.
   Mobile (<=680px) is untouched - own choreography in styles2.css. */
.bio.in .bio__text{opacity:1;transform:none;transition-delay:.1s;}
/* stage-1 exit MUST come after .bio.in .bio__text above: same specificity (0,3,0), so source
   order decides the cascade and this needs to win once the stage flips to 1. Stepping back a
   stage restores it via the .bio.in rule above (stage attribute removed, no stage-1 rule left
   to fight it). */
@media(min-width:681px){
  .bio[data-stage="1"] .bio__text{opacity:0;transform:translateY(-24px);pointer-events:none;}
}
.bio__text .prose p{font-size:1.05rem;line-height:1.5;color:var(--ink-2);max-width:38ch;margin-bottom:var(--s2);}
.bio__text .prose{margin-top:var(--s2)!important;}
/* legibility over the centred photo — soft paper halo behind the bio copy */
.bio__text .eyebrow,.bio__text .prose p{text-shadow:0 1px 14px rgba(242,236,224,.9),0 0 4px rgba(242,236,224,.95);}

/* Filimon cutout — full height on the right, bottom-anchored, transparent; comes in after the text */
/* large desktop: near the original full size so his head sits at the top of the copy
   (smaller widths are handled by the max-width:1400px rule below to avoid overlap) */
/* Filimon cutout on the right (commanding arms-crossed pose, background removed).
   top + bottom reserve the stats row's space so it never collides with the numbers. */
.bio__img{position:absolute;right:clamp(40px,5vw,104px);top:clamp(28px,5vh,60px);bottom:clamp(176px,22vh,212px);left:auto;z-index:1;
  width:auto;height:auto;aspect-ratio:3/4;transform:scale(1.14);transform-origin:center top;   /* zoom into torso+head, anchored top so the head stays put; single transform keeps the bg image + overlaid videos + mask pixel-aligned */
  /* the element's own backdrop is the panel's paper tone, never white — so even a browser that
     fails to decode the webp's alpha (reported on the client's iPhone) blends into the page
     instead of flashing a white plate. PNG (real alpha, universally reliable) is offered via
     image-set() as a fallback source for any browser that can't handle the webp; browsers that
     support both keep fetching the smaller webp only (the png is never downloaded by them). */
  background-image:url("fil-bio.png?v=1");
  background-image:image-set(url("fil-bio.webp?v=4") type("image/webp"), url("fil-bio.png?v=1") type("image/png"));
  background-repeat:no-repeat;background-size:contain;background-position:center top;   /* head near the top, bigger */
  /* fade the lower torso into the cream starting around the waistline — raised from 82% so the
     hands and the waist-level fabric bulge on the viewer-left side are fully melted, never visible */
  -webkit-mask-image:linear-gradient(to bottom,#000 58%,rgba(0,0,0,0) 74%);
  mask-image:linear-gradient(to bottom,#000 58%,rgba(0,0,0,0) 74%);
  opacity:0;transition:opacity 1.1s ease .7s;}   /* opacity-only reveal; height is set by top/bottom */
.bio.in .bio__img{opacity:1;}
/* living portrait: alpha videos overlay the static cutout, same framing; parent's bottom-fade mask covers them.
   idle breathing/blink loop always plays; the look-down crossfades in when you scroll on past the section. */
.bio__live{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;object-position:center top;pointer-events:none;transition:opacity .28s ease;}
.bio__live--look{opacity:0;transition:opacity .22s ease;}
.bio__img.is-looking .bio__live--look{opacity:1;}
/* while the turn (profile) plays, hide the forward idle so it never ghosts a second head/ear behind it */
.bio__img.is-looking .bio__live:not(.bio__live--look){opacity:0;}
@media(prefers-reduced-motion:reduce){.bio__live{display:none;}}   /* reduced-motion keeps the static cutout */

/* stats span the bottom, clearing the rail on the left; appear on the NEXT scroll (stage 1).
   FF-01: decorative only, no interactive children, hence pointer-events:none so its bounding
   box never steals the "Read the full story" click, even while it's opacity:0 at stage 0. */
.bio__stats{position:absolute;left:calc(var(--rail) + clamp(28px,3.5vw,64px));right:clamp(48px,6vw,120px);bottom:clamp(40px,6vh,64px);z-index:2;
  display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s4);
  border-top:1px solid var(--hairline);padding-top:var(--s4);
  pointer-events:none;
  opacity:0;transform:translateY(16px);transition:opacity .9s ease,transform .9s cubic-bezier(.16,1,.3,1);}
.bio[data-stage="1"] .bio__stats{opacity:1;transform:none;}
.bio .stat .n{font-family:var(--serif);font-weight:900;font-size:clamp(3.4rem,7vw,6rem);color:var(--ink);line-height:.9;letter-spacing:-0.03em;font-variant-numeric:tabular-nums;}
.bio .stat .l{font-size:12px;letter-spacing:0.12em;text-transform:uppercase;color:var(--ink-2);margin-top:14px;}

html:not(.js) .bio__text,html:not(.js) .bio__stats{opacity:1;transform:none;}
html:not(.js) .bio__img{opacity:1;transform:scale(1.14);}   /* keep the zoom even with JS disabled */

/* ---- WHO FOR: headline + copy (left); on 2nd scroll the closing statement becomes the centre-piece ---- */
.whofor__in{width:100%;display:grid;grid-template-columns:1fr 1fr;align-items:center;gap:clamp(48px,6vw,120px);}
.whofor__text{max-width:620px;align-self:center;}
.whofor__pq{align-self:center;justify-self:end;max-width:15ch;margin:0;
  opacity:0;transform:translateX(48px);transition:opacity 1s ease,transform 1.05s cubic-bezier(.16,1,.3,1);}
.whofor[data-stage="1"] .whofor__pq,.whofor[data-stage="2"] .whofor__pq{opacity:1;transform:none;}
html:not(.js) .whofor__pq{opacity:1;transform:none;}
@media(max-width:900px){.whofor__in{grid-template-columns:1fr;}.whofor__pq{justify-self:start;margin-top:var(--s4);}}

/* ===== Two beats (desktop htrack only): stage 1 = the statement appears in its RIGHT
   column; stage 2 = it glides to dead-centre + scales up as the feature. Absolute the whole
   time so the move to centre is one smooth transition, never a jump. Mirrors the merge. ===== */
@media(min-width:901px){
  .whofor{position:relative;
    --wpl:calc(var(--rail) + clamp(28px,3.5vw,64px));--wpr:clamp(48px,6vw,110px);--wg:clamp(48px,6vw,120px);}
  .whofor__text{transition:opacity .55s ease, transform .7s cubic-bezier(.16,1,.3,1);}
  .whofor[data-stage="2"] .whofor__text{opacity:0;transform:translateX(-40px);pointer-events:none;}
  /* the statement sits absolutely in its right column, vertically centred */
  .whofor__pq{position:absolute;top:50%;justify-self:auto;margin:0;z-index:6;max-width:none;text-align:left;
    left:calc(50vw + var(--wpl)/2 - var(--wpr)/2 + var(--wg)/2);
    width:calc(50vw - var(--wpl)/2 - var(--wpr)/2 - var(--wg)/2);
    font-size:clamp(1.7rem,2.9vw,2.5rem);line-height:1.14;
    opacity:0;transform:translateY(-50%);transform-origin:center;
    transition:opacity .8s ease, transform .85s cubic-bezier(.16,1,.3,1);}
  .whofor[data-stage="1"] .whofor__pq{opacity:1;transform:translateY(-50%);}
  /* stage 2: translate the statement's centre to viewport centre (exact, via the layout vars) + scale up */
  .whofor[data-stage="2"] .whofor__pq{opacity:1;text-align:center;
    transform:translate(calc(-25vw - var(--wpl)/4 + var(--wpr)*3/4 - var(--wg)/4), -50%) scale(1.5);}
}

/* ============================================================
   SITE BACKGROUND — "Emergence" (bg.js).
   Fixed canvas behind everything; plain paper/dark sections go
   transparent so the marks show through. Gated on .sitebg (added
   by bg.js) so backgrounds stay solid if the script never runs.
   Sand + dark panels stay opaque and punctuate the motion.
   ============================================================ */
/* client: reduce the ambient ripple/dot field to ~1/4 of its prior visibility.
   Single lever on the canvas element itself so ripples + dots drop together,
   uniformly, site-wide (bg.js mounts this one #sitebg canvas on every page). */
#sitebg{position:fixed;inset:0;width:100%;height:100%;z-index:-1;pointer-events:none;opacity:.7;}
html.sitebg{background:var(--paper);}
html.sitebg-dark{background:var(--dark);}
html.sitebg body,
html.sitebg .page-body,
html.sitebg .page,
html.sitebg .htrack,
html.sitebg .psec,
html.sitebg .phero{background:transparent;}
/* Home htrack: the plain paper panels must stay transparent so the fixed
   canvas shows through — on desktop the base .htrack>section rule already
   does this, but the mobile stylesheet repaints them paper, so pin them
   here. Sand (.alt/.feature/.bio) and dark (.cta/footer) panels keep their
   fill and punctuate the motion, matching desktop. */
html.sitebg .htrack > section.hero--bold,
html.sitebg .htrack > section.merge,
html.sitebg .htrack > section.whofor{background:transparent;}

/* ============================================================
   MOBILE (<=680px) — CLEAN EDITORIAL BASELINE (ground 0).
   Vertical scroll, all content visible, no intro/scroll-reveal
   motion. Single source of truth for mobile; last in the file so
   it wins source-order ties. Desktop (outside) is untouched.
   ============================================================ */
