/* ==========================================================================
   journey.css — "The Full Journey" band on index.html only.
   Added 2026-09-14. Vanilla CSS, no build step, no dependencies.

   SCOPE
   -----
   Every selector in this file is namespaced `.journey-*`. Nothing here can
   reach any other block on the page, and no other page links this file.

   WHY THE DEFAULT STATE IS THE FINISHED STATE
   -------------------------------------------
   Nothing in this band starts at `opacity: 0` and waits for JS or for an
   animation to bring it in. All six steps, their labels, their brackets and
   the connecting line are fully painted by CSS alone. journey.js only adds a
   travelling highlight over the top of that.

   That single decision is what makes three separate requirements fall out for
   free rather than needing three separate fallbacks:
     - JS disabled  -> the band is complete and every link works;
     - reduced motion -> the band is complete, the travel just never runs;
     - no layout shift -> nothing moves in or out of flow at any point.

   REDUCED MOTION
   --------------
   motion-guard.css already crushes every animation-duration site-wide to
   0.01ms under prefers-reduced-motion. That alone would leave the ambient hum
   and the dashed energy flow snapping to their end frame rather than stopping,
   so this file ALSO declares its own guard that sets `animation: none` on the
   purely decorative loops. That is safe here, and only here, because — unlike
   the reveal patterns motion-guard.css was written to protect — none of these
   elements depends on an animation to become visible. journey.js makes the
   same check and never starts the travelling signal at all.

   CORNER BRACKETS
   ---------------
   The brackets are SVG strokes animated with stroke-dashoffset, not CSS
   borders. A border cannot be drawn on progressively, and four separately
   staggered borders on one box is not expressible at all.
   ========================================================================== */

.journey {
  position: relative;
  background: #0a1930;
  padding: 4.5rem 0 4rem;
  overflow: hidden;
  isolation: isolate;
}

.journey-inner {
  max-width: 78rem;
  margin-inline: auto;
  padding-inline: 1.5rem;
}

/* ---------- heading ---------- */

.journey-head { text-align: center; margin-bottom: 3rem; }

.journey-eyebrow {
  display: inline-block;
  margin-bottom: 1rem;
  padding: 6px 20px;
  border-radius: 50px;
  background: rgba(212, 168, 75, 0.12);
  color: #d4a84b;
  font-family: 'Montserrat', sans-serif;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 1px;
  text-transform: uppercase;
}

.journey-title {
  margin: 0 0 0.75rem;
  font-family: 'Playfair Display', serif;
  font-size: clamp(1.9rem, 3.6vw, 2.9rem);
  font-weight: 700;
  line-height: 1.15;
  color: #ffffff;
}

.journey-sub {
  max-width: 34rem;
  margin: 0 auto;
  font-family: 'Montserrat', sans-serif;
  font-size: 1.05rem;
  line-height: 1.6;
  color: #b0bec5;
}

/* ---------- track ---------- */

.journey-track { position: relative; }

/* The road sits behind the nodes and spans the full track. It is decorative:
   the ordered list below is what actually carries the sequence. */
.journey-road {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
  overflow: visible;
}

.journey-road-base {
  fill: none;
  stroke: rgba(212, 168, 75, 0.22);
  stroke-width: 2;
  stroke-linecap: round;
}

/* Ambient dashed "energy" drifting along the road at idle pace. */
.journey-road-flow {
  fill: none;
  stroke: rgba(225, 177, 104, 0.45);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-dasharray: 10 26;
  animation: journey-flow 9s linear infinite;
}

@keyframes journey-flow {
  from { stroke-dashoffset: 0; }
  to   { stroke-dashoffset: -72; }
}

/* The travelling signal. Hidden until journey.js arms it, because a static
   bright segment sitting on the road forever would read as a mistake. */
.journey-road-signal {
  fill: none;
  stroke: #f0a83c;
  stroke-width: 3.5;
  stroke-linecap: round;
  opacity: 0;
  filter: drop-shadow(0 0 6px rgba(240, 168, 60, 0.75));
}

.journey[data-journey-running="true"] .journey-road-signal { opacity: 1; }

/* ---------- the list of steps ---------- */

.journey-steps {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 1rem;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: journey;
}

.journey-step { counter-increment: journey; display: flex; }

/* Real anchor, real link text. Not a div with a click handler. */
.journey-node {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
  width: 100%;
  padding: 1.4rem 0.75rem 1.5rem;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.035);
  color: #ffffff;
  text-decoration: none;
  text-align: center;
  transition: background 0.35s ease, transform 0.35s ease;
}

.journey-node:hover,
.journey-node:focus-visible { background: rgba(255, 255, 255, 0.08); }

.journey-node:focus-visible {
  outline: 3px solid #f0a83c;
  outline-offset: 3px;
}

/* Soft inner glow. Ambient hum idles at ~15%; the lock pass takes it to full
   and eases back. `will-change` is set only while the node is locking. */
.journey-node::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 12px;
  pointer-events: none;
  background: radial-gradient(ellipse at 50% 45%, var(--journey-tint, rgba(240,168,60,0.55)) 0%, transparent 70%);
  opacity: 0.15;
  animation: journey-hum 6s ease-in-out infinite;
}

@keyframes journey-hum {
  0%, 100% { opacity: 0.10; }
  50%      { opacity: 0.20; }
}

.journey-node[data-journey-lock="true"] { will-change: transform; }
.journey-node[data-journey-lock="true"]::after {
  animation: journey-lock-glow 1.1s ease-out;
  will-change: opacity;
}

@keyframes journey-lock-glow {
  0%   { opacity: 0.15; }
  18%  { opacity: 0.85; }
  100% { opacity: 0.15; }
}

/* ---------- corner brackets ---------- */

/* Four separate 22x22 SVGs pinned to the four corners, rather than one
   stretched SVG. A single SVG scaled to the node would need
   preserveAspectRatio="none", which distorts the stroke width differently on
   each axis — visibly so on the wide 6-column layout. Fixed-size corners keep
   the stroke honest at every breakpoint. */
.journey-corner-box {
  position: absolute;
  width: 22px;
  height: 22px;
  overflow: visible;
  pointer-events: none;
}

.journey-corner-box--tl { top: -1px; left: -1px; }
.journey-corner-box--tr { top: -1px; right: -1px; transform: scaleX(-1); }
.journey-corner-box--br { bottom: -1px; right: -1px; transform: scale(-1); }
.journey-corner-box--bl { bottom: -1px; left: -1px; transform: scaleY(-1); }

.journey-corner {
  fill: none;
  stroke: var(--journey-stroke, #d4a84b);
  stroke-width: 1.5;
  stroke-linecap: square;
  /* Drawn in full by default: this is the static, no-JS, reduced-motion
     appearance. The lock pass re-draws them from nothing. The L is 11 + 11
     units long, so 24 clears it with a little room. */
  stroke-dasharray: 24;
  stroke-dashoffset: 0;
  opacity: 0.55;
}

.journey-node[data-journey-lock="true"] .journey-corner {
  animation: journey-draw 0.5s ease-out both;
  animation-delay: calc(var(--journey-c) * 0.09s + 0.1s);
  will-change: stroke-dashoffset;
}

@keyframes journey-draw {
  0%   { stroke-dashoffset: 24; opacity: 0.55; }
  60%  { opacity: 1; }
  100% { stroke-dashoffset: 0; opacity: 0.55; }
}

/* The impact flash at the entry corner — top-left on the horizontal layout. */
.journey-flash {
  position: absolute;
  top: -3px;
  left: -3px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #ffffff;
  opacity: 0;
  pointer-events: none;
}

.journey-node[data-journey-lock="true"] .journey-flash {
  animation: journey-flash 0.4s ease-out;
  will-change: opacity, transform;
}

@keyframes journey-flash {
  0%   { opacity: 0; transform: scale(0.4); }
  25%  { opacity: 0.95; transform: scale(1); }
  100% { opacity: 0; transform: scale(2.2); }
}

/* ---------- node contents ---------- */

.journey-index {
  font-family: 'Montserrat', sans-serif;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--journey-stroke, #d4a84b);
}

/* JS-free connector.

   journey.js draws the real road, because only measurement can put a path
   through six node centres across three different grid shapes. With JS off
   there is no road at all, and six unconnected boxes do not read as a journey.

   These two hairlines fix that without guessing any geometry: they hang off
   the icon itself, so they are always at exactly the height (or, stacked, the
   column) the road would have run through, at every breakpoint. They sit at
   z-index -1, behind each node's own background, so — like the SVG road —
   they show in the gaps between nodes and never cross a label.

   journey.js sets data-journey-road on the section the moment it has a real
   path, which retires these in favour of it. */
.journey-rail { position: relative; display: block; }

.journey-rail::before,
.journey-rail::after {
  content: '';
  position: absolute;
  top: 50%;
  width: 50vw;
  height: 1px;
  background: rgba(212, 168, 75, 0.22);
  z-index: -1;
  pointer-events: none;
}

.journey-rail::before { right: 50%; }
.journey-rail::after  { left: 50%; }

.journey[data-journey-road="true"] .journey-rail::before,
.journey[data-journey-road="true"] .journey-rail::after { display: none; }

/* Clips the hairlines to the band rather than letting 50vw run off-page. */
.journey-steps { overflow: hidden; }

.journey-icon { display: block; width: 34px; height: 34px; }
.journey-icon * { stroke: var(--journey-stroke, #d4a84b); }

.journey-label {
  font-family: 'Montserrat', sans-serif;
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1.3;
  color: #ffffff;
}

/* Micro-reveal. Reserved height, so revealing it shifts nothing. Only one can
   ever be open at a time because it is tied to :hover / :focus-visible on a
   single node. */
.journey-reveal {
  display: block;
  min-height: 1.15rem;
  font-family: 'Montserrat', sans-serif;
  font-size: 0.78rem;
  line-height: 1.15rem;
  color: #d4a84b;
  opacity: 0;
  transition: opacity 0.28s ease;
}

.journey-node:hover .journey-reveal,
.journey-node:focus-visible .journey-reveal { opacity: 1; }

/* ---------- category tints ---------- */
/* Warm gold for the venue-side steps, cooler blue for the digital step —
   the same two-family split the halves band above already uses. */

.journey-step--warm .journey-node { --journey-stroke: #d4a84b; --journey-tint: rgba(240,168,60,0.55); }
.journey-step--cool .journey-node { --journey-stroke: #7FB2E5; --journey-tint: rgba(127,178,229,0.5); }
.journey-step--cool .journey-reveal { color: #9CC6EE; }

/* ---------- breakpoints ---------- */

@media (max-width: 1100px) {
  .journey-steps { grid-template-columns: repeat(3, 1fr); gap: 1.25rem; }
}

@media (max-width: 720px) {
  .journey { padding: 3.5rem 0 3rem; }
  .journey-steps { grid-template-columns: 1fr; gap: 0.85rem; }
  .journey-node {
    flex-direction: row;
    align-items: center;
    gap: 0.9rem;
    text-align: left;
    padding: 1rem 1rem 1rem 1.1rem;
  }
  .journey-node > .journey-text { flex: 1; }
  .journey-index { min-width: 1.6rem; }
  /* Stacked: the connector runs down the icon rail, not across it. */
  .journey-rail::before,
  .journey-rail::after {
    top: auto;
    left: 50%;
    right: auto;
    width: 1px;
    height: 50vh;
  }
  .journey-rail::before { bottom: 50%; }
  .journey-rail::after  { top: 50%; }
  /* The reveal goes entirely on the stacked layout. Two reasons, and the
     second is the one that actually forced it: there is no hover on a touch
     device for it to respond to, and because the reveals are different
     lengths they wrap to different numbers of lines at this width — which
     made the six nodes 94px, 76px, 94px, 94px, 76px, 94px tall instead of one
     even stack. It is supplementary, aria-hidden text; the label and the link
     target are untouched. */
  .journey-reveal { display: none; }
}

/* ---------- reduced motion ---------- */
/* Safe here: nothing below is hidden at rest, so switching these off removes
   movement without removing content. See the header note. */

@media (prefers-reduced-motion: reduce) {
  .journey-road-flow,
  .journey-node::after,
  .journey-node[data-journey-lock="true"]::after,
  .journey-node[data-journey-lock="true"] .journey-corner,
  .journey-node[data-journey-lock="true"] .journey-flash {
    animation: none !important;
  }
  .journey-node::after { opacity: 0.15; }
  .journey-corner { stroke-dashoffset: 0 !important; }
  .journey-road-signal { opacity: 0 !important; }
  .journey-node { transition: none; }
  .journey-reveal { transition: none; }
}
