/* Dharti Group — the Ascent pinned sequence
   ============================================================ */

/* ============================================================
   THE ASCENT (wow)
   ============================================================ */
.ascent{ position:relative; height:320vh; }
.ascent__stage{
  position:sticky; top:0; height:100vh; overflow:hidden;
  display:flex; align-items:center; justify-content:center;
}
.sky{ position:absolute; inset:0; }
.sky--dusk{
  background:
    radial-gradient(120% 80% at 50% 100%, rgba(198,141,71,.45), transparent 55%),
    linear-gradient(180deg, #0d1b3a 0%, #2a2b52 45%, #6b4a55 78%, #b6784c 100%);
}
.sky--night{
  opacity:calc(var(--p));
  background:
    radial-gradient(120% 70% at 50% 108%, rgba(70,90,150,.25), transparent 60%),
    linear-gradient(180deg, #03060f 0%, #060d1c 46%, #0a1529 74%, #12203c 100%);
}
.stars{ position:absolute; inset:0; opacity:calc(var(--p)); }
.stars span{
  position:absolute; left:var(--x); top:var(--y);
  width:2px; height:2px; border-radius:50%; background:var(--bone);
  box-shadow:0 0 6px 1px rgba(243,239,230,.5);
  animation:twinkle 3.4s ease-in-out infinite; animation-delay:var(--d);
}
@keyframes twinkle{ 0%,100%{opacity:.3;} 50%{opacity:1;} }

/* ============================================================
   THE TOWER, DRAWING ITSELF
   An elevation put down line by line. Every stroke in the SVG carries
   pathLength="1", so one dash of length 1 and an offset running 1 -> 0
   reveals any path, whatever its real length, at the same rate.

   js/ascent.js still sets --l1/--l2/--l3 (eased, 0 to 1) and --settle.
   The three now mean base, shaft and crown.
   ============================================================ */
.asc-mark{
  position:relative; z-index:3;
  height:min(66vh, 620px);
  margin-top:6vh; margin-bottom:5vh;
  /* the whole drawing drifts up as the sequence runs */
  transform:translateY(calc((1 - var(--p)) * 7vh));
}
.asc-tower{
  display:block; height:100%; width:auto;
  overflow:visible;
  filter:drop-shadow(0 0 26px rgba(198,161,91,calc(.08 + var(--p) * .18)));
}

/* every drawn line, in the lockup's gold, at a weight that holds at any size */
.asc-s{
  fill:none;
  stroke:url(#dhAscLine);
  stroke-width:1.7; stroke-linecap:round; stroke-linejoin:round;
  vector-effect:non-scaling-stroke;
  stroke-dasharray:1;
  stroke-dashoffset:calc(1 - var(--t, 0));
  will-change:stroke-dashoffset;
}
.asc-s--heavy{ stroke-width:2.1; }
.asc-s--fine, .asc-s--fine .asc-s{ stroke-width:1.1; opacity:.72; }

/* each group owns one of the three scroll slices */
.asc-g--base  .asc-s{ --t:var(--l1, 0); }
.asc-g--shaft .asc-s{ --t:var(--l2, 0); }
.asc-g--crown .asc-s{ --t:var(--l3, 0); }

/* the storeys stack instead of arriving together: line i opens its own
   window inside --l2, the last one closing as the slice ends */
.asc-g--shaft .asc-s.asc-floor{
  --n:11;
  --s:calc(var(--i) / var(--n) * .62);
  --t:clamp(0, calc((var(--l2, 0) - var(--s)) / .38), 1);
}

/* the beacon, lit only once the mast is drawn */
.asc-beacon{
  fill:var(--gold-2);
  opacity:calc(max(0, (var(--l3, 0) - .82)) / .18);
}

/* the setting-out line the elevation is drawn from: a drafting mark, so it
   stays faint and never draws itself in */
.asc-guide{
  fill:none; stroke:rgba(224,196,137,.3); stroke-width:1;
  stroke-dasharray:3 7; vector-effect:non-scaling-stroke;
  opacity:calc(var(--l1, 0) * .8);
}

/* the light the tower rises into */
.asc-glow{
  position:absolute; left:50%; top:56%;
  width:280%; aspect-ratio:1; border-radius:50%;
  transform:translate(-50%,-50%) scale(calc(.55 + var(--p) * .55));
  opacity:calc(var(--p) * .45);
  background:radial-gradient(circle, rgba(198,161,91,.3) 0%, rgba(198,161,91,.09) 38%, transparent 66%);
  pointer-events:none;
}

/* the plinth it lands on, drawn only once the crown is home */
.asc-mark::after{
  content:""; position:absolute; left:50%; bottom:-4%;
  width:150%; height:1px;
  transform:translateX(-50%) scaleX(var(--settle, 0));
  opacity:var(--settle, 0);
  background:linear-gradient(90deg, transparent, rgba(224,196,137,.85) 50%, transparent);
}

.ascent__captions{
  /* clear of the mark's crown: the active caption used to sit six pixels
     above it at full height */
  position:absolute; z-index:4; left:0; right:0; top:11%;
  text-align:center; padding:0 var(--gutter); pointer-events:none;
}
.cap{
  position:absolute; left:0; right:0;
  font-weight:500; font-size:clamp(1.2rem,2.6vw,2rem); line-height:1.38; letter-spacing:-.02em; color:var(--bone);
  opacity:0; transform:translateY(16px);
  transition:opacity .6s var(--ease), transform .6s var(--ease);
  text-shadow:0 2px 30px rgba(0,0,0,.6);
}
.cap em{ color:var(--gold-2); }
.cap.active{ opacity:1; transform:none; }

.ascent__progress{
  position:absolute; z-index:5; bottom:2.2rem; left:50%; transform:translateX(-50%);
  width:min(200px,40vw); height:1px; background:rgba(243,239,230,.16);
}
.ascent__progress span{ display:block; height:100%; width:calc(var(--p)*100%); background:var(--gold); }

@media (max-width:820px){
  .ascent{ height:280vh; }
  /* the elevation is roughly 4:7, so on a phone it is height that runs out
     first. Give it the stage and let the captions keep the top. */
  .asc-mark{ height:min(56vh, 460px); margin-top:9vh; margin-bottom:4vh; }
  .asc-s{ stroke-width:1.4; }
  .asc-s--heavy{ stroke-width:1.7; }
  .asc-s--fine, .asc-s--fine .asc-s{ stroke-width:.9; }
}

/* ============================================================
   REDUCED MOTION
   Pinning three screens of scroll to drive an animation is the thing this
   preference exists to avoid, so the section collapses to a single screen
   and js/ascent.js hands it the finished frame.
   ============================================================ */
@media (prefers-reduced-motion:reduce){
  .ascent{ height:100vh; }
  .asc-mark{ transform:none; }
  /* the finished elevation, drawn */
  .asc-s{ --t:1 !important; stroke-dashoffset:0; }
  .asc-beacon{ opacity:1; }
  .asc-guide{ opacity:.24; }
  .stars span{ animation:none; opacity:.7; }
}
