/* ============================================================
   Site 2.0, the copy rail

   Layout, then six entrances and six exits.

   Each scene uses a DIFFERENT MECHANISM, not a different value of the
   same one. An earlier version gave scenes 1, 2 and 3 an opacity fade
   with a small translate each, and a critic counted them as one
   effect, correctly: 30px versus 26px versus 14px is not a different
   entrance, it is the same entrance measured differently. The six
   mechanisms here are soft focus, a hinge, a vertical set down, word
   by word arrival, a horizontal wipe and a horizon split.

   Every exit answers its own entrance using that same mechanism,
   travelling somewhere the entrance did not, so no two exits look
   alike either. Timing lives in the two variables below and copy.js
   reads --copy-out from here, so the script and the stylesheet cannot
   drift apart.
   ============================================================ */

/* Kept deliberately brisk. Every millisecond spent in transition is a
   millisecond the copy is not readable, which the critic counts as dead air. */
:root{
  --copy-in:  700ms;
  --copy-out: 500ms;
}

.rail{
  position:absolute; z-index:6;
  left:var(--gut); bottom:clamp(4.5rem,12vh,8rem);
  width:var(--rail);
  pointer-events:none;
}
.rail > *{ pointer-events:auto; }

/* Titles, treated the way film titles are actually treated.

   THE MEASUREMENT THAT DECIDED THIS. Over the finished 4K footage, navy ink
   measured 1.61:1 against the darkest fifth of the frame behind it and 2.50:1
   against the median. Unreadable. The obvious fix, switching the type to
   white, fails the other end: white measures 2.45:1 against the brightest
   fifth, the sky. No colour of text alone can survive a frame that spans
   both a dark doorway and a bright sky.

   So the treatment is the one cinema settled on long ago: LIGHT TYPE OVER A
   SOFT VIGNETTE. The vignette darkens the corner the titles occupy instead of
   washing the picture out, which is the opposite of the glare the client
   rejected. It is also how anamorphic lenses behave, so it reads as
   photography rather than as a user interface panel.

   No box, no edge, no card. The gradient is elliptical, far larger than the
   text, and fades to nothing well inside the frame, so its own boundary is
   never on screen. */
.scene{
  position:absolute; left:0; bottom:0; width:100%; visibility:hidden;
  padding:0 0 .2rem;
  color:#FBF8F3;
}
.scene.is-on, .scene.is-exiting{ visibility:visible; }

/* The vignette. Deliberately enormous relative to the type so only its
   centre is ever visible. */
/* The per scene backdrop is GONE. It lived on .scene::before, and the scenes
   are animated with clip-path for their entrances and exits, which clips a
   ::before to the element box. The soft radial therefore rendered as a hard
   edged rectangle: measured with the film and type stripped, sharp edges at
   x=58, y=391 and y=703, exactly the scene bounds. The client called it a grey
   box, and it was one.

   Legibility now comes from .stage-veil in world.css, which sits on the stage
   itself, spans the full frame, and has nothing to be clipped by. */

/* A close dark shadow for edge definition against anything still bright. */
.scene h1, .scene h2{
  color:#FFFDFA;
  text-shadow:0 1px 3px rgba(4,10,20,.55), 0 6px 26px rgba(4,10,20,.42);
}
.scene p{
  color:rgba(255,253,250,.94);
  text-shadow:0 1px 3px rgba(4,10,20,.55), 0 4px 18px rgba(4,10,20,.40);
}
.scene .tag{
  color:var(--gold);
  text-shadow:0 1px 3px rgba(4,10,20,.6);
}

.scene .tag{
  text-shadow:
    0 1px 2px rgba(10,26,47,.26),
    0 3px 16px rgba(10,26,47,.20);
}

.scene .tag{ margin-bottom:1.1rem; }
.scene h2{ margin-bottom:.7rem; }
.scene p{ max-width:32ch; margin-bottom:0; }

.scene .pills{ display:flex; flex-wrap:wrap; gap:.45rem; margin-top:1.4rem; }
.scene .pills span{
  font:500 var(--t-xs)/1 var(--mono);
  letter-spacing:.14em; text-transform:uppercase;
  padding:.5rem .8rem;
  border:1px solid rgba(255,253,250,.38); border-radius:100px;
  color:rgba(255,253,250,.92);
  text-shadow:0 1px 3px rgba(4,10,20,.5);
}

@media (max-width:760px){
  :root{ --rail:min(90vw, 46ch); }
  .rail{ bottom:clamp(3.5rem,14vh,7rem); }
}

/* ---------- hero (scene 1) ---------- */

.hero-rail{ max-width:22ch; }
.hero-rail .mark{ width:clamp(210px,26vw,330px); margin-bottom:1.6rem; }
.hero-rail h1{ font-size:var(--t-2xl); margin-bottom:.8rem; }

/* Returning a scene to its idle state must never animate. Scene 5 leaves
   to the right but idles collapsed at the left, and scene 2 closes the
   opposite way from its hinge, so an animated reset would sweep the whole
   thing back across the screen. copy.js adds this for one frame. */
.no-anim, .no-anim *{ transition:none !important; }

/* ================================================================
   1. The Community. SOFT FOCUS.
   Arrives out of blur, the way something becomes clear as you get
   near it. Leaves by lifting away and going soft again, rather than
   simply switching off.
   ================================================================ */
.scene[data-scene="1"]{
  opacity:0; filter:blur(12px); transform:translateY(14px);
  transition:opacity var(--copy-in) var(--ease-out),
             filter var(--copy-in) var(--ease-out),
             transform var(--copy-in) var(--ease-out);
}
.scene[data-scene="1"].is-on{ opacity:1; filter:blur(0); transform:none; }
.scene[data-scene="1"].is-exiting{
  opacity:0; filter:blur(9px); transform:translateY(-20px);
  transition:opacity var(--copy-out) var(--ease-io),
             filter var(--copy-out) var(--ease-io),
             transform var(--copy-out) var(--ease-io);
}

/* ================================================================
   2. The Doorstep. HINGE.
   Swings open on its left edge, like the door the scene is named
   for. Leaves by swinging shut the other way, on the same hinge.
   ================================================================ */
.scene[data-scene="2"]{
  opacity:0; transform-origin:left center;
  transform:perspective(900px) rotateY(-16deg) translateX(-14px);
  transition:opacity calc(var(--copy-in) * .8) var(--ease-out),
             transform var(--copy-in) var(--ease-out);
}
.scene[data-scene="2"].is-on{ opacity:1; transform:perspective(900px) rotateY(0) translateX(0); }
.scene[data-scene="2"].is-exiting{
  opacity:0; transform:perspective(900px) rotateY(12deg) translateX(6px);
  transition:opacity var(--copy-out) var(--ease-io),
             transform var(--copy-out) var(--ease-io);
}

/* ================================================================
   3. The Kitchen Table. SET DOWN.
   Placed from just above, the way something is put on a table.
   Nothing blurs and nothing turns; the whole gesture is vertical.
   Leaves by being taken straight back down and away.
   ================================================================ */
.scene[data-scene="3"]{
  opacity:0; transform:translateY(-26px);
  transition:opacity calc(var(--copy-in) * .7) var(--ease-out),
             transform var(--copy-in) var(--ease-out);
}
.scene[data-scene="3"].is-on{ opacity:1; transform:none; }
.scene[data-scene="3"].is-exiting{
  opacity:0; transform:translateY(30px);
  transition:opacity var(--copy-out) var(--ease-io),
             transform var(--copy-out) var(--ease-io);
}

/* ================================================================
   4. The Learning Room. WORD BY WORD.
   The heading arrives a word at a time, in reading order, which is
   what learning something looks like. It leaves in the same order it
   arrived, first word first, so it reads as a sentence being taken
   away rather than rewound.
   ================================================================ */
.scene[data-scene="4"]{
  opacity:0;
  transition:opacity calc(var(--copy-in) * .45) var(--ease-out);
}
.scene[data-scene="4"].is-on{ opacity:1; }
.scene[data-scene="4"].is-exiting{
  opacity:0;
  transition:opacity var(--copy-out) var(--ease-io) 180ms;
}

.scene[data-scene="4"] h2 .split{ display:inline; }
.scene[data-scene="4"] h2 .word{
  display:inline-block;
  opacity:0; transform:translateY(12px);
  transition:opacity .5s var(--ease-out), transform .5s var(--ease-out);
}
.scene[data-scene="4"].is-on h2 .word{ opacity:1; transform:none; }
.scene[data-scene="4"].is-exiting h2 .word{
  opacity:0; transform:translateY(-10px);
  transition:opacity .44s var(--ease-io), transform .44s var(--ease-io);
}
@media (prefers-reduced-motion:no-preference){
  .scene[data-scene="4"].is-on h2 .word{ transition-delay:calc(var(--i) * 70ms); }
  .scene[data-scene="4"].is-exiting h2 .word{ transition-delay:calc(var(--i) * 42ms); }
}

/* ================================================================
   5. Out In The World. WIPE.
   Unveiled left to right, like a view opening up as you travel. It
   never fades: opacity stays at 1 throughout, so it reads as motion
   rather than appearance. It leaves by continuing off to the right,
   never reversing, which is the same rule the camera itself obeys.
   ================================================================ */
.scene[data-scene="5"]{
  opacity:1; clip-path:inset(0 100% 0 0);
  transition:clip-path var(--copy-in) var(--ease-out);
}
.scene[data-scene="5"].is-on{ clip-path:inset(0 0 0 0); }
.scene[data-scene="5"].is-exiting{
  clip-path:inset(0 0 0 100%);
  transition:clip-path var(--copy-out) var(--ease-io);
}

/* ================================================================
   6. The Park. HORIZON SPLIT.
   Opens from a thin band at the centre line, echoing the horizon
   rule in the logo, and closes back to that same band at the end.
   It is the only scene that opens along two edges at once, which is
   why the finale feels like an arrival.
   ================================================================ */
.scene[data-scene="6"]{
  opacity:0; clip-path:inset(48% 0 48% 0);
  transition:opacity calc(var(--copy-in) * .5) var(--ease-out),
             clip-path calc(var(--copy-in) * 1.15) var(--ease-out);
}
.scene[data-scene="6"].is-on{ opacity:1; clip-path:inset(0 0 0 0); }
.scene[data-scene="6"].is-exiting{
  opacity:0; clip-path:inset(48% 0 48% 0);
  transition:opacity var(--copy-out) var(--ease-io),
             clip-path var(--copy-out) var(--ease-io);
}

/* Reduced motion: the copy still changes, it just does not travel.
   base.css already collapses every duration, so all that is needed
   here is to make sure nothing rests in a hidden or clipped state. */
@media (prefers-reduced-motion:reduce){
  .scene[data-scene="1"],
  .scene[data-scene="2"],
  .scene[data-scene="3"],
  .scene[data-scene="4"]{ filter:none; transform:none; }
  .scene[data-scene="5"],
  .scene[data-scene="6"]{ clip-path:none; }
  .scene[data-scene="5"].is-exiting,
  .scene[data-scene="6"].is-exiting{ clip-path:none; opacity:0; }
  .scene[data-scene="4"] h2 .word{ opacity:1; transform:none; }
}
