/* ============================================================
   Sahar Sabouri — Scrollytelling layer
   Pinned scenes, stepped reveals, scroll-linked motion.
   Every effect degrades to a readable static layout when
   `prefers-reduced-motion: reduce` or JS is unavailable.
   ============================================================ */

:root { --header-h: 74px; }

/* ---------- Scroll progress ---------- */
.progress {
  position: absolute; left: 0; right: 0; bottom: -1px; height: 2px;
  background: transparent; overflow: hidden;
}
.progress__bar {
  height: 100%; width: 100%; background: var(--brand);
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform .1s linear;
}

/* ---------- Chapter rail ---------- */
.rail {
  position: fixed; left: clamp(1rem, .3rem + 1.4vw, 2rem); top: 50%;
  transform: translateY(-50%); z-index: 80;
  display: grid; gap: .1rem;
  opacity: 0; pointer-events: none;
  transition: opacity .4s var(--ease);
}
.rail.is-visible { opacity: 1; pointer-events: auto; }
.rail a {
  display: flex; align-items: center; gap: .7rem;
  text-decoration: none; padding: .3rem 0; color: var(--muted);
}
.rail__dot {
  width: 9px; height: 9px; border-radius: 50%; flex: none;
  border: 1.5px solid var(--line); background: var(--bg);
  transition: background-color .3s var(--ease), border-color .3s var(--ease), transform .3s var(--ease);
}
.rail__label {
  font-size: .72rem; letter-spacing: .06em; font-weight: 500;
  white-space: nowrap; opacity: 0; transform: translateX(-6px);
  transition: opacity .3s var(--ease), transform .3s var(--ease), color .3s var(--ease);
}
.rail a:hover .rail__label, .rail a.is-active .rail__label { opacity: 1; transform: translateX(0); }
.rail a.is-active .rail__dot { background: var(--brand); border-color: var(--brand); transform: scale(1.25); }
.rail a.is-active .rail__label { color: var(--ink); }
@media (max-width: 1180px) { .rail { display: none; } }

/* ---------- Hero, scroll-driven ---------- */
.hero--scrolly { min-height: calc(100dvh - var(--header-h)); display: grid; align-items: center; }
.hero__cue {
  display: inline-flex; flex-direction: column; align-items: center; gap: .5rem;
  margin-top: clamp(1.5rem, 1rem + 2vw, 3rem);
  font-size: .7rem; letter-spacing: .16em; text-transform: uppercase; color: var(--muted);
  text-decoration: none;
}
.hero__cue-line {
  width: 1px; height: 46px; background: linear-gradient(var(--line), var(--brand));
  position: relative; overflow: hidden;
}
.hero__cue-line::after {
  content: ""; position: absolute; left: -1px; width: 3px; height: 14px; border-radius: 2px;
  background: var(--brand); animation: cue 2.1s var(--ease) infinite;
}
@keyframes cue {
  0%   { top: -14px; opacity: 0; }
  35%  { opacity: 1; }
  100% { top: 46px; opacity: 0; }
}

/* ---------- Generic scrolly scene ---------- */
/* DOM order is intro -> graphic -> steps, which is exactly what a phone
   needs. On wide screens the three are placed explicitly instead: the
   graphic occupies one column across both rows, the words the other. */
.scrolly {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: clamp(2rem, 1rem + 4vw, 5rem);
  align-items: start;
}
.scrolly__intro  { grid-column: 2; grid-row: 1; }
.scrolly__sticky { grid-column: 1; grid-row: 1 / span 2; align-self: start;
                   position: sticky; top: calc(var(--header-h) + clamp(1.5rem, 1rem + 2vw, 3rem)); }
.scrolly__steps  { grid-column: 2; grid-row: 2; display: grid; }

.scrolly--flip .scrolly__intro,
.scrolly--flip .scrolly__steps  { grid-column: 1; }
.scrolly--flip .scrolly__sticky { grid-column: 2; }

.scrolly__intro { padding-block: 2rem 1rem; }
.scrolly__step {
  min-height: 66vh; display: flex; flex-direction: column; justify-content: center;
  padding-block: 2rem;
}
.scrolly__step:last-child { min-height: 50vh; }

/* Step card look */
.step-card {
  background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--radius);
  padding: clamp(1.4rem, 1.1rem + 1vw, 2rem);
  box-shadow: var(--shadow-sm);
  opacity: .38; transform: translateY(14px) scale(.985); transform-origin: left center;
  transition: opacity .5s var(--ease), transform .5s var(--ease), box-shadow .5s var(--ease), border-color .5s var(--ease);
}
.scrolly__step.is-active .step-card {
  opacity: 1; transform: none; box-shadow: var(--shadow); border-color: var(--line);
}
.step-card__no {
  font-size: .7rem; letter-spacing: .16em; text-transform: uppercase;
  color: var(--brand); font-weight: 650; margin-bottom: .7rem; display: block;
}
.step-card h3 { font-size: var(--step-2); margin-bottom: .4em; }
.step-card p { font-size: .97rem; }

/* ---------- The scene on a phone ---------- */
/* One column: the chapter title, then a graphic panel pinned under the
   header, then the cards scrolling through the space below it. The panel
   is opaque and full-bleed so cards pass cleanly underneath instead of
   colliding with it. */
@media (max-width: 900px) {
  .scrolly {
    display: block;
    --panel-h: clamp(180px, 26vh, 240px);
    --panel-pad: .75rem;
  }
  .scrolly__intro { padding-block: 0 1.4rem; }

  .scrolly__sticky {
    position: sticky; top: var(--header-h); z-index: 3;
    height: var(--panel-h);
    display: grid; place-items: center;
    margin-inline: calc(var(--gutter) * -1);
    padding: var(--panel-pad) var(--gutter);
    background: var(--scene-bg, var(--bg));
    /* Nothing may escape the panel onto the cards travelling underneath.
       A graphic sized from its own image, or a caption that grew when the
       language changed, has managed it before. `clip` rather than `hidden`
       because `hidden` would make this a scroll container. */
    overflow: clip;
    /* A box-shadow is painted outside the border box, so `overflow: clip`
       leaves it alone — a gradient pseudo-element would have been cut off. */
    box-shadow: 0 14px 20px -18px rgba(20,33,31,.55);
  }

  .scrolly__steps { padding-top: 1.1rem; }
  /* One card at a time, in the strip the panel leaves free. Capped: on a tall
     phone the untrimmed strip left the next card so far down that the reader
     scrolled through a screenful of nothing to reach it. */
  .scrolly__step {
    min-height: clamp(17rem, calc(100dvh - var(--header-h) - var(--panel-h) - 1.5rem), 26rem);
    padding-block: .5rem; justify-content: center;
  }
  .scrolly__step:last-child { min-height: auto; padding-bottom: 1.5rem; }

  /* The three-phase path reads better as a horizontal stepper on a phone,
     so that scene needs far less panel. */
  .path-scene { --panel-h: 124px; }
}

/* ---------- Scene 1: concerns constellation ---------- */
.constellation {
  position: relative; aspect-ratio: 1; width: 100%; max-width: 460px; margin-inline: auto;
  display: grid; place-items: center;
}
.constellation__ring {
  position: absolute; inset: 0; border-radius: 50%; border: 1px dashed var(--line);
  animation: spin 90s linear infinite;
}
.constellation__ring:nth-child(2) { inset: 14%; border-style: solid; opacity: .7; animation-duration: 130s; animation-direction: reverse; }
.constellation__ring:nth-child(3) { inset: 28%; border-color: var(--sand); animation-duration: 70s; }
@keyframes spin { to { transform: rotate(360deg); } }
.constellation__core {
  position: relative; width: 44%; aspect-ratio: 1; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #fff, var(--brand-soft) 70%);
  border: 1px solid rgba(46,106,94,.16);
  display: grid; place-items: center; text-align: center; padding: 1.4rem;
  box-shadow: 0 20px 50px -22px rgba(46,106,94,.5);
}
.constellation__core span {
  font-family: var(--font-display); font-size: clamp(.95rem, .8rem + .5vw, 1.2rem);
  color: var(--brand-dark); line-height: 1.25;
}
.constellation__node {
  position: absolute; padding: .5rem .9rem; border-radius: 100px;
  background: var(--surface); border: 1px solid var(--line-soft);
  font-size: .8rem; color: var(--muted); white-space: nowrap;
  box-shadow: var(--shadow-sm);
  opacity: .45; transform: scale(.92);
  transition: opacity .5s var(--ease), transform .5s var(--ease), color .5s var(--ease),
              border-color .5s var(--ease), box-shadow .5s var(--ease);
}
.constellation__node.is-lit {
  opacity: 1; transform: scale(1); color: var(--ink);
  border-color: var(--brand); box-shadow: 0 10px 28px -12px rgba(46,106,94,.45);
}
.constellation__node[data-pos="1"] { top: 2%;  left: 50%; translate: -50% 0; }
.constellation__node[data-pos="2"] { top: 20%; right: -2%; }
.constellation__node[data-pos="3"] { bottom: 22%; right: -4%; }
.constellation__node[data-pos="4"] { bottom: 1%; left: 50%; translate: -50% 0; }
.constellation__node[data-pos="5"] { bottom: 22%; left: -4%; }
.constellation__node[data-pos="6"] { top: 20%; left: -2%; }
@media (max-width: 900px) {
  /* No room for a ring of labels: show the core and the one theme the
     reader is on, which still changes as they scroll. Two rows — the label
     takes what it needs and the core takes the rest — so the pair can never
     add up to more than the panel, whatever the label says in Persian. */
  .constellation {
    aspect-ratio: auto; max-width: none; width: 100%; height: 100%;
    /* a grid item's automatic minimum is its *min-content* height — one word
       per line — which quietly outvotes `height: 100%` and pushes the graphic
       back out of the panel */
    min-height: 0;
    display: grid; grid-template-rows: minmax(0, 1fr) auto;
    justify-items: center; gap: .7rem;
  }
  .constellation__ring { display: none; }
  .constellation__core {
    width: auto; height: 100%; aspect-ratio: 1; max-width: 100%;
    padding: clamp(.7rem, .45rem + 1vw, 1.1rem);
  }
  .constellation__core span { font-size: clamp(.76rem, .7rem + .5vw, .96rem); line-height: 1.2; }
  /* `[data-pos]` outranks a bare class, so the ring placement has to be undone
     at the same specificity. Without the attribute here, nodes 1 and 4 kept
     their `translate: -50%` and hung half off the left edge of the phone. */
  .constellation__node[data-pos] {
    position: static; inset: auto; translate: none;
    display: none; opacity: 1; transform: none;
    white-space: normal; max-width: 100%; text-align: center;
    font-size: .84rem; padding: .45rem .9rem;
    color: var(--ink); border-color: var(--brand);
    box-shadow: 0 10px 28px -12px rgba(46,106,94,.45);
  }
  .constellation__node[data-pos].is-current { display: inline-flex; }
}

/* ---------- Scene 2: portrait that breathes ---------- */
.figure-sticky { position: relative; max-width: 430px; margin-inline: auto; width: 100%; }
.figure-sticky__frame {
  position: relative; overflow: hidden; border-radius: var(--radius-lg);
  aspect-ratio: 4/5; box-shadow: var(--shadow-lg); background: var(--bg-alt);
}
.figure-sticky__frame img {
  width: 100%; height: 100%; object-fit: cover; object-position: 50% 15%;
  transform: scale(var(--zoom, 1.04));
  transition: transform 1.1s var(--ease);
}
.figure-sticky__veil {
  position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(20,33,31,.78) 0%, rgba(20,33,31,.18) 42%, transparent 72%);
}
.figure-sticky__cap {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 1.5rem;
  color: #fff;
  display: grid;                 /* every caption shares one cell … */
}
.figure-sticky__cap .cap {
  grid-area: 1 / 1;              /* … so only the lit one is ever visible */
  opacity: 0; transform: translateY(10px);
  transition: opacity .2s var(--ease), transform .2s var(--ease);
}
/* the outgoing caption clears out before the next fades in, so the two
   never sit on top of each other mid-crossfade */
.figure-sticky__cap .cap.is-on {
  opacity: 1; transform: none;
  transition: opacity .34s var(--ease) .14s, transform .34s var(--ease) .14s;
}
.figure-sticky__cap strong { display: block; font-family: var(--font-display); font-size: 1.15rem; margin-bottom: .15rem; }
.figure-sticky__cap span { font-size: .82rem; color: rgba(255,255,255,.72); }
@media (max-width: 900px) {
  /* A tall thin photo with text laid over it wastes a phone's width, so the
     panel turns on its side: portrait left, caption beside it. */
  .figure-sticky {
    max-width: 440px; width: 100%; height: 100%;
    min-height: 0;               /* see the note on .constellation above */
    display: grid; grid-template-columns: auto 1fr;
    gap: clamp(.9rem, .5rem + 2vw, 1.4rem); align-items: center;
  }
  /* Sized off --panel-h, not `height: 100%`: the row above is content-sized,
     so a percentage height resolved to `auto` and the frame took the photo's
     own proportions — about 100px taller than the panel, painting over the
     card underneath and shoving the caption off the right edge. */
  .figure-sticky__frame {
    height: calc(var(--panel-h) - var(--panel-pad) * 2);
    width: auto; aspect-ratio: 4/5;
    border-radius: var(--radius); box-shadow: var(--shadow);
  }
  .figure-sticky__veil { display: none; }
  .figure-sticky__cap {
    position: static; padding: 0; color: var(--ink);
    align-self: center; text-align: start;
    min-width: 0;                /* let the caption wrap rather than overflow */
  }
  .figure-sticky__cap strong { font-size: 1rem; margin-bottom: .3rem; }
  .figure-sticky__cap span { font-size: .82rem; color: var(--muted); line-height: 1.5; }
}

/* ---------- Scene 3: pinned horizontal track ---------- */
.pin { position: relative; }
.pin__stage {
  position: sticky; top: var(--header-h);
  height: calc(100dvh - var(--header-h));
  display: flex; flex-direction: column; justify-content: center;
  overflow: hidden;
}
.pin__head { width: min(100% - (var(--gutter)*2), 1180px); margin-inline: auto; margin-bottom: clamp(.9rem, .6rem + 1vw, 1.6rem); }
.pin__head .section-head { margin-bottom: 0; }
.pin__head h2 { font-size: var(--step-3); }
/* `flex: none` stops the column layout from shrinking the track and
   clipping the bottom of every card. */
.pin__viewport { overflow: hidden; flex: 0 0 auto; }
.pin__track {
  display: flex; gap: clamp(1rem, .6rem + 1.4vw, 1.75rem);
  padding-inline: max(var(--gutter), calc((100vw - 1180px) / 2));
  will-change: transform;
}
.svc {
  flex: 0 0 clamp(276px, 29vw, 392px);
  background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--radius-lg);
  padding: clamp(1.35rem, 1.1rem + .9vw, 1.85rem);
  display: flex; flex-direction: column;
  transition: border-color .4s var(--ease), box-shadow .4s var(--ease), transform .4s var(--ease);
}
.svc:hover { border-color: var(--brand); box-shadow: var(--shadow); transform: translateY(-3px); }
.svc__no {
  font-family: var(--font-display); font-size: 2rem; line-height: 1;
  color: var(--brand-soft); margin-bottom: .55rem;
}
.svc__icon { width: 40px; height: 40px; border-radius: 12px; background: var(--brand-soft); color: var(--brand-dark); display: grid; place-items: center; margin-bottom: .9rem; }
.svc__icon svg { width: 21px; height: 21px; }
.svc h3 { font-size: var(--step-1); margin-bottom: .45em; }
.svc p { font-size: .92rem; }
.svc ul { margin-top: auto; padding-top: .95rem; display: grid; gap: .35rem; }
.svc li { position: relative; padding-inline-start: 1.05rem; font-size: .83rem; color: var(--muted); }
.svc li::before { content: ""; position: absolute; inset-inline-start: 0; top: .58em; width: 5px; height: 5px; border-radius: 50%; background: var(--brand); opacity: .55; }
.pin__hint {
  width: min(100% - (var(--gutter)*2), 1180px); margin: clamp(.9rem,.6rem+1vw,1.5rem) auto 0;
  display: flex; align-items: center; gap: .8rem;
  font-size: .74rem; letter-spacing: .12em; text-transform: uppercase; color: var(--muted);
}
.pin__hint-track { flex: 1; height: 2px; background: var(--line); border-radius: 2px; overflow: hidden; max-width: 220px; }
.pin__hint-bar { display: block; height: 100%; width: 100%; background: var(--brand); transform: scaleX(.2); transform-origin: 0 50%; transition: transform .12s linear; }

/* Fallback: no pinning — plain horizontal swipe track */
.pin.is-static { height: auto !important; }
.pin.is-static .pin__stage { position: static; height: auto; padding-block: var(--section-y); }
.pin.is-static .pin__viewport { overflow-x: auto; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; padding-bottom: 1rem; }
.pin.is-static .pin__track { transform: none !important; }
.pin.is-static .svc { scroll-snap-align: center; }
.pin.is-static .pin__hint-track { display: none; }

/* ---------- Scene 4: drawn path ---------- */
.path-scene { position: relative; }
/* .path-scene__sticky is only a hook for this scene's panel height now —
   stickiness comes from .scrolly__sticky, and a second `top` here left a
   gap under the header on phones. */
.path-svg { width: 100%; height: auto; overflow: visible; }

/* Horizontal three-phase stepper — phones only (see .path-mini rules below) */
.path-mini { display: none; }
@media (max-width: 900px) {
  .path-svg { display: none; }
  .path-mini {
    display: grid; grid-template-columns: repeat(3, 1fr);
    width: 100%; max-width: 420px; margin: 0; padding: 0; list-style: none;
    position: relative;
  }
  .path-mini::before {
    content: ""; position: absolute; left: 16%; right: 16%; top: 9px;
    height: 2px; background: var(--line);
  }
  .path-mini li {
    display: grid; justify-items: center; gap: .55rem; position: relative;
    font-size: .78rem; line-height: 1.3; text-align: center; color: var(--muted);
    transition: color .4s var(--ease);
  }
  .path-mini__dot {
    width: 20px; height: 20px; border-radius: 50%;
    border: 2px solid var(--line); background: var(--scene-bg, var(--bg));
    transition: background-color .4s var(--ease), border-color .4s var(--ease), transform .4s var(--ease);
  }
  .path-mini li.is-on { color: var(--ink); font-weight: 600; }
  .path-mini li.is-on .path-mini__dot { background: var(--brand); border-color: var(--brand); }
  .path-mini li.is-current .path-mini__dot { transform: scale(1.18); }
}
.path-svg .track { fill: none; stroke: var(--line); stroke-width: 2; }
.path-svg .draw {
  fill: none; stroke: var(--brand); stroke-width: 2.5; stroke-linecap: round;
  stroke-dasharray: var(--len); stroke-dashoffset: var(--len);
}
.path-svg .knot { fill: var(--bg); stroke: var(--line); stroke-width: 2; transition: fill .4s var(--ease), stroke .4s var(--ease), r .4s var(--ease); }
.path-svg .knot.is-on { fill: var(--brand); stroke: var(--brand); }
.path-svg .knot-label { font-family: var(--font-sans); font-size: 13px; fill: var(--muted); transition: fill .4s var(--ease); }
.path-svg .knot-label.is-on { fill: var(--ink); font-weight: 600; }

/* ---------- Parallax helpers ---------- */
[data-parallax] { will-change: transform; }

/* ---------- Word-by-word reveal ---------- */
.reveal-words span.w {
  display: inline-block; opacity: .16;
  transition: opacity .45s var(--ease), color .45s var(--ease);
}
.reveal-words span.w.is-on { opacity: 1; }

/* ---------- Counters ---------- */
.stat { display: grid; gap: .25rem; }
.stat__num { font-family: var(--font-display); font-size: var(--step-3); color: #fff; line-height: 1; }
.stat__lbl { font-size: .8rem; color: rgba(255,255,255,.6); }

/* ---------- Reduced motion / no-JS fallbacks ---------- */
@media (prefers-reduced-motion: reduce) {
  .scrolly__sticky, .path-scene__sticky, .pin__stage { position: static !important; height: auto !important; }
  .pin { height: auto !important; }
  .pin__viewport { overflow-x: auto; }
  .pin__track { transform: none !important; flex-wrap: wrap; justify-content: center; }
  .scrolly__step { min-height: auto; }
  .step-card, .constellation__node, .reveal-words span.w { opacity: 1 !important; transform: none !important; }
  .figure-sticky__cap .cap { position: static; opacity: 1; transform: none; }
  .figure-sticky__cap .cap + .cap { margin-top: .5rem; }
  .path-svg .draw { stroke-dashoffset: 0 !important; }
  .constellation__ring { animation: none; }
  .hero__cue-line::after { animation: none; }
  .rail { display: none; }
}
.no-js .scrolly__sticky, .no-js .path-scene__sticky { position: static; }
.no-js .pin { height: auto !important; }
.no-js .pin__stage { position: static; height: auto; }
.no-js .step-card, .no-js .constellation__node, .no-js .reveal { opacity: 1; transform: none; }
.no-js .path-svg .draw { stroke-dashoffset: 0; }
.no-js .figure-sticky__cap .cap { position: static; opacity: 1; transform: none; }

/* ---------- Interlude: full-bleed room, parallaxed ---------- */
.interlude {
  position: relative; isolation: isolate;
  height: clamp(380px, 62vh, 620px);
  display: grid; align-items: end;
  overflow: hidden;
}
.interlude__media { position: absolute; inset: 0; z-index: -1; overflow: hidden; }
.interlude__media img {
  width: 100%; height: 128%; object-fit: cover; object-position: 50% 42%;
  transform: translate3d(0, -11%, 0);
  will-change: transform;
}
.interlude__veil {
  position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(20,33,31,.80) 0%, rgba(20,33,31,.34) 46%, rgba(20,33,31,.10) 100%);
}
.interlude__body { padding-block: clamp(1.8rem, 1.2rem + 2vw, 3.2rem); color: #fff; }
.interlude__line {
  font-family: var(--font-display); font-variation-settings: "SOFT" 0, "WONK" 1, "opsz" 60;
  font-size: var(--step-4); line-height: 1.14; letter-spacing: -.015em;
  max-width: 18ch; margin: 0 0 .5rem; text-wrap: balance;
  text-shadow: 0 2px 24px rgba(20,33,31,.4);
}
.interlude__sub {
  margin: 0; font-size: .78rem; letter-spacing: .14em; text-transform: uppercase;
  color: rgba(255,255,255,.76);
}
@media (prefers-reduced-motion: reduce) {
  .interlude__media img { transform: none; height: 100%; }
}

/* ---------- Anchor offset under the sticky header ---------- */
:target, section[id], [id^="chi"], [id^="serv"] { scroll-margin-top: calc(var(--header-h) + 14px); }
#servizi { scroll-margin-top: 0; }
