/* ============================================================
   THE JOURNEY
   Scroll-scrubbed flight across India. Everything is namespaced
   `jr-` and scoped under #jr-journey so it cannot touch the rest
   of the page — `card` and `prog` already exist here.
   Reference build: journey-chain.html
============================================================ */
#jr-journey,
#jr-leg2,
.jr-extra-leg { position: relative; }           /* height set from JS = scroll budget */

.jr-stage {
  position: sticky; top: 0;
  height: 100vh; height: 100dvh;
  overflow: hidden; background: var(--navy);
}

/* One layer per clip, stacked. Each holds its own poster and video; the
   poster covers until that clip's first painted frame, which is also what
   stops iOS showing black. Layer opacity is what crossfades a seam. */
.jr-plate { position: absolute; inset: 0; }
.jr-layer { position: absolute; inset: 0; opacity: 0; }
.jr-layer img,
.jr-layer video {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.jr-layer img   { z-index: 1; }
.jr-layer video { z-index: 2; opacity: 0; }
.jr-layer.painted img   { opacity: 0; }
.jr-layer.painted video { opacity: 1; }

/* All of a stage's furniture lives in here so it can be faded as one.
   A stage that only half fills the viewport must not show its Counter, Rail
   or Escape: during a leg-to-leg handover two stages are on screen at once,
   and without this the outgoing leg's Card collides with the nav while the
   incoming leg's chrome floats in mid-screen. Card opacity nests inside and
   multiplies naturally. */
.jr-chrome {
  position: absolute; inset: 0; z-index: 5;
  pointer-events: none;
}
.jr-chrome .jr-escape { pointer-events: auto; }
.jr-chrome.off { visibility: hidden; }   /* so a faded Escape is not still clickable */

/* Legibility darkening for the Card. Fades in and out WITH the Card, so the
   picture is never dimmed while the picture is the subject. */
.jr-scrim {
  position: absolute; inset: 0; z-index: 3; pointer-events: none; opacity: 0;
  /* Neutral (not navy) and lighter than before — the old navy read as a blue
     slab. Just enough darkening to keep the bigger, bolder Card readable over
     a bright, busy photo; the bigger type does the rest of the work. */
  background:
    linear-gradient(to right, rgba(0,0,0,.60) 0%, rgba(0,0,0,.33) 26%,
                              rgba(0,0,0,.08) 46%, transparent 60%),
    linear-gradient(to top,   rgba(0,0,0,.40) 0%, rgba(0,0,0,.06) 34%, transparent 50%);
}
/* permanent, very light vignette so the Escape always reads */
.jr-vignette {
  position: absolute; inset: 0; z-index: 3; pointer-events: none;
  background:
    linear-gradient(to bottom, rgba(17,29,64,.40) 0%, transparent 13%),
    linear-gradient(to top,    rgba(17,29,64,.32) 0%, transparent 11%);
}

/* ---- The Card — bottom-left. Helvetica (matches the page), no week chip,
   text 30% larger, bullets marked with white squares. ---- */
.jr-card {
  position: absolute; left: var(--gutter); z-index: 5;
  /* The last line's baseline sits 10px above the Card's bottom edge, so the text
     is as far from the bottom of the window as from its left (Martin, 2026-10-22). */
  bottom: calc(var(--gutter) - 10px + env(safe-area-inset-bottom));
  width: min(680px, 56vw); opacity: 0; pointer-events: none;
  font-family: Helvetica, 'Helvetica Neue', Arial, sans-serif;
}
.jr-city {
  font-size: clamp(3.65rem, 7.5vw, 6.5rem); font-weight: 900; line-height: .94;
  letter-spacing: -.03em; color: var(--white);
  margin-bottom: 28px;                           /* sits where the "Dag n–m" line was (removed, Martin 2026-10-05) */
  text-shadow: 0 2px 30px rgba(0,0,0,.5);
}
.jr-list { list-style: none; display: flex; flex-direction: column; gap: 17px; }
.jr-list li {
  position: relative; padding-left: 30px; font-size: 24px; line-height: 1.5;
  font-weight: 700;                               /* bold, to match the heavy header */
  color: var(--white); text-shadow: 0 1px 3px rgba(0,0,0,.85), 0 2px 22px rgba(0,0,0,.7);
}
.jr-list li::before {
  content: ''; position: absolute; left: 0; top: .5em;
  width: 10px; height: 10px; background: var(--white);
}

/* ---- The Rail — one fixed element for the whole journey ----
   Fixed to the viewport (like the Escape) so it never fades between legs.
   Faded in whenever any leg is meaningfully on screen. The Counter that used
   to sit top-left is gone by design. */
.jr-rail-global {
  position: fixed; right: var(--gutter); top: 50%; transform: translateY(-50%); z-index: var(--z-journey-chrome);
  display: flex; flex-direction: column; gap: 14px;
  opacity: 0; pointer-events: none; visibility: hidden;
  /* visibility waits out the fade, so a hidden Rail is neither clickable nor focusable */
  transition: opacity .25s ease, visibility 0s linear .25s;
}
.jr-rail-global.on { opacity: 1; visibility: visible; transition-delay: 0s; }
/* each city is one button — label and dot together are the click target */
.jr-rail-item {
  position: relative; z-index: 1;                 /* above the Thread */
  display: flex; align-items: center; gap: 10px; justify-content: flex-end;
  margin: 0; padding: 0; border: 0; background: none; font: inherit;
  cursor: pointer; pointer-events: auto;
}
.jr-rail-lbl {
  font-family: Helvetica, 'Helvetica Neue', Arial, sans-serif;  /* same as the city header */
  font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: rgba(255,255,255,.6); background: rgba(17,29,64,.6); padding: 5px 8px; border-radius: 6px;
  backdrop-filter: blur(6px); white-space: nowrap;
  transition: color .2s ease, background .2s ease;
}
.jr-rail-dot {
  width: 8px; height: 8px; border-radius: 50%; background: rgba(255,255,255,.5);
  box-shadow: 0 0 0 2px rgba(17,29,64,.55);
  transition: transform .2s ease, background .2s ease;
}
.jr-rail-item:hover .jr-rail-lbl,
.jr-rail-item:focus-visible .jr-rail-lbl { color: var(--white); background: rgba(17,29,64,.9); }
.jr-rail-item:focus-visible { outline: 2px solid var(--red); outline-offset: 3px; }
.jr-rail-item.visited .jr-rail-dot { background: var(--red); }   /* flight has passed */
.jr-rail-item.on .jr-rail-lbl { color: var(--white); }
.jr-rail-item.on .jr-rail-dot { background: var(--red); transform: scale(1.45); }

/* The Thread — the red route line down the dots. The faint dashed base is
   the "intention line" ahead; the solid red fill is drawn behind you and
   grows as the flight descends through the journey. Its position and length
   are set from script to the measured dot centres so it always hits them. */
.jr-thread {
  position: absolute; width: 2px; z-index: 0; transform: translateX(-50%);
  background-image: linear-gradient(rgba(255,255,255,.30) 55%, transparent 0);
  background-size: 2px 7px;                        /* dash, gap */
}
.jr-thread-fill {
  position: absolute; left: 0; top: 0; width: 100%; height: 0;
  background: var(--red);
}

/* ---- The Escape — bottom-right. Mandatory, never hidden. ---- */
.jr-escape {
  position: absolute; right: var(--gutter); z-index: 7;
  bottom: calc(26px + env(safe-area-inset-bottom));
  font-size: 19px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; line-height: 1.2;
  color: rgba(255,255,255,.72); background: rgba(17,29,64,.55); padding: 4px 9px; border-radius: var(--radius-btn);
  text-decoration: none; backdrop-filter: blur(6px);
}
.jr-escape:hover, .jr-escape:focus { color: var(--white); background: var(--red); outline: none; }

/* One Escape for the whole journey, not one per leg. The spec calls it
   persistent and never hidden, and a per-stage copy disappears during a
   leg-to-leg handover — there is a stretch where the outgoing stage has
   faded and the incoming one has not arrived. Fixed to the viewport, shown
   whenever any leg is meaningfully on screen. */
.jr-escape-global {
  position: fixed; right: var(--gutter); z-index: var(--z-journey-chrome);
  bottom: calc(26px + env(safe-area-inset-bottom));
  opacity: 0; pointer-events: none; visibility: hidden;
  transition: opacity 0.25s ease, visibility 0s linear 0.25s;
}
.jr-escape-global.on { opacity: 1; pointer-events: auto; visibility: visible; transition-delay: 0s; }

@media (prefers-reduced-motion: reduce) {
  /* In flow, centred directly under the intro heading as a small outlined
     button (pulled up into the intro's bottom padding; z-index lifts it
     above the intro's white background). The id beats the generic
     reduced-motion .jr-escape rule further down. */
  #jr-escape.jr-escape-global {
    position: relative; z-index: 4; right: auto; bottom: auto;
    opacity: 1; pointer-events: auto; visibility: visible;
    display: block; width: fit-content;
    margin: calc(var(--space-2) - var(--space-6)) auto var(--space-5);
    color: var(--navy); background: transparent; backdrop-filter: none;
    border: 1.5px solid var(--navy); border-radius: var(--radius-btn);
  }
  #jr-escape.jr-escape-global:hover,
  #jr-escape.jr-escape-global:focus-visible { color: var(--white); background: var(--red); border-color: var(--red); }
}

.jr-prog { position: absolute; left: 0; bottom: 0; height: 3px; background: var(--red); z-index: 8; width: 0; }

.jr-loading {
  position: absolute; inset: 0; z-index: 9;
  display: flex; align-items: center; justify-content: center;
  background: var(--navy); color: rgba(255,255,255,.6);
  font-size: 11px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
}
.jr-loading.gone { display: none; }

/* diagnostics, only with ?diag=1 */
.jr-diag {
  position: absolute; top: 84px; right: 5vw; z-index: 6; pointer-events: none;
  font: 700 10px/1.6 ui-monospace, Menlo, monospace; letter-spacing: .06em;
  color: rgba(255,255,255,.8); background: rgba(17,29,64,.55); padding: 6px 9px;
  backdrop-filter: blur(6px); display: none;
}
.jr-diag.show { display: block; }

@media (max-width: 900px) {
  .jr-card { width: min(430px, 78vw); bottom: calc(18vh + env(safe-area-inset-bottom)); }
  .jr-city { font-size: clamp(2.5rem, 12vw, 3.65rem); }   /* "Ranthambore" fits the card at 360px */
  .jr-rail-global { display: none; }
}
/* Phones in landscape: a wider, smaller Card so it clears the nav. */
@media (orientation: landscape) and (max-height: 500px) {
  .jr-card { width: min(600px, 72vw); bottom: calc(14vh + env(safe-area-inset-bottom)); }
  .jr-city { font-size: clamp(2rem, 12vh, 3rem); margin-bottom: 12px; }
  .jr-list { gap: 6px; }
  .jr-list li { font-size: 16px; padding-left: 22px; }
  .jr-list li::before { width: 8px; height: 8px; }
}

@media (prefers-reduced-motion: reduce) {
  #jr-leg2, .jr-extra-leg { height: auto !important; }
}

/* Reduced motion: the journey becomes composed stills, scrolled normally.
   A deliberate alternative, not a broken animation. */
@media (prefers-reduced-motion: reduce) {
  #jr-journey { height: auto !important; }
  .jr-stage { position: static; height: auto; }
  .jr-plate { position: relative; }
  .jr-layer { position: relative; height: 76vh; opacity: 1 !important; }
  .jr-layer video { display: none; }
  .jr-layer img { opacity: 1 !important; }
  .jr-card {
    position: relative; left: auto; bottom: auto; opacity: 1 !important;
    width: auto; max-width: 820px; margin: 28px auto 0; padding: 0 6vw;
  }
  /* the stage's dark fill would sit behind the now-static Card: drop it so
     the navy type reads on the page's white */
  .jr-stage { background: transparent; padding-bottom: var(--space-6); }
  .jr-city, .jr-list li { color: var(--navy); text-shadow: none; }
  .jr-list li::before { background: var(--red); }
  /* the stage goes static here, so the chrome must stop being absolute or it
     would position against an ancestor further up and float off */
  .jr-chrome { position: static; opacity: 1 !important; visibility: visible !important; }
  .jr-scrim, .jr-vignette, .jr-rail-global, .jr-prog, .jr-diag { display: none; }
  .jr-escape {
    position: relative; right: auto; bottom: auto; display: inline-block;
    margin: 24px 0 0 6vw; color: var(--white); background: var(--navy);
  }
}

/* ============================================================
   PHONES: NO JOURNEY
   Martin, 2026-10-22: phones skip the scrolling journey entirely, so
   the pillars run straight into the partners. Same query as
   window.iipPhone in core.js, which also keeps the clips from preloading;
   hidden sections never trigger their own lazy loaders either.
============================================================ */
@media (max-width: 760px), (orientation: landscape) and (max-height: 500px) {
  #si-intro, #jr-escape, #jr-journey, #jr-leg2, .jr-extra-leg, .jr-rail-global { display: none !important; }
}
