/* ==========================================================================
   MAGNETIQ V2 : home.css
   Home page only. Loaded AFTER core.css and never redeclares a core token,
   utility or component. Everything here is layout and behaviour that exists
   on index.html and nowhere else.

   Scroll bound values come from the motion engine:
     --p   written on [data-scrub] and [data-pin] hosts (0 to 1)
   All --p driven maths uses multiplication by a literal reciprocal instead of
   calc division, because division by a variable is not universally supported.

   CONTENTS
     H1  Shared page helpers
     H2  01 Hero
     H3  02 Proof
     H4  03 Why motion (pinned line swap)
     H5  04 Capability scrub (pinned, mock browser)
     H6  05 Work rail + marquee
     H7  06 Packages teaser
     H8  07 Process rail
     H9  08 Testimonial + closing CTA
     H10 Reduced motion overrides
   ========================================================================== */


/* ==========================================================================
   H1  SHARED PAGE HELPERS
   ========================================================================== */

/* <i> is used as a non semantic hook all over this page, never as italics. */
#smooth i,
.ftr-fine i{ font-style:normal; }

/* The pinned blocks are held flush to the top of the viewport by the engine,
   so their inner panel owns a full screen and centres itself. */
.pin-inner{
  display:flex;
  align-items:center;
  min-height:100vh;
  min-height:100svh;
}


/* ==========================================================================
   H2  01 HERO
   Light surface, transparent so the liquid ink object shows through. A wash
   across the reading half keeps the copy at full contrast and hands the right
   of the frame to the object.
   ========================================================================== */

.hero{
  position:relative;
  min-height:100vh;
  min-height:100svh;
  display:flex;
  flex-direction:column;
  justify-content:space-between;
  padding-block:calc(var(--hdr-h) + clamp(22px,5vh,58px)) clamp(18px,2.6vh,30px);
  overflow:hidden;
}

/* An ink wash across the reading half. It guarantees contrast over the 3D
   object and it is what hands the right half of the frame to the object. */
.hero::before{
  content:"";
  position:absolute;
  inset:0;
  pointer-events:none;
  background:linear-gradient(96deg,
    var(--bg) 0%,
    var(--bg) 26%,
    color-mix(in srgb, var(--bg) 88%, transparent) 44%,
    color-mix(in srgb, var(--bg) 46%, transparent) 60%,
    transparent 80%);
}
.hero > *{ position:relative; }

.hero-in{
  flex:1 1 auto;
  display:flex;
  align-items:center;
  padding-block:clamp(10px,2.4vh,34px);
}

.hero-col{
  position:relative;
  width:100%;
  max-width:min(660px,62%);
}

.hero h1{
  font-size:clamp(2.4rem,5.9vw,6rem);
  max-width:14ch;
}
/* the per character split turns every letter into an atomic inline box, so the
   word wrappers are what stop a line breaking in the middle of a word */
.hero h1 .w{ white-space:nowrap; }
.hero .kicker{ margin-bottom:clamp(18px,3vh,30px); }
.hero .lede{ max-width:46ch; margin-top:clamp(20px,2.8vh,32px); }

.hero-cta{ --gap:12px; margin-top:clamp(26px,3.6vh,40px); }

/* ---- bottom rail --------------------------------------------------------- */

.hero-foot{
  flex:none;
  display:grid;
  gap:clamp(18px,2.6vh,28px);
}

.hero-cue{
  display:inline-flex;
  align-items:center;
  gap:12px;
  width:max-content;
  color:var(--fg-dim);
  transition:color .35s var(--e-out);
}
.hero-cue:hover{ color:var(--fg); }
/* The contract puts every mono label in uppercase at .18em. This cue was the one
   holdout. Done in CSS rather than by shouting in the dictionary, so the Indonesian
   and Chinese strings stay written as normal words. */
.hero-cue .mono-sm{ text-transform:uppercase; letter-spacing:.18em; }
.hero-cue-line{
  position:relative;
  display:block;
  width:1px;
  height:44px;
  background:var(--line);
  overflow:hidden;
}
.hero-cue-line::after{
  content:"";
  position:absolute;
  left:0; top:0;
  width:1px; height:44px;
  background:var(--fg);
  transform:translateY(-100%);
  animation:cueRun 2.4s var(--e-io) infinite;
}
@keyframes cueRun{
  0%   { transform:translateY(-100%); }
  55%  { transform:translateY(100%); }
  100% { transform:translateY(100%); }
}

.hero-rail{
  position:relative;
  isolation:isolate;
  display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));
  gap:clamp(14px,2vw,32px);
  padding-top:clamp(16px,2.4vh,26px);
  border-top:1px solid var(--line);
  list-style:none;
}
/* The diagonal hero wash runs out before the right of the frame, so the last
   two rail items would sit on bare 3D object. This bleeds a short vertical
   wash under the rail only: the object still owns the upper right, the fine
   mono copy still clears the contrast floor. */
.hero-rail::before{
  content:"";
  position:absolute;
  z-index:-1;
  inset:0 calc(var(--gut) * -1) calc(clamp(18px,2.6vh,30px) * -1);
  pointer-events:none;
  background:linear-gradient(180deg,
    transparent 0%,
    color-mix(in srgb, var(--bg) 72%, transparent) 32%,
    var(--bg) 72%);
  -webkit-backdrop-filter:blur(7px);
  backdrop-filter:blur(7px);
  -webkit-mask-image:linear-gradient(180deg,transparent 0%,#000 34%,#000 100%);
  mask-image:linear-gradient(180deg,transparent 0%,#000 34%,#000 100%);
}
.hero-rail li{
  display:flex;
  align-items:flex-start;
  gap:10px;
  font-family:var(--mono);
  font-size:10.5px;
  letter-spacing:.13em;
  line-height:1.5;
  text-transform:uppercase;
  color:var(--fg-dim);
  opacity:0;
  transform:translateY(14px);
  transition:opacity .8s var(--e-out), transform .9s var(--e-out);
}
html.is-ready .hero-rail li{ opacity:1; transform:none; }
.hero-rail li:nth-child(1){ transition-delay:.50s; }
.hero-rail li:nth-child(2){ transition-delay:.58s; }
.hero-rail li:nth-child(3){ transition-delay:.66s; }
.hero-rail li:nth-child(4){ transition-delay:.74s; }
.hero-rail .dot{
  margin-top:.42em;
  background:var(--iris);
  width:6px; height:6px;
}

@media (max-width:900px){
  .hero-col{ max-width:100%; }
  .hero h1{ max-width:16ch; }
  .hero::before{
    background:linear-gradient(180deg,
      var(--bg) 0%,
      color-mix(in srgb, var(--bg) 86%, transparent) 26%,
      color-mix(in srgb, var(--bg) 80%, transparent) 62%,
      color-mix(in srgb, var(--bg) 94%, transparent) 100%);
  }
}
@media (max-width:680px){
  .hero-rail{ grid-template-columns:repeat(2,minmax(0,1fr)); row-gap:14px; }
  .hero-cue{ display:none; }
  /* Lift the fact rail clear of the floating WhatsApp bubble, which is parked
     in this exact corner and is still on screen at the top of the page. */
  .hero{ padding-bottom:84px; }
}


/* ==========================================================================
   H3  02 PROOF
   ========================================================================== */

.prf-rule{
  position:relative;
  height:1px;
  width:100%;
  background:var(--line);
  margin-bottom:clamp(34px,5vh,64px);
  overflow:hidden;
}
.prf-rule > i{
  position:absolute;
  inset:0;
  display:block;
  background:var(--iris);
  background-size:220% 100%;
  transform:scaleX(0);
  transform-origin:0 50%;
  transition:transform 1.6s var(--e-io) .1s;
}
.prf-rule.is-in > i{ transform:scaleX(1); }

.prf-grid{ gap:clamp(26px,3vw,52px) clamp(20px,2.4vw,40px); }

.prf-cell{
  display:flex;
  flex-direction:column;
  gap:14px;
  padding-top:clamp(12px,1.6vh,20px);
  border-top:1px solid var(--line);
}
.prf-cell p{ max-width:22ch; }

.prf-val{ display:inline-flex; align-items:flex-start; }
.prf-unit{
  font-family:var(--serif);
  font-size:clamp(1.3rem,2.6vw,2.2rem);
  line-height:1;
  color:var(--fg-dim);
  margin-left:.06em;
  transform:translateY(.18em);
}

@media (max-width:640px){
  .prf-grid{ grid-template-columns:repeat(2,minmax(0,1fr)); }
  .prf-cell p{ font-size:9.5px; letter-spacing:.14em; }
}


/* ==========================================================================
   H4  03 WHY MOTION
   The left column pins for 100vh while three display lines hand over one by
   one. The right column starts half a screen down so its three cards reach the
   middle of the frame at p = .18, .51 and .84, which is the middle of each of
   the three line windows. Change one and you must retime the other.
   ========================================================================== */

.why-in{
  display:grid;
  gap:clamp(28px,4vw,80px);
  align-items:stretch;
}
@media (min-width:960px){
  .why-in{ grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr); }
}

.why-stage{ align-items:center; }
.why-stage-in{ width:100%; }
.why-stage .kicker{ margin-bottom:clamp(22px,4vh,44px); }

.why-lines{
  display:grid;
  align-items:start;
  /* A masked window. Lines leave through the top and arrive through the
     bottom, so the swap is a conveyor: the pair is always exactly one window
     apart, the stage is never empty and the two never sit on top of each
     other. Opacity plays no part in the handover any more. */
  overflow:hidden;
  padding-block:.08em;
}
.why-line{
  grid-area:1 / 1;
  font-family:var(--display);
  font-weight:500;
  font-variation-settings:'opsz' 96,'wght' 500;
  font-size:clamp(1.9rem,4.4vw,4.2rem);
  line-height:.98;
  letter-spacing:-.035em;
  color:var(--fg);
  max-width:13ch;

  /* window on the pin progress: fade in at --i0, hand over at --o0.
     The windows are butt joined ON PURPOSE: the incoming line's --i0 equals
     the outgoing line's --o0, so a and b grow in lockstep and the two lines
     travel as one conveyor, always exactly one window height apart. Fading was
     the original design and it failed both ways: butt-joined fades left a blank
     beat, overlapped fades stacked two headlines. Line one is lit from the
     first frame (--i0:-1). */
  --i0:0; --o0:9; --k:14;
  --a:clamp(0, calc((var(--p,0) - var(--i0)) * var(--k)), 1);
  --b:clamp(0, calc((var(--p,0) - var(--o0)) * var(--k)), 1);
  /* conveyor: y = (1 - a - b) * own height. Waiting below the window while
     a < 1, resting at 0, leaving above it as b grows. */
  opacity:1;
  transform:translate3d(0, calc((1 - var(--a) - var(--b)) * 100%), 0);
  will-change:opacity,transform;
}
.why-line:nth-child(1){ --i0:-1;  --o0:.30; }
.why-line:nth-child(2){ --i0:.30; --o0:.63; }
.why-line:nth-child(3){ --i0:.63; --o0:9; }

.why-line em{ font-size:1.06em; }

.why-track{
  position:relative;
  width:min(220px,44%);
  height:1px;
  margin-top:clamp(26px,4.4vh,52px);
  background:var(--line);
  overflow:hidden;
}
.why-track > i{
  position:absolute;
  inset:0;
  background:var(--iris);
  background-size:240% 100%;
  transform:scaleX(var(--p,0));
  transform-origin:0 50%;
}

/* The stack starts half a screen down so card one reaches the middle of the
   frame at the same moment line one takes over, and the three cards then rise
   through the pin in step with the three lines. */
.why-args{
  display:flex;
  flex-direction:column;
  justify-content:flex-start;
  gap:clamp(16px,4vh,44px);
  padding-top:50vh;
}

.why-card{
  position:relative;
  transition:border-color .45s var(--e-out);

  --i0:0; --o0:9; --k:14;
  --a:clamp(0, calc((var(--p,0) - var(--i0)) * var(--k)), 1);
  --b:clamp(0, calc((var(--p,0) - var(--o0)) * var(--k)), 1);
  --on:calc(var(--a) - var(--b));
}
.why-card:nth-child(1){ --i0:.01; --o0:.30; }
.why-card:nth-child(2){ --i0:.34; --o0:.63; }
.why-card:nth-child(3){ --i0:.67; --o0:9; }

/* the active card gains a brighter hairline, no opacity games, so every word
   stays at full contrast whatever the scroll is doing */
.why-card::before{
  content:"";
  position:absolute;
  inset:0;
  border-radius:inherit;
  box-shadow:inset 0 0 0 1px var(--fg);
  opacity:calc(var(--on,0) * .34);
  pointer-events:none;
}
.why-card h3{
  font-size:clamp(1.35rem,2.1vw,2rem);
  margin-bottom:14px;
  max-width:16ch;
}
.why-idx{
  display:block;
  color:var(--fg-dim);
  margin-bottom:clamp(18px,3vh,30px);
}
.why-card::after{
  content:"";
  position:absolute;
  left:0; top:0;
  width:2px;
  height:calc(var(--on,0) * 100%);
  background:var(--iris);
  background-size:100% 260%;
  background-position:0 12%;
}
.why-card:hover::after{ height:100%; transition:height .5s var(--e-out); }

@media (max-width:959px){
  .why-args{ padding-top:0; }
}


/* ==========================================================================
   H5  04 CAPABILITY SCRUB
   340vh of pinned scroll. --p lights the active row, rolls the big numeral and
   crossfades the mock browser. An inline script on the page reads the same --p
   and hands it to window.GL.setMorph so the 3D object morphs in step.
   ========================================================================== */

.cap{ padding-block:0; }

.cap-stage{
  align-items:center;
  padding-block:calc(var(--hdr-h) + clamp(18px,4vh,54px)) clamp(28px,6vh,70px);
}
.cap-in{
  display:grid;
  gap:clamp(30px,4vw,72px);
  align-items:center;
  width:100%;
}
@media (min-width:900px){
  .cap-in{ grid-template-columns:minmax(0,1fr) minmax(0,1.02fr); }
}

.cap-left{ position:relative; }
.cap-left > *{ position:relative; z-index:1; }
.cap-left .kicker{ margin-bottom:clamp(20px,3.4vh,38px); }

.cap-list{
  list-style:none;
  display:flex;
  flex-direction:column;
  gap:clamp(10px,1.6vh,18px);
  counter-reset:cap;
}

.cap-item{
  position:relative;
  display:grid;
  grid-template-columns:2px minmax(0,1fr);
  column-gap:clamp(14px,1.6vw,22px);
  row-gap:6px;
  padding-block:clamp(8px,1.2vh,14px);
  border-top:1px solid var(--line);

  --a0:0; --b0:9; --k:26;
  --x:clamp(0, calc((var(--p,0) - var(--a0)) * var(--k)), 1);
  --y:clamp(0, calc((var(--p,0) - var(--b0)) * var(--k)), 1);
  --on:calc(var(--x) - var(--y));
}
.cap-item:nth-child(1){ --a0:-.02; --b0:.18; }
.cap-item:nth-child(2){ --a0:.18;  --b0:.38; }
.cap-item:nth-child(3){ --a0:.38;  --b0:.58; }
.cap-item:nth-child(4){ --a0:.58;  --b0:.78; }
.cap-item:nth-child(5){ --a0:.78;  --b0:9;   }

.cap-bar{
  grid-row:1 / span 2;
  display:block;
  width:2px;
  height:100%;
  background:var(--iris);
  background-size:100% 300%;
  background-position:0 10%;
  transform:scaleY(var(--on,0));
  transform-origin:50% 0;
}
/* Both opacity floors are set so the inactive state still clears the 4.5:1
   contrast floor on ink (the name is large type, so 3:1 is its bar). */
.cap-name{
  font-family:var(--display);
  font-weight:500;
  font-variation-settings:'opsz' 32,'wght' 500;
  font-size:clamp(1.15rem,2vw,1.9rem);
  letter-spacing:-.025em;
  line-height:1.06;
  color:var(--fg);
  opacity:calc(.44 + .56 * var(--on,0));
  transform:translate3d(calc(var(--on,0) * 6px),0,0);
}
/* The note never collapses. A pinned panel whose inner height changed on scroll
   would make the engine remeasure the pin, so only opacity moves here. */
.cap-note{
  grid-column:2;
  font-size:clamp(13px,.95vw,15px);
  line-height:1.55;
  color:var(--fg);
  max-width:44ch;
  opacity:calc(.56 + .44 * var(--on,0));
}

/* ---- right side: numeral + mock browser --------------------------------- */

.cap-right{
  position:relative;
  display:flex;
  flex-direction:column;
  gap:clamp(14px,2vh,24px);
}

.cap-num{
  font-size:clamp(3.4rem,8vw,7.4rem);
  line-height:1;
  color:var(--fg);
  opacity:.5;
  height:1em;
  overflow:hidden;
  width:.72em;
  --d:clamp(0, calc(var(--p,0) * 5 - .5), 4);
  /* the roll is continuous, so the window feathers its top and bottom and a
     digit halfway through the change reads as a soft odometer, not a slice */
  -webkit-mask-image:linear-gradient(180deg,transparent 0%,#000 30%,#000 70%,transparent 100%);
  mask-image:linear-gradient(180deg,transparent 0%,#000 30%,#000 70%,transparent 100%);
}
.cap-num-roll{
  display:block;
  transform:translate3d(0, calc(var(--d) * -1em), 0);
}
.cap-num-roll i{
  display:block;
  height:1em;
  line-height:1;
  font-variant-numeric:lining-nums tabular-nums;
}

.mock{
  position:relative;
  border:1px solid var(--line);
  border-radius:var(--r);
  background:color-mix(in srgb, var(--card) 94%, transparent);
  -webkit-backdrop-filter:blur(18px);
  backdrop-filter:blur(18px);
  overflow:hidden;
  box-shadow:0 30px 70px rgba(0,0,0,.28);
}
.mock-bar{
  display:flex;
  align-items:center;
  gap:6px;
  padding:11px 14px;
  border-bottom:1px solid var(--line);
}
.mock-dot{
  width:7px; height:7px;
  border-radius:50%;
  background:var(--line);
  flex:none;
}
.mock-bar .mock-dot:first-child{ background:color-mix(in srgb, var(--flare) 60%, transparent); }
.mock-url{
  margin-left:10px;
  font-family:var(--mono);
  font-size:9.5px;
  letter-spacing:.12em;
  color:var(--fg-dim);
  text-transform:uppercase;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}

.mock-body{
  position:relative;
  display:grid;
  aspect-ratio:16/10;
}
.mock-pane{
  grid-area:1 / 1;
  position:relative;
  overflow:hidden;
  padding:clamp(16px,2vw,26px);

  --a0:0; --b0:9; --k:26;
  --x:clamp(0, calc((var(--p,0) - var(--a0)) * var(--k)), 1);
  --y:clamp(0, calc((var(--p,0) - var(--b0)) * var(--k)), 1);
  --on:calc(var(--x) - var(--y));
  opacity:var(--on);
  transform:translate3d(0, calc(14px - var(--on) * 14px), 0);
}
.mock-pane:nth-child(1){ --a0:-.02; --b0:.18; }
.mock-pane:nth-child(2){ --a0:.18;  --b0:.38; }
.mock-pane:nth-child(3){ --a0:.38;  --b0:.58; }
.mock-pane:nth-child(4){ --a0:.58;  --b0:.78; }
.mock-pane:nth-child(5){ --a0:.78;  --b0:9;   }

.mock-tag{
  position:absolute;
  left:clamp(16px,2vw,26px);
  bottom:clamp(14px,1.8vw,22px);
  font-family:var(--mono);
  font-size:9px;
  letter-spacing:.18em;
  color:var(--fg-dim);
}

/* pane 1 : gl */
.mock-gl{ display:grid; place-items:center; }
.mock-blob{
  width:46%;
  aspect-ratio:1;
  background:var(--iris);
  background-size:200% 200%;
  background-position:8% 50%;
  border-radius:58% 42% 47% 53% / 46% 55% 45% 54%;
  filter:blur(.4px);
  animation:blob 7s var(--e-io) infinite;
  box-shadow:0 0 60px color-mix(in srgb, var(--volt) 45%, transparent);
}
.mock-grid{
  position:absolute;
  inset:0;
  background-image:
    linear-gradient(to right, var(--line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--line) 1px, transparent 1px);
  background-size:34px 34px;
  opacity:.5;
  mask-image:radial-gradient(70% 70% at 50% 50%, #000 20%, transparent 78%);
  -webkit-mask-image:radial-gradient(70% 70% at 50% 50%, #000 20%, transparent 78%);
}

/* pane 2 : motion */
/* The panes read as a real screen only when they occupy the whole frame.
   Distributing the tracks over the full height (instead of clumping them in
   the middle) turns four bars plus the playhead into a timeline. */
.mock-motion{
  display:flex;
  flex-direction:column;
  justify-content:space-between;
  gap:10px;
  padding-block:clamp(22px,3vw,34px) clamp(42px,6vw,60px);
}
.mock-bar-row{
  display:block;
  height:clamp(10px,1.5vw,14px);
  border-radius:999px;
  background:var(--faint);
  overflow:hidden;
}
.mock-bar-row > i{
  display:block;
  height:100%;
  width:var(--w,50%);
  border-radius:999px;
  background:var(--iris);
  background-size:300% 100%;
  background-position:6% 50%;
  transform-origin:0 50%;
  animation:mockBar 3.4s var(--e-io) infinite alternate;
}
.mock-bar-row:nth-child(2) > i{ animation-delay:.25s; }
.mock-bar-row:nth-child(3) > i{ animation-delay:.5s; }
.mock-bar-row:nth-child(4) > i{ animation-delay:.75s; }
@keyframes mockBar{
  from{ transform:scaleX(.34); }
  to  { transform:scaleX(1); }
}
.mock-play{
  position:absolute;
  top:0; bottom:0;
  left:38%;
  width:1px;
  background:var(--acid);
  opacity:.8;
  animation:mockPlay 5s linear infinite;
}
@keyframes mockPlay{
  from{ left:8%; }
  to  { left:92%; }
}

/* pane 3 : multilingual */
.mock-lang{
  display:flex;
  flex-direction:column;
  justify-content:flex-start;
  gap:clamp(13px,2.2vw,22px);
  padding-block:clamp(20px,2.8vw,32px) clamp(42px,6vw,60px);
}
.mock-chips{ display:flex; gap:8px; margin-bottom:clamp(6px,1.4vw,16px); }
.mock-chips > i{
  padding:5px 11px;
  border-radius:999px;
  border:1px solid var(--line);
  font-family:var(--mono);
  font-size:9.5px;
  letter-spacing:.14em;
  color:var(--fg-dim);
}
.mock-chips > i.is-on{
  color:var(--bg);
  background:var(--fg);
  border-color:transparent;
}
.mock-line{
  display:block;
  height:clamp(9px,1.4vw,13px);
  width:var(--w,70%);
  border-radius:999px;
  background:var(--faint);
}

/* pane 4 : commerce + whatsapp */
.mock-shop{
  display:flex;
  flex-direction:column;
  justify-content:space-between;
  gap:14px;
  padding-block:clamp(20px,2.8vw,32px) clamp(42px,6vw,60px);
}
.mock-tiles{ display:grid; grid-template-columns:1fr 1fr; gap:10px; }
.mock-tiles > i{
  display:block;
  aspect-ratio:4/3;
  border-radius:10px;
  border:1px solid var(--line);
  background:linear-gradient(150deg,
    color-mix(in srgb, var(--volt) 40%, transparent),
    color-mix(in srgb, var(--flare) 26%, transparent));
}
.mock-tiles > i:last-child{
  background:linear-gradient(150deg,
    color-mix(in srgb, var(--volt-2) 34%, transparent),
    color-mix(in srgb, var(--acid) 22%, transparent));
}
.mock-chat{
  align-self:flex-start;
  padding:9px 14px;
  border-radius:14px 14px 14px 4px;
  background:#25D366;
  color:#062B14;
  font-family:var(--mono);
  font-size:9.5px;
  letter-spacing:.14em;
  text-transform:uppercase;
  animation:mockPop 4.2s var(--e-spring) infinite;
}
@keyframes mockPop{
  0%,70%,100%{ transform:translateY(0) scale(1); }
  78%{ transform:translateY(-4px) scale(1.04); }
}

/* pane 5 : dashboard */
.mock-dash{
  display:flex;
  align-items:center;
  gap:clamp(18px,3vw,38px);
  padding-block-end:clamp(30px,4vw,44px);
}
.mock-ring{
  position:relative;
  width:clamp(86px,13vw,152px);
  aspect-ratio:1;
  flex:none;
  border-radius:50%;
  background:conic-gradient(var(--volt-2) 0 62%, var(--faint) 62% 100%);
  display:grid;
  place-items:center;
}
.mock-ring::before{
  content:"";
  position:absolute;
  inset:clamp(9px,1.3vw,15px);
  border-radius:50%;
  background:var(--card);
}
.mock-ring > i{
  position:relative;
  font-family:var(--serif);
  font-size:clamp(20px,2.9vw,36px);
  color:var(--fg);
}
.mock-rows{ display:flex; flex-direction:column; gap:clamp(11px,1.7vw,17px); flex:1 1 auto; }
.mock-rows > i{
  display:block;
  height:clamp(10px,1.5vw,14px);
  width:var(--w,60%);
  border-radius:999px;
  background:var(--faint);
}

/* Below the two column breakpoint the mock browser cannot share a single pinned
   screen with the list, and a pinned panel taller than the viewport would hide
   its own last rows. The mock is decorative and aria-hidden, so it steps out. */
@media (max-width:899px), (max-height:640px){
  .cap-right{ display:none; }
}
/* single column: the list now sits directly over the object, so it gets the
   same kind of wash the hero uses */
@media (max-width:899px){
  /* the wash below bleeds past the gutter, so the section clips it */
  .cap{ overflow:hidden; }
  .cap-left::before{
    content:"";
    position:absolute;
    inset:-8% -26%;
    z-index:0;
    pointer-events:none;
    background:radial-gradient(46% 46% at 50% 50%,
      color-mix(in srgb, var(--bg) 88%, transparent) 0%,
      color-mix(in srgb, var(--bg) 70%, transparent) 54%,
      transparent 100%);
  }
}


/* ==========================================================================
   H6  05 WORK RAIL
   ========================================================================== */

.wk-rail{
  overflow-x:auto;
  overflow-y:hidden;
  scroll-snap-type:x proximity;
  -webkit-overflow-scrolling:touch;
  scrollbar-width:none;
  padding-block:4px clamp(18px,2.6vh,30px);
}
.wk-rail::-webkit-scrollbar{ height:0; display:none; }
.wk-rail.is-drag{ scroll-snap-type:none; user-select:none; }

.wk-track{
  display:flex;
  gap:clamp(16px,2vw,34px);
  padding-inline:var(--gut);
  width:max-content;
}

.wk-card{
  flex:none;
  width:clamp(268px,32vw,470px);
  scroll-snap-align:center;
  display:flex;
  flex-direction:column;
  gap:16px;
  -webkit-tap-highlight-color:transparent;
}

.wk-shot{
  display:block;
  aspect-ratio:8 / 5;
  border-radius:var(--r);
  background:var(--faint);
  position:relative;
  overflow:hidden;
}
/* The wipe lives on the image, never on the observed element. A data-reveal
   host that clips ITSELF reports a zero area intersection, so its observer
   never fires and the reveal is stuck shut. The host only fades, the image
   carries the clip. */
.wk-shot img{
  position:absolute;
  inset:0;
  width:100%; height:100%;
  object-fit:cover;
  transform:scale(1.04);
  clip-path:inset(0 0 100% 0);
  transition:transform 1.3s var(--e-out), clip-path 1.1s var(--e-io), filter .7s var(--e-out);
}
.wk-shot.is-in img{ clip-path:inset(0 0 0 0); transform:scale(1.001); }
.wk-card:hover .wk-shot.is-in img{ transform:scale(1.055); }
.wk-shot::after{
  content:"";
  position:absolute;
  inset:0;
  border-radius:inherit;
  box-shadow:inset 0 0 0 1px var(--line);
  pointer-events:none;
}

.wk-meta{
  display:grid;
  grid-template-columns:auto minmax(0,1fr);
  column-gap:14px;
  row-gap:8px;
  align-items:baseline;
}
.wk-idx{
  color:var(--fg-dim);
  grid-row:1;
}
.wk-name{
  font-family:var(--display);
  font-weight:600;
  font-variation-settings:'opsz' 24,'wght' 600;
  font-size:clamp(1.05rem,1.4vw,1.35rem);
  letter-spacing:-.02em;
  color:var(--fg);
  grid-row:1;
}
.wk-desc{
  grid-column:2;
  font-size:14px;
  line-height:1.55;
  color:var(--fg-dim);
  max-width:38ch;
}
.wk-tags{
  grid-column:2;
  display:flex;
  flex-wrap:wrap;
  gap:6px;
}

.wk-foot{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:20px;
  flex-wrap:wrap;
  padding-top:clamp(6px,1vh,14px);
}

.wk-marquee{
  margin-top:clamp(44px,7vh,96px);
  padding-block:clamp(16px,2.4vh,26px);
  border-top:1px solid var(--line);
  border-bottom:1px solid var(--line);
}
.wk-marquee .marquee-item{
  font-size:clamp(1.3rem,3.4vw,2.8rem);
  color:var(--fg-dim);
  transition:color .4s var(--e-out);
}
.wk-marquee:hover .marquee-item{ color:var(--fg); }

@media (max-width:560px){
  .wk-card{ width:78vw; }
}


/* ==========================================================================
   H7  06 PACKAGES TEASER
   ========================================================================== */

.pk-grid{ align-items:stretch; }

.pk-card{
  display:flex;
  flex-direction:column;
  gap:clamp(18px,2.4vh,26px);
  padding-top:clamp(48px,5vw,64px);   /* clears the "most popular" badge */
}
.pk-card.is-pop{
  border-color:color-mix(in srgb, var(--volt-2) 52%, transparent);
  background:linear-gradient(180deg,
    color-mix(in srgb, var(--volt) 12%, var(--card)) 0%,
    var(--card) 58%);
}
.pk-badge{
  position:absolute;
  top:16px; right:16px;
  background-size:220% 100%;
  background-position:6% 50%;
}

.pk-head h3{ font-size:clamp(1.5rem,2.2vw,2.1rem); }
.pk-head p{ margin-top:8px; }
/* Same rule as the packages page: while the cards are in a row, the one line
   and two line subtitles must still leave the prices on one baseline. */
@media (min-width:641px){
  .pk-head p{ min-height:46px; min-height:3lh; }
}

.pk-price{
  display:flex;
  align-items:baseline;
  gap:12px;
  flex-wrap:wrap;
  padding-bottom:clamp(16px,2vh,22px);
  border-bottom:1px solid var(--line);
}
.pk-price .num{ font-size:clamp(2.4rem,4.4vw,3.6rem); }
.pk-idr{ color:var(--fg-dim); letter-spacing:.14em; }

.price{ white-space:nowrap; font-variant-numeric:lining-nums tabular-nums; }

/* The included hosting years. Every package is all in now, so this line is the
   offer, not a footnote. Same pill language as the rest of the system, tokens
   only, no new colour. */
.pk-inc{
  display:inline-flex;
  align-items:center;
  gap:9px;
  align-self:flex-start;
  max-width:100%;
  padding:8px 14px;
  border:1px solid var(--line);
  border-radius:999px;
  background:var(--faint);
  color:var(--fg);
  letter-spacing:.1em;   /* tighter than .mono-sm so the line does not wrap */
  line-height:1.4;
}
.pk-inc i{
  flex:0 0 auto;
  width:6px; height:6px;
  border-radius:50%;
  background:var(--volt-2);
}
.pk-card.is-pop .pk-inc{ border-color:color-mix(in srgb, var(--acid) 42%, transparent); }
.pk-card.is-pop .pk-inc i{ background:var(--acid); }

/* the per card renewal micro line, tucked under the included hosting pill so
   the buyer reads "included, then this" as one thought, never a surprise */
.pk-then{
  margin-top:calc(9px - clamp(18px,2.4vh,26px));
  padding-left:15px;
  color:var(--fg-dim);
  letter-spacing:.1em;
  line-height:1.5;
}
.pk-then .price{ color:var(--fg); }

/* the honest renewal line, so nobody is surprised in year two */
.pk-renew{
  max-width:none;                    /* the body rule caps p at 62ch */
  margin-top:clamp(28px,3.4vh,44px);
  text-align:center;
  color:var(--fg-dim);
  line-height:1.6;
}
.pk-renew .price{ color:var(--fg); }
.pk-renew + .pk-foot{ margin-top:clamp(20px,2.4vh,30px); }

.pk-list{
  list-style:none;
  display:flex;
  flex-direction:column;
  gap:11px;
  flex:1 1 auto;
  margin:0;
  padding:0;
}
.pk-list li{
  position:relative;
  padding-left:22px;
  font-size:14.5px;
  line-height:1.5;
  color:var(--fg-dim);
}
.pk-list li::before{
  content:"";
  position:absolute;
  left:0; top:.55em;
  width:9px; height:1px;
  background:var(--fg-dim);
}
.pk-card.is-pop .pk-list li::before{ background:var(--acid); width:11px; }

.pk-foot{
  display:flex;
  justify-content:center;
  margin-top:clamp(32px,4.4vh,56px);
}

@media (max-width:640px){
  .pk-card{ padding-top:52px; }
  .pk-price .num{ font-size:clamp(2.6rem,11vw,3.4rem); }
}


/* ==========================================================================
   H8  07 PROCESS RAIL
   The connecting line draws with --p from [data-scrub] on .pr-rail, remapped
   so it finishes while the block is still on screen instead of as it exits.
   ========================================================================== */

.pr-rail{
  position:relative;
  --draw:clamp(0, calc((var(--p,0) - .14) * 2.6), 1);
}

.pr-line{
  position:absolute;
  left:0; right:0;
  top:6px;
  height:1px;
  background:var(--line);
  overflow:hidden;
}
.pr-line > i{
  display:block;
  width:100%; height:100%;
  background:var(--iris);
  background-size:200% 100%;
  transform:scaleX(var(--draw));
  transform-origin:0 50%;
}

.pr-steps{
  position:relative;
  display:grid;
  grid-template-columns:repeat(5,minmax(0,1fr));
  gap:clamp(16px,2vw,34px);
  padding-top:34px;
  list-style:none;
}

.pr-step{
  position:relative;
  --s0:0;
  --lit:clamp(0, calc((var(--draw) - var(--s0)) * 9), 1);
}
.pr-step:nth-child(1){ --s0:.02; }
.pr-step:nth-child(2){ --s0:.22; }
.pr-step:nth-child(3){ --s0:.44; }
.pr-step:nth-child(4){ --s0:.66; }
.pr-step:nth-child(5){ --s0:.86; }

.pr-dot{
  position:absolute;
  top:-32px;
  left:0;
  width:9px; height:9px;
  border-radius:50%;
  background:var(--bg);
  box-shadow:inset 0 0 0 1px var(--line);
}
.pr-dot::after{
  content:"";
  position:absolute;
  inset:-2px;
  border-radius:50%;
  background:var(--iris);
  background-size:200% 200%;
  opacity:var(--lit,0);
  transform:scale(calc(.55 + .45 * var(--lit,0)));
}

.pr-n{
  display:block;
  color:var(--fg-dim);
  margin-bottom:12px;
}
.pr-step h4{ margin-bottom:10px; }
.pr-step p{ font-size:14px; line-height:1.55; max-width:30ch; }

@media (max-width:900px){
  .pr-steps{
    grid-template-columns:minmax(0,1fr);
    gap:clamp(26px,4vh,40px);
    padding-top:0;
    padding-left:36px;
  }
  .pr-line{
    top:6px; bottom:6px;
    left:4px; right:auto;
    width:1px; height:auto;
  }
  .pr-line > i{
    transform:scaleY(var(--draw));
    transform-origin:50% 0;
  }
  .pr-dot{ top:4px; left:-36px; }
  .pr-step p{ max-width:44ch; }
}


/* ==========================================================================
   H9  08 TESTIMONIAL + CLOSING CTA
   ========================================================================== */

.close{ padding-bottom:0; overflow:hidden; }

.quote{
  position:relative;
  max-width:min(820px,72%);
  padding-block:clamp(10px,3vh,40px);
}
.q-mark{
  font-size:clamp(4rem,9vw,8rem);
  line-height:.6;
  color:var(--fg-dim);
  opacity:.4;
  margin-bottom:.08em;
  max-width:none;
}
.q-text{
  font-family:var(--serif);
  font-style:italic;
  font-weight:400;
  font-size:clamp(1.55rem,3.5vw,3.1rem);
  line-height:1.16;
  letter-spacing:-.015em;
  color:var(--fg);
  max-width:26ch;
  padding-left:0;
  border-left:0;
}
.q-by{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:8px 16px;
  margin-top:clamp(26px,4vh,44px);
  padding-top:clamp(16px,2.4vh,24px);
  border-top:1px solid var(--line);
  max-width:40ch;
}

@media (max-width:900px){
  .quote{ max-width:100%; }
}

.cta{
  position:relative;
  margin-top:clamp(70px,12vh,170px);
  padding-block:clamp(80px,15vh,190px) clamp(80px,14vh,180px);
  border-top:1px solid var(--line);
}
/* a violet bloom behind the closing line, faded out well inside its own box so
   it can never draw its own rectangle on the page */
.cta::before{
  content:"";
  position:absolute;
  inset:0;
  pointer-events:none;
  background:radial-gradient(40% 48% at 50% 46%,
    color-mix(in srgb, var(--volt) 30%, transparent) 0%,
    color-mix(in srgb, var(--volt-2) 12%, transparent) 44%,
    transparent 100%);
}
.cta > *{ position:relative; }

.cta-line{
  font-size:clamp(2.3rem,7vw,7rem);
  max-width:15ch;
  margin-inline:auto;
}
.cta-lede{
  margin-top:clamp(22px,3vh,34px);
  max-width:48ch;
}
.cta-btns{
  --gap:14px;
  justify-content:center;
  margin-top:clamp(30px,4.4vh,48px);
}
.cta-fine{ margin-top:clamp(20px,2.6vh,30px); max-width:none; }


/* ==========================================================================
   H10 REDUCED MOTION
   Scroll bound values keep tracking under reduced motion (the engine still
   writes --p), so anything that hides content by default is forced open here.
   Kept last so it wins inside this stylesheet.
   ========================================================================== */

@media (prefers-reduced-motion: reduce){
  .pin-inner{ min-height:0; }

  .hero-cue-line::after{ display:none; }

  .prf-rule > i{ transform:scaleX(1); }

  .why-lines{ gap:clamp(16px,3vh,30px); }
  .why-line{
    grid-area:auto;
    opacity:1;
    transform:none;
    font-size:clamp(1.5rem,3.4vw,2.6rem);
  }
  .why-track > i{ transform:scaleX(1); }
  .why-args{ padding-top:0; justify-content:flex-start; }
  .why-card::before{ opacity:0; }
  .why-card::after{ height:100%; }

  .cap-stage{ padding-block:clamp(40px,8vh,90px); }
  .cap-item{ opacity:1; }
  .cap-bar{ transform:scaleY(1); }
  .cap-name{ transform:none; }
  .cap-note{ opacity:1; }
  .cap-num-roll{ transform:none; }
  .mock-pane{ opacity:0; transform:none; }
  .mock-pane:first-child{ opacity:1; }

  .pr-line > i{ transform:scaleX(1); }
  .pr-dot::after{ opacity:1; transform:scale(1); }

  .wk-shot img{ clip-path:none; transform:scale(1.001); }

  .cta{ margin-top:clamp(60px,10vh,120px); }
}

@media (prefers-reduced-motion: reduce) and (max-width:900px){
  .pr-line > i{ transform:scaleY(1); }
}
