/* The scroll-driven descent. Loaded by the home page only.
   This is the one dark stretch of the site: night over the planet becoming dawn
   over Malaysia. Everything below it is the bone-and-olive daylight page. */

.hero{position:relative;height:900vh;z-index:1;background:#0B1006}
.stage{position:sticky;top:0;height:100vh;height:100svh;overflow:hidden;color:var(--bone)}
#herovid{position:absolute;inset:0;width:100%;height:100%;display:block;object-fit:cover;
  opacity:0;transition:opacity .8s var(--ease);will-change:transform;
  transform-origin:50% 50%}
/* tall screens show the whole 16:9 frame and scale it instead of cropping it.
   The mask feathers the film's own top and bottom edges into the page so the
   letterbox never shows as a hard line. */
.stage.fit-contain #herovid{object-fit:contain;
  -webkit-mask-image:linear-gradient(to bottom,transparent var(--mt,0px),
    #000 calc(var(--mt,0px) + 34px), #000 calc(var(--mb,100%) - 34px), transparent var(--mb,100%));
  mask-image:linear-gradient(to bottom,transparent var(--mt,0px),
    #000 calc(var(--mt,0px) + 34px), #000 calc(var(--mb,100%) - 34px), transparent var(--mb,100%))}
.stage.video-ready #herovid{opacity:1}
.poster{position:absolute;inset:0;background:#0B1006 center/cover no-repeat;
  transition:opacity .8s var(--ease)}
.stage.video-ready .poster{opacity:0}
/* an honest progress ring while the film streams in; the page is usable throughout */
.ring{position:absolute;left:50%;top:50%;width:48px;height:48px;margin:-24px 0 0 -24px;
  color:var(--sand);opacity:.85;transform:rotate(-90deg);pointer-events:none;
  transition:opacity .5s var(--ease)}
.stage.video-ready .ring,.stage.video-failed .ring{opacity:0}

/* the twelve deployed states, lit on top of the film once the country settles */
.marks{position:absolute;inset:0;pointer-events:none;opacity:0}
.marks i{position:absolute;width:0;height:0;display:block}
.marks i::before,.marks i::after{content:"";position:absolute;border-radius:50%;
  left:50%;top:50%;transform:translate(-50%,-50%) scale(.2);opacity:0;
  transition:opacity .7s var(--ease),transform .7s var(--ease)}
.marks i::before{width:34px;height:34px;
  background:radial-gradient(circle,rgba(255,246,226,.62),rgba(255,198,124,.22) 46%,transparent 74%)}
.marks i::after{width:6.5px;height:6.5px;background:#FFF8EC;
  box-shadow:0 0 7px 1.5px rgba(255,231,190,.75)}
.marks i.on::before,.marks i.on::after{opacity:1;transform:translate(-50%,-50%) scale(1)}
.marks i.on::before{animation:markpulse 3.4s var(--ease-soft) infinite;animation-delay:-1.1s}
@keyframes markpulse{0%,100%{transform:translate(-50%,-50%) scale(1);opacity:.9}
  50%{transform:translate(-50%,-50%) scale(1.18);opacity:.55}}
.scrim{position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(ellipse 128% 94% at 50% 46%,rgba(9,13,5,.18) 22%,rgba(9,13,5,.5) 62%,rgba(9,13,5,.84) 100%)}

.bands{position:absolute;inset:0;pointer-events:none}
.band{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;
  padding:clamp(100px,12vh,164px) var(--pad) clamp(70px,9vh,124px);
  opacity:0;text-shadow:var(--tshadow);color:var(--bone);
  /* load bearing: without a stacking context of its own, the z-index:-1 scrim below
     escapes to the back of the sticky stage and paints behind the film */
  isolation:isolate}
.band::before{content:"";position:absolute;inset:-4%;pointer-events:none;z-index:-1;
  opacity:calc(.25 + .75*var(--k,1));
  background:radial-gradient(ellipse 104% 86% at var(--sx,50%) var(--sy,50%),
    rgba(8,12,4,.80) 0%,rgba(8,12,4,.62) 46%,rgba(8,12,4,.26) 74%,rgba(8,12,4,0) 92%)}
.band .inner{max-width:min(1220px,100%);margin:0 auto;width:100%;text-align:center}
.band.top{justify-content:flex-start;padding-top:clamp(108px,15vh,196px)}
@media (max-height:700px){.band.top{padding-top:clamp(92px,11vh,132px)}}
.band h2,.band h1{font-family:var(--display);font-weight:400;color:var(--bone);
  font-size:clamp(2.5rem,7.4vw,6.2rem);letter-spacing:-.026em;line-height:1.02}
.band .sub{margin:clamp(18px,2.2vh,32px) auto 0;font-size:clamp(1.04rem,1.65vw,1.42rem);
  color:var(--bone);opacity:.92;max-width:38ch;font-weight:400}
.band .kick{font-family:var(--mono);font-size:clamp(10.5px,1.05vw,12px);letter-spacing:.28em;
  text-transform:uppercase;color:var(--sand);margin-bottom:clamp(18px,2.4vh,30px);
  display:flex;align-items:center;justify-content:center;gap:14px}
.band .kick::before{content:"";width:28px;height:1px;background:currentColor;opacity:.65}
/* the settle uses the real JPIoT lockup rather than typesetting the name,
   which never looked right in a serif */
.band .wordmark{margin:0;line-height:0}
.band .wordmark img{height:clamp(66px,10.5vw,152px);width:auto;margin:0 auto;
  opacity:var(--k,0);transform:translateY(calc((1 - var(--k,0))*28px));
  filter:drop-shadow(0 12px 34px rgba(9,13,5,.75))}
/* the scale line: prominent, but the supporting line never competes with it */
.band .stat{margin-top:clamp(22px,3.2vh,42px);display:flex;flex-direction:column;
  align-items:center;gap:clamp(8px,1.2vh,14px)}
.band .stat .big{font-family:var(--display);font-weight:400;line-height:1;
  font-size:clamp(2.4rem,5.4vw,4.2rem);letter-spacing:-.03em;color:var(--bone);
  font-variant-numeric:tabular-nums;display:flex;align-items:baseline;gap:clamp(9px,1vw,15px)}
.band .stat.lead .big{font-size:clamp(3.2rem,8.4vw,6.6rem)}
.band .stat .big em{font-style:normal;font-family:var(--mono);font-size:.2em;
  letter-spacing:.26em;text-transform:uppercase;color:var(--sand)}
.band .stat .supp{font-size:clamp(.98rem,1.5vw,1.24rem);color:var(--bone);opacity:.8;font-weight:400}
.band .proof{margin-top:clamp(20px,2.8vh,34px);font-family:var(--mono);
  font-size:clamp(11px,1.1vw,13px);letter-spacing:.26em;text-transform:uppercase;color:var(--sand)}

/* --- the scene three to four handover, staged inside one band ---
   --kb runs 0 to 1 across the band's whole span. The headline fades but keeps its
   space, which is the whole trick: the scale line underneath never shifts, so
   "250+ SITES / Across 12 states" reads as one continuous statement across both
   scenes rather than two that blink out and back. */
.band[data-sub]{
  --h-out:clamp(0,(var(--kb,0) - .26)/.16,1);   /* headline leaving   */
  --n-grow:clamp(0,(var(--kb,0) - .30)/.26,1);  /* number taking over */
  --p-in:clamp(0,(var(--kb,0) - .46)/.16,1)}    /* proof arriving     */
.band .hand-out{opacity:calc(1 - var(--h-out,0));
  transform:translateY(calc(var(--h-out,0) * -20px))}
.band .stat.grow{margin-top:clamp(16px,2.4vh,30px)}
.band .stat.grow .big{font-size:calc(clamp(2.4rem,5.4vw,4.2rem) + var(--n-grow,0) *
  (clamp(3.2rem,8.4vw,6.6rem) - clamp(2.4rem,5.4vw,4.2rem)))}
.band .hand-in{opacity:var(--p-in,0);
  transform:translateY(calc((1 - var(--p-in,0)) * 16px))}
.band .btnrow{justify-content:center;pointer-events:auto;margin-top:36px}
/* the stage is dark whatever the page tokens say, so the outline button states its own colours */
.band .btn-2,.stage .btn-2{border-color:rgba(245,239,229,.45);color:var(--bone)}
.band .btn-2:hover,.stage .btn-2:hover{border-color:var(--bone);color:#fff}

/* split-text primitives */
.w{display:inline-block;white-space:pre}
.c{display:inline-block;will-change:transform,opacity}
.e-scatter .c{--kc:clamp(0,(var(--k,0) - var(--th,0))*2.6,1);opacity:var(--kc);
  transform:translate(calc((1 - var(--kc))*var(--jx,0px)),calc((1 - var(--kc))*var(--jy,0px)))
            rotate(calc((1 - var(--kc))*var(--jr,0deg)))}
.e-snap .c{--kc:clamp(0,(var(--k,0) - var(--th,0))*3.4,1);opacity:var(--kc);
  transform:translateX(calc((1 - var(--kc))*var(--jx,0px)))}
.e-blur{position:relative}
.e-blur .soft{position:absolute;inset:0;filter:blur(12px);opacity:calc(1 - var(--k,0));pointer-events:none}
.e-blur .sharp{opacity:var(--k,0)}
.e-punch .w{--kc:clamp(0,(var(--k,0) - var(--th,0))*3,1);
  --ks:clamp(0,(var(--k,0) - var(--th,0) - var(--sd,.1))*var(--ss,3.2),1);
  opacity:var(--kc);
  transform:scale(calc(0.62 + (0.38 + var(--ov,.12))*var(--kc) - var(--ov,.12)*var(--ks)))}
.e-punch .w.em{--ov:0.24;--sd:0.16;--ss:2.6}
.e-drift .w{--kc:clamp(0,(var(--k,0) - var(--th,0))*2.8,1);opacity:var(--kc);
  transform:translateY(calc((1 - var(--kc))*-28px))}
.e-rise .w{--kc:clamp(0,(var(--k,0) - var(--th,0))*2.9,1);opacity:var(--kc);
  transform:translateY(calc((1 - var(--kc))*24px))}
.e-rise .stage2{opacity:var(--ks2,0);transform:translateY(calc((1 - var(--ks2,0))*16px))}
.e-rise .stage3{opacity:var(--ks3,0);transform:translateY(calc((1 - var(--ks3,0))*16px))}

/* readouts over the journey */
.hud{position:absolute;left:var(--pad);bottom:clamp(26px,4vh,48px);
  display:flex;align-items:baseline;gap:14px;pointer-events:none;
  opacity:var(--hudop,0);transition:opacity .6s var(--ease)}
.hud .n{font-family:var(--display);font-weight:400;
  font-size:clamp(2.6rem,5.6vw,4.8rem);letter-spacing:-.032em;line-height:1;
  font-variant-numeric:tabular-nums;color:var(--bone);text-shadow:var(--tshadow)}
.hud .plus{font-family:var(--display);font-weight:400;
  font-size:clamp(1.5rem,3vw,2.5rem);color:var(--accent);margin-left:-8px;text-shadow:var(--tshadow)}
.hud .lbl{font-family:var(--mono);font-size:11px;letter-spacing:.24em;text-transform:uppercase;
  color:var(--sand);text-shadow:var(--tshadow)}
.statechip{position:absolute;right:var(--pad);bottom:clamp(28px,4vh,50px);
  font-family:var(--mono);font-size:11.5px;letter-spacing:.18em;text-transform:uppercase;
  background:rgba(11,16,6,.62);border:1px solid rgba(174,190,140,.35);border-radius:11px;
  padding:10px 16px;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
  color:var(--bone);text-shadow:0 1px 3px rgba(9,13,5,.9);
  opacity:var(--hudop,0);transition:opacity .6s var(--ease);pointer-events:none}
@media (max-height:580px){.hud,.statechip{display:none}}
@media (max-width:820px){
  .marks i::before{width:22px;height:22px}
  .marks i::after{width:4.5px;height:4.5px;box-shadow:0 0 5px 1px rgba(255,231,190,.75)}
  .hud{left:var(--pad);bottom:clamp(18px,3vh,30px);gap:9px}
  .statechip{right:var(--pad);bottom:clamp(20px,3vh,32px);font-size:10px;padding:8px 11px}
}
/* the counter and the chip cannot share one narrow line, and the lit points
   already say how many states there are */
@media (max-width:620px){
  .statechip{display:none}
  .hud .lbl{font-size:10px;letter-spacing:.18em}
}

.cue{position:absolute;left:50%;bottom:20px;transform:translateX(-50%);
  opacity:var(--cueop,1);transition:opacity .6s var(--ease);
  font-family:var(--mono);font-size:10.5px;letter-spacing:.26em;text-transform:uppercase;
  color:rgba(245,239,229,.6);display:flex;flex-direction:column;align-items:center;gap:8px;
  animation:cuebob 3.6s var(--ease-soft) infinite;animation-delay:-1s}
.cue span{width:1px;height:28px;background:linear-gradient(to bottom,var(--sand),transparent)}
@keyframes cuebob{0%,100%{transform:translate(-50%,0)}50%{transform:translate(-50%,6px)}}
@keyframes cuepulse{0%,100%{opacity:.45}50%{opacity:1}}
.cue span{animation:cuepulse 3.6s var(--ease-soft) infinite;animation-delay:-1s}

/* the composed still, for reduced motion, no script, and very short screens */
.hero-static{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;
  padding:calc(var(--nav-h) + 40px) var(--pad) 84px;z-index:3;color:var(--bone);background:
  radial-gradient(88% 66% at 50% 114%,rgba(224,86,22,.3),transparent 62%),
  radial-gradient(74% 56% at 50% 2%,rgba(124,145,77,.28),transparent 64%),#101709}
.js .hero-static{display:none}
.hero-static .inner{max-width:var(--maxw);margin:0 auto;width:100%}
.hero-static .kicker{color:var(--sand)}
.hero-static h1{font-family:var(--display);font-weight:400;color:var(--bone);
  font-size:clamp(2.6rem,7vw,5.6rem);letter-spacing:-.026em;line-height:1.04}
.hero-static p{margin-top:24px;color:#CFD6BC;
  font-size:clamp(1.04rem,1.5vw,1.3rem);max-width:44ch}
.hero-static .btnrow{margin-top:40px}
.hero-static .shot{margin-top:clamp(30px,5vh,52px);border-radius:18px;overflow:hidden;
  border:1px solid rgba(174,190,140,.28);background:#0E1508}
.hero-static .shot img{width:100%;height:auto;display:block}
.hero-static .btn-2{border-color:rgba(245,239,229,.42);color:var(--bone)}
.hero-static .btn-2:hover{border-color:var(--bone)}

/* the static-hero gates, matching hero.js exactly */
@media (orientation:landscape) and (pointer:coarse) and (max-height:480px),
       (prefers-reduced-motion:reduce){
  .hero{height:auto!important}
  .stage{position:relative;height:auto;min-height:100svh}
  #herovid,.poster,.ring,.marks,.bands,.scrim,.hud,.statechip,.cue{display:none}
  .hero-static{display:flex!important;position:relative;min-height:100svh}
}

/* ============================ the drop sequence ============================
   Scrubbed on scroll like the hero, for the same reason: the reader sets the
   pace, so the four readings can take exactly as long as they want. The film is
   the picture only. Every word is drawn in the page, so it stays sharp at any
   size and switches language with everything else. */
.dropsec{position:relative;height:500vh;background:#0B0F06}
.dropstage{position:sticky;top:0;height:100vh;height:100svh;overflow:hidden;
  background:#0B0F06;isolation:isolate;
  --ax:50%;--ay:40%}
#dropvid,.dpost{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.dpost{background:center/cover no-repeat;opacity:1;transition:opacity .6s var(--ease)}
.dropstage.drop-ready .dpost{opacity:0}
#dropvid{opacity:0;transition:opacity .6s var(--ease)}
.dropstage.drop-ready #dropvid{opacity:1}
/* the film is already dark, so this only steadies the corners under the words */
.dveil{position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(ellipse 92% 78% at 50% 44%,rgba(8,12,4,0) 34%,rgba(8,12,4,.52) 82%,rgba(8,12,4,.78) 100%)}

.dhead{position:absolute;left:0;right:0;top:clamp(84px,12vh,150px);padding:0 var(--pad);
  text-align:center;color:var(--bone);text-shadow:var(--tshadow);
  opacity:var(--headop,1);transition:opacity .3s linear}
.dhead .kicker{color:var(--sand)}
.dhead h2{font-family:var(--display);font-weight:400;color:var(--bone);margin:14px auto 0;
  font-size:clamp(1.9rem,4.4vw,3.4rem);letter-spacing:-.022em;line-height:1.06;max-width:20ch}

/* the ring marks the drop the readings belong to */
.dring{position:absolute;left:var(--ax);top:var(--ay);width:clamp(64px,7vw,96px);
  aspect-ratio:1;margin:calc(clamp(64px,7vw,96px) / -2) 0 0 calc(clamp(64px,7vw,96px) / -2);
  border:1px solid rgba(245,239,229,.5);border-radius:50%;pointer-events:none;
  opacity:var(--ringop,0);transition:opacity .35s linear}
.dring::after{content:"";position:absolute;inset:-9px;border:1px solid rgba(245,239,229,.16);
  border-radius:50%}

.dlines{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;overflow:visible}
.dlines line{stroke:rgba(245,239,229,.55);stroke-width:1;
  transition:opacity .5s var(--ease)}

.calls{position:absolute;inset:0;pointer-events:none}
/* .call is moved every frame to stay with the droplet, so it carries no
   transition at all. .cbody does the arriving, which is why they are two
   elements: a transition on a per frame transform drags everything behind. */
.call{position:absolute;left:0;top:0;width:clamp(190px,18vw,258px);
  transform:translate3d(var(--cx,0px),var(--cy,0px),0);will-change:transform}
.cbody{position:relative;isolation:isolate;color:var(--bone);
  padding:clamp(13px,1.35vw,18px) clamp(15px,1.55vw,21px);
  text-shadow:var(--tshadow);opacity:0;
  transition:opacity .55s var(--ease),transform .55s var(--ease)}
.cbody b{display:block;font-family:var(--display);font-weight:400;
  font-size:clamp(1.12rem,1.7vw,1.5rem);letter-spacing:-.01em;line-height:1.1}
.cbody em{display:inline-block;margin-top:7px;font-style:normal;font-family:var(--mono);
  font-size:clamp(10px,1vw,11.5px);letter-spacing:.2em;color:var(--sand);
  border:1px solid rgba(201,169,107,.42);border-radius:999px;padding:3px 9px}
.cbody p{margin:11px 0 0;font-size:clamp(.86rem,1.12vw,.98rem);line-height:1.5;opacity:.9}
.call.side-l .cbody{text-align:right;transform:translateX(-16px)}
.call.side-r .cbody{text-align:left;transform:translateX(16px)}
.call.on .cbody{opacity:1;transform:translateX(0)}

.dbottom{position:absolute;left:0;right:0;bottom:0;height:56%;pointer-events:none;
  background:linear-gradient(to top,rgba(8,12,4,.94) 0%,rgba(8,12,4,.8) 24%,
    rgba(8,12,4,.44) 56%,rgba(8,12,4,.12) 82%,rgba(8,12,4,0) 100%);
  opacity:var(--endop,0);transition:opacity .4s linear}
.dend{position:absolute;left:0;right:0;bottom:clamp(64px,10vh,118px);padding:0 var(--pad);
  text-align:center;color:var(--bone);text-shadow:var(--tshadow);
  opacity:var(--endop,0);transition:opacity .4s linear}
/* one flat block of serif reads as an afterthought. The claim carries the
   display face at size, the explanation sits under it in the body face, and the
   difference between them is what makes it look composed rather than typed. */
.dend .lead{margin:0 auto;max-width:17ch;font-family:var(--display);font-weight:400;
  font-size:clamp(1.55rem,3.3vw,2.85rem);line-height:1.08;letter-spacing:-.022em}
.dend .say{margin:clamp(12px,1.7vh,21px) auto 0;max-width:40ch;font-family:var(--body);
  font-size:clamp(.92rem,1.28vw,1.1rem);line-height:1.5;font-weight:400;opacity:.84}

.dstatic{display:none}

/* Narrow screens have no room beside the drop, so the readings move underneath
   it and the leader lines are dropped rather than drawn to nowhere. */
@media (max-width:860px){
  .dropsec{height:510vh}
  .dlines,.dring{display:none}
  .calls{top:auto;bottom:clamp(96px,15vh,168px);height:auto;
    display:grid;grid-template-columns:1fr 1fr;gap:clamp(12px,2.4vw,20px);
    padding:0 var(--pad)}
  /* beats the .side-l right alignment, which only makes sense beside the drop */
  .call{position:static;width:auto;transform:none;will-change:auto}
  .cbody,.call.side-l .cbody,.call.side-r .cbody{text-align:left;
    transform:translateY(14px);padding:12px 13px}
  .call.on .cbody{transform:translateY(0)}
  .cbody b{font-size:1.02rem}
  .cbody em{margin-top:5px}
  .cbody p{margin-top:8px;font-size:.76rem;line-height:1.45}
  .dend{bottom:clamp(28px,5vh,54px)}
  .dend .lead{font-size:clamp(1.3rem,5.6vw,1.8rem);max-width:14ch}
  .dend .say{font-size:.88rem;max-width:32ch}
}
@media (max-width:860px){
  .call::before{-webkit-backdrop-filter:none;backdrop-filter:none;
    background:rgba(8,12,4,.78)}
}
@media (max-width:430px){
  .calls{grid-template-columns:1fr;gap:8px;bottom:clamp(84px,13vh,132px)}
  .cbody{padding:10px 12px}
  .cbody b{display:inline;vertical-align:middle}
  .cbody em{margin:0 0 0 9px;vertical-align:middle;padding:2px 8px}
  .cbody p{margin-top:5px;font-size:.74rem}
}

/* Same two exits as the hero: a screen too short to hold the sequence, and a
   visitor who asked for less motion. Both get the whole thing as plain page. */
@media (prefers-reduced-motion:reduce),
       (orientation:landscape) and (pointer:coarse) and (max-height:480px){
  .dropsec{height:auto;background:var(--bone-2)}
  .dropstage{display:none}
  .dstatic{display:block;padding:clamp(64px,9vh,112px) 0}
  .dstatic .dsgrid{margin-top:clamp(34px,5vw,54px);display:grid;
    grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(18px,2.6vw,30px)}
  .dstatic .dsgrid b{display:block;font-family:var(--display);font-weight:400;
    font-size:clamp(1.1rem,1.7vw,1.42rem);color:var(--text)}
  .dstatic .dsgrid em{display:inline-block;margin-top:6px;font-style:normal;
    font-family:var(--mono);font-size:11px;letter-spacing:.2em;color:var(--forest);
    border:1px solid var(--line);border-radius:999px;padding:3px 9px}
  .dstatic .dsgrid p{margin:10px 0 0;color:var(--text-2);line-height:1.55}
  .dstatic .shot{margin-top:clamp(34px,5vw,54px);border-radius:18px;overflow:hidden}
  .dstatic .shot img{width:100%;height:auto;display:block}
}

/* The film brightens hard under the words at both ends: bokeh behind the
   readings, and a lit chilli plant behind the closing line. Each block carries
   its own pool of shade. isolation:isolate is load bearing here for the same
   reason it is on .band, a z-index:-1 child escapes to the back of the sticky
   stage without it and paints behind the film. */
.cbody::before{content:"";position:absolute;pointer-events:none;z-index:-1}
/* A wash alone cannot win against the bokeh, which runs to near white and drifts
   under the words as the film plays. This crushes whatever is behind it instead,
   and the mask feathers the plate out so it never reads as a box. Measured worst
   case over the brightest frame, not judged by eye. */
.cbody::before{inset:0;border-radius:14px;background:rgba(8,12,4,.52);
  border:1px solid rgba(245,239,229,.11);
  -webkit-backdrop-filter:blur(14px) brightness(.34) saturate(.9);
  backdrop-filter:blur(14px) brightness(.34) saturate(.9)}
@supports not (backdrop-filter: blur(1px)){
  .cbody::before{background:rgba(8,12,4,.8)}
}

