/* The entrance sequence. Tokens (--void, --starlight, --haze, --faint,
   --vein, --font) come from hero.css. The nav is white / black / red:
   white letters, black ground, the red vein for the frame and every
   hover cue. Nothing warm — no gold, no ember.

   .hero is position:fixed (see hero.css) so its canvas keeps rendering as a
   backdrop the whole way down. Everything here scrolls OVER it — nothing in
   this file has its own background, the fixed canvas shows through until
   the scrim (below) darkens it. */

/* Reserves the hero's first screen (it's fixed, takes no flow space).
   plain `vh`: an `svh` here has collapsed to 0 in the wild. */
.hero-spacer { height: 100vh; }

/* Scroll snap — ONLY the motto beat is a full stop. Everything else (the
   hero, the wordmark, the nav) scrolls freely. `proximity` means nothing
   is forced except the one target that also carries `scroll-snap-stop:
   always` — the motto — which you can't fling past: you land on the quote,
   read it, scroll again to carry on. Disabled for reduced-motion. */
html {
  scroll-snap-type: y proximity;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-snap-type: none; }
}

.entrance {
  position: relative;
  z-index: 1;
  color: var(--starlight);
}

/* Darkens progressively as you scroll, independent of the sky's own grade
   shift — keeps the motto/mark/paths legible over whatever the canvas is
   showing without hiding it outright. Driven by entrance.js (--scrim-a). */
.entrance__scrim {
  position: fixed;
  inset: 0;
  z-index: 0;
  background: var(--void);
  opacity: var(--scrim-a, 0);
  pointer-events: none;
}

.entrance__motto-wrap {
  position: relative;
  height: 100vh;
  scroll-snap-align: center;
  scroll-snap-stop: always;
}
.entrance__motto {
  height: 100%;
  display: flex;
  flex-direction: column;
  /* Up and to the left — the ronin stands dead centre, so the motto sits in
     the dark quarter beside the gate rather than across him. */
  justify-content: flex-start;
  align-items: flex-start;
  gap: 0.35rem;
  padding: 24vh clamp(1.5rem, 6vw, 6rem) 0 clamp(1.75rem, 7vw, 8.5rem);
  /* Hidden until the beat scrolls into view (entrance.js adds .is-visible via
     IntersectionObserver) — stops the ghost text peeking on the hero. */
  opacity: 0;
  transition: opacity 700ms ease;
}
.entrance__motto.is-visible { opacity: 1; }
/* The ink writes itself on once the beat is reached — it's not scrubbed by
   scroll any more (the snap means there's no slow scroll-through to scrub
   with). Second line trails the first. */
.entrance__motto .ink-stroke {
  transition: stroke-dashoffset 1100ms cubic-bezier(0.45, 0, 0.15, 1);
}
.entrance__motto.is-visible .ink-stroke { stroke-dashoffset: 0; }
.entrance__motto.is-visible .ink-line:last-of-type .ink-stroke {
  transition-delay: 360ms;
}
@media (prefers-reduced-motion: reduce) {
  .entrance__motto { opacity: 1; transition: none; }
  .entrance__motto .ink-stroke { transition: none; stroke-dashoffset: 0; }
}

.ink-line {
  width: min(50vw, 540px);
  height: auto;
  overflow: visible;
  /* The sky behind this runs from a deep violet to a pale dawn as you
     scroll — the words have to hold over both, so they carry their own
     shadow rather than relying on the scrim alone. */
  filter: drop-shadow(0 2px 18px rgba(0, 0, 0, 0.8));
}
.ink-line + .ink-line { margin-left: clamp(1rem, 3vw, 2.25rem); }  /* second line steps in */

.ink-text {
  font: 300 clamp(2rem, 5vw, 3.8rem) var(--font);
  fill: var(--starlight);
}
.ink-text--ghost { fill: var(--starlight); opacity: 0.06; }

.ink-stroke {
  fill: none;
  stroke: #fff;
  stroke-width: 140;
  stroke-linecap: round;
  stroke-dasharray: 1400;
  stroke-dashoffset: 1400; /* animated by entrance.js */
}

/* Everything after the motto is plain sequential flow, each block getting
   its own full screen-height of space — no more than one of these is ever
   competing for the same pixels at the same time. */
.entrance__mark,
.entrance__gate {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 900ms cubic-bezier(0.4, 0, 0.2, 1),
              transform 900ms cubic-bezier(0.4, 0, 0.2, 1);
}
/* Legible over the full grade range — the paths still carry text. */
.entrance__gate {
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6), 0 2px 16px rgba(0, 0, 0, 0.55);
}
.entrance__mark {
  align-items: center;
  text-align: center;
  /* lift it off dead centre so SOFTWORKS clears the ronin's helm */
  padding: 0 clamp(1.5rem, 6vw, 6rem) 12vh;
}
.entrance__mark.is-visible,
.entrance__gate.is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* The wordmark — her hand-set logo, keyed to white-on-transparent so it
   sits straight on the ember sky. Its own drop-shadow does the job the
   text-shadow used to: a tight contact edge plus one soft pass. */
.entrance__mark .mark__logo {
  display: block;
  width: clamp(15rem, 44vw, 31rem);
  height: auto;
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.5))
          drop-shadow(0 2px 16px rgba(0, 0, 0, 0.42));
}

/* The path nav — the site's main navigation, and the last beat of the
   entrance. A vertical index in the dark left quarter (the ronin stands
   dead centre; the motto sat here too, so the sequence bookends left →
   centre → left). Each room is a line drawn out of a doorframe rule. */
.entrance__gate {
  position: relative;
  align-items: flex-start;
  padding: 0 clamp(1.5rem, 8vw, 5rem) 0 clamp(1.75rem, 7vw, 8.5rem);
}
/* A soft pool of shade behind the column — the sky is at its palest "dawn"
   here, so the links need it to stay readable without darkening the frame. */
.entrance__gate::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  width: min(80vw, 560px);
  height: min(64vh, 460px);
  transform: translateY(-50%);
  background: radial-gradient(ellipse 70% 60% at 32% 50%,
              rgba(5, 6, 12, 0.66), rgba(5, 6, 12, 0) 74%);
  pointer-events: none;
  z-index: -1;
}

.paths {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: clamp(0.6rem, 1.7vh, 1.15rem);
  padding-left: 1.5rem;
}
/* the doorframe — a hairline the paths are cut into */
.paths::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.15rem;
  bottom: 0.15rem;
  width: 2px;
  background: linear-gradient(rgba(200, 30, 42, 0) 0%,
              rgba(200, 30, 42, 0.55) 14%, rgba(200, 30, 42, 0.55) 86%,
              rgba(200, 30, 42, 0) 100%);
}

.paths__item {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  text-decoration: none;
  color: var(--starlight);
  padding: 0.15rem 0;
}
.paths__num {
  flex: none;
  width: 1.35rem;
  font: 400 0.72rem var(--font);
  letter-spacing: 0.08em;
  color: #FFFFFF;
  text-align: right;
}
.paths__rule {
  flex: none;
  align-self: center;
  width: 1.4rem;
  height: 2px;
  background: rgba(200, 30, 42, 0.55);
  transition: width 320ms cubic-bezier(0.4, 0, 0.2, 1), background-color 280ms ease;
}
.paths__name {
  font: 400 clamp(1.15rem, 1.9vw, 1.5rem) var(--font);
  letter-spacing: 0.005em;
  color: #FFFFFF;
  transition: letter-spacing 320ms ease;
}

.paths__item:hover .paths__name,
.paths__item:focus-visible .paths__name {
  letter-spacing: 0.03em;
}
.paths__item:hover .paths__rule,
.paths__item:focus-visible .paths__rule {
  width: 2.7rem;
  background: var(--vein);
}
.paths__item:focus-visible { outline: none; }

/* The scroll cue — same face as the seal (Newsreader, sentence case, a hair
   of tracking that opens on hover), sat over the still hero. Hidden by
   default; entrance.js adds .is-visible after a few seconds of no scroll
   and removes it the instant one happens. A real <button> so it's a click
   target too, not just a hint. */
.scroll-cue {
  position: fixed;
  left: 50%;
  bottom: clamp(1.6rem, 4vh, 3rem);
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.55rem;
  background: none;
  border: none;
  padding: 0.4rem;
  margin: 0;
  cursor: pointer;
  color: #FFFFFF;
  opacity: 0;
  pointer-events: none;
  transform: translateX(-50%);
  transition: opacity 1100ms ease;
  -webkit-tap-highlight-color: transparent;
}
.scroll-cue.is-visible {
  opacity: 1;
  pointer-events: auto;
}
.scroll-cue__label {
  font: 400 1.02rem/1 var(--font);
  letter-spacing: 0.01em;
  white-space: nowrap;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.85);
  transition: letter-spacing 320ms ease;
}
.scroll-cue__arrow {
  width: 1.15rem;
  height: 1.15rem;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  fill: none;
  filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.8));
  animation: scroll-cue-drift 2.4s ease-in-out infinite;
}
.scroll-cue:hover .scroll-cue__label,
.scroll-cue:focus-visible .scroll-cue__label { letter-spacing: 0.05em; }
.scroll-cue:focus-visible { outline: none; }

@keyframes scroll-cue-drift {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(5px); }
}

@media (prefers-reduced-motion: reduce) {
  .entrance__mark, .entrance__gate { opacity: 1; transform: none; transition: none; }
  .paths__rule, .paths__name, .paths__num { transition: none; }
  .ink-stroke { stroke-dashoffset: 0; }
  .scroll-cue { transition: opacity 300ms ease; }
  .scroll-cue__arrow { animation: none; }
}
