/* ==========================================================================
   About — the journey
   Loads on top of app.css for the reset, the face and the navbar. Nothing new
   is introduced typographically: every size, weight and tracking below is the
   same system the rest of the site uses (Inter, 400 headings, -.035em).
   One scalar, --t, is the position along the journey. The field colours, the
   path colour, the copy and the parallax are all mixed off it, so the whole
   page is a single continuous move rather than five slides.
   ========================================================================== */

:root{
  --light:1;                 /* app.css navbar: white pill for the whole page */

  /* the live chapter blend, written by the driver every frame */
  --ca:#ff2d55; --cb:#a80f31; --cc:#14020a; --glow:#ff4d78;

  --pad: clamp(22px, 5.4vw, 104px);
}

.abody{
  background:#14020a;
  color:#fff;
  overflow-x:hidden;
}
.adefs{position:absolute;width:0;height:0;overflow:hidden}

/* ── The stage ───────────────────────────────────────────────────────────── */

.ab{position:relative;height:calc(100svh + 600svh)}
.ab__stage{
  position:sticky;top:0;height:100svh;overflow:hidden;
  isolation:isolate;
  background:var(--cc);
}

/* bright corner top-left, depth bottom-right — the direction every reference
   shares, whatever the hue */
.ab__field{
  position:absolute;inset:0;z-index:0;
  background:
    radial-gradient(112% 86% at 4% -6%,  var(--ca) 0%, transparent 58%),
    radial-gradient(104% 92% at 96% 106%, var(--cc) 0%, transparent 62%),
    linear-gradient(148deg, var(--cb) 0%, var(--cc) 72%);
}
/* keeps the edges heavier than the middle so the path always reads */
.ab__vig{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  background:radial-gradient(80% 70% at 50% 46%, transparent 0%, rgba(0,0,0,.30) 100%);
}

/* ── Cubes ───────────────────────────────────────────────────────────────
   Depth is carried by --z: bigger z means further away, so it blurs more and
   parallaxes less. The float and spin are ambient and independent of scroll;
   only --par comes from the journey.                                       */

.ab__cubes{position:absolute;inset:0;z-index:2;pointer-events:none}
.acube{
  position:absolute;left:var(--x);top:var(--y);
  width:var(--s);height:calc(var(--s) * 1.1);
  opacity:calc(var(--o) * .46);
  /* Three motions that compose instead of overwriting each other: the ambient
     float owns `transform`, the scroll drift owns `translate`, the scroll spin
     owns `rotate`. Each cube carries its own vector, and depth damps how far
     it travels, so the field genuinely moves around rather than sliding as a
     single sheet. */
  translate:
    calc(-50% + var(--sp,0) * var(--dx,0) * 1px * (1 - var(--z) * .55))
    calc(-50% + var(--sp,0) * var(--dy,0) * 1px * (1 - var(--z) * .55));
  rotate:calc(var(--sp,0) * var(--rot,0) * 1deg);
  filter:blur(calc(var(--z) * var(--z) * 7px));
  animation:abFloat var(--dur,36s) ease-in-out infinite alternate;
  will-change:translate,rotate,transform;
}
@keyframes abFloat{
  from{transform:translate3d(0,0,0) rotate(-3.5deg) scale(.97)}
  to  {transform:translate3d(0,-26px,0) rotate(3.5deg) scale(1.03)}
}

/* ── The world and the path ─────────────────────────────────────────────── */

.ab__world{
  position:absolute;left:0;top:0;width:100%;z-index:3;pointer-events:none;
  will-change:transform;
}
.ab__svg{display:block;width:100%;height:100%;overflow:visible}

/* the route ahead, always faintly present so the journey has somewhere to go */
.ab__track{stroke:#fff;stroke-opacity:.13;stroke-width:1.4}
/* the part already travelled */
.ab__live{
  stroke:var(--glow);stroke-width:2;stroke-linecap:round;
  filter:drop-shadow(0 0 6px var(--glow)) drop-shadow(0 0 18px var(--glow));
}
.ab__branch{
  stroke:var(--glow);stroke-width:1.4;stroke-linecap:round;stroke-opacity:.9;
  filter:drop-shadow(0 0 5px var(--glow));
}

/* chapter markers, dim until the point arrives */
.abnode circle{fill:none;stroke:var(--glow);stroke-width:1.2}
.abnode .abnode__halo{opacity:calc(.10 + var(--lit,0) * .5)}
.abnode .abnode__ring{opacity:calc(.28 + var(--lit,0) * .72)}
.abnode .abnode__core{fill:#fff;stroke:none;opacity:calc(.25 + var(--lit,0) * .75)}

.abbrdot{fill:#fff;stroke:none}
.ab__blabel{
  position:absolute;z-index:4;
  font-size:clamp(11px,.82vw,13px);font-weight:500;
  letter-spacing:.16em;text-transform:uppercase;
  color:#fff;opacity:calc(var(--bo,0) * .86);
  translate:-50% -50%;white-space:nowrap;
  text-shadow:0 0 18px rgba(0,0,0,.5);
}

/* the travelling point — held at one screen position while the world moves */
.ab__dot{position:absolute;z-index:5;pointer-events:none;translate:-50% -50%}
.ab__dot i{
  display:block;width:14px;height:14px;border-radius:50%;
  background:#fff;
  box-shadow:0 0 0 6px color-mix(in srgb, var(--glow) 26%, transparent),
             0 0 22px 6px var(--glow),
             0 0 60px 14px color-mix(in srgb, var(--glow) 55%, transparent);
}

/* ── Chapters ─────────────────────────────────────────────────────────────
   Every block sits in the same stage and only one is lit at a time. Sides
   alternate so the composition keeps moving with the path.                 */

.ab__copy{position:absolute;inset:0;z-index:4}
.ab__ch{
  position:absolute;top:50%;
  width:min(40%,560px);
  opacity:var(--o,0);
  translate:0 calc(-50% + (1 - var(--o,0)) * 22px);
  pointer-events:none;
}
.ab__ch--left  {left:var(--pad)}
.ab__ch--right {right:var(--pad);text-align:right}
.ab__ch--centre{
  left:50%;width:min(64%,760px);text-align:center;
  translate:-50% calc(-50% + (1 - var(--o,0)) * 22px);
}
.ab__ch [href]{pointer-events:auto}

/* the same treatment the Horizon hero uses: whatever is behind the copy —
   a cube edge, the path, a gradient seam — is blurred out and the field
   settled a little, feathered to nothing so it never reads as a panel */
.ab__ch::before{
  content:'';position:absolute;z-index:-1;pointer-events:none;
  left:-9%;right:-9%;top:-42%;bottom:-42%;
  -webkit-backdrop-filter:blur(22px);backdrop-filter:blur(22px);
  background:radial-gradient(58% 54% at 50% 50%, rgba(6,4,14,.34), rgba(6,4,14,0) 74%);
  -webkit-mask-image:radial-gradient(56% 52% at 50% 50%, #000 32%, transparent 76%);
  mask-image:radial-gradient(56% 52% at 50% 50%, #000 32%, transparent 76%);
}

.ab__eyebrow{
  margin:0 0 clamp(14px,1.5vw,22px);
  font-size:clamp(11px,.82vw,13px);font-weight:500;
  letter-spacing:.24em;text-transform:uppercase;
  color:var(--glow);
}
.ab__h{
  margin:0;font-weight:400;
  font-size:clamp(1.95rem,3.7vw,3.7rem);line-height:1.06;letter-spacing:-.04em;
  color:#fff;
  text-wrap:balance;
}
.ab__h--lead{max-width:14ch}
/* three authored lines: stepped down so the column keeps the author's breaks */
.ab__h--three{font-size:clamp(1.45rem,2.62vw,2.6rem);line-height:1.16}
.ab__ch--right .ab__h{margin-left:auto}
.ab__sub{
  margin:clamp(20px,2.2vw,34px) 0 0;
  font-size:clamp(.95rem,1.12vw,1.2rem);line-height:1.55;
  color:rgba(255,255,255,.74);
}
/* the eyebrow and support of the opening chapter arrive a beat after the
   headline, so the page opens on one spacious line and then settles */
.ab__late{opacity:var(--late,0)}

.ab__link{
  display:inline-flex;align-items:center;gap:.5em;
  margin-top:clamp(26px,2.8vw,44px);
  font-size:clamp(.95rem,1.05vw,1.12rem);font-weight:500;
  color:#fff;
  padding-bottom:6px;
  border-bottom:1px solid color-mix(in srgb, var(--glow) 70%, transparent);
  transition:gap .35s var(--ease), border-color .35s var(--ease);
}
.ab__link:hover{gap:.9em;border-bottom-color:#fff}

/* ── Entrance ────────────────────────────────────────────────────────────
   The chapters are hidden by their own --o default, which the driver writes
   every frame — a blanket .js-a rule here would outrank that and pin them at
   zero forever. The failsafe path is the other way round: if the script never
   arrives the class comes off, and the opening chapter shows unaided. */
html:not(.js-a) .ab__ch--lead{opacity:1}

/* ── Narrow ──────────────────────────────────────────────────────────────
   Same story, same nodes, same gradient run — a shallower path, fewer cubes
   and far less parallax, because the amplitude that reads as elegant on a
   desktop reads as thrash on a phone.                                      */

@media (max-width:860px){
  .ab{height:calc(100svh + 488svh)}
  /* the copy takes the upper screen and the node the lower, because at this
     width they would otherwise occupy the same place */
  .ab__ch,.ab__ch--centre{
    left:var(--pad);right:var(--pad);width:auto;text-align:left;top:32%;
    translate:0 calc(-50% + (1 - var(--o,0)) * 18px);
  }
  .ab__ch--right{text-align:left}
  .ab__ch--right .ab__h{margin-left:0}
  .ab__h{font-size:clamp(1.7rem,7.2vw,2.5rem)}
  .ab__h--three{font-size:clamp(1.3rem,5.4vw,1.9rem)}
  .ab__h--lead{max-width:none}
  .acube:nth-child(n+6){display:none}
  .ab__dot i{width:12px;height:12px}
}

@media (prefers-reduced-motion:reduce){
  .acube{animation:none}
}
