/* The world reflected in water. Everything here is the WATER, and nothing else on the site depends
   on it: delete this file, delete reflect.js, and drop data-role="reflect" from the markup, and the
   band falls back to an ordinary world band with no loose ends. That separation is deliberate,
   because if it does not convince as water we want to lift it out rather than unpick it.

   The frame maths for a reflected band stays in pageworld.js, behind the mode registry that
   reflect.js registers into, so the geometry lives where the rest of the geometry lives. */

.page-world[data-role="reflect"] .page-world-stack {
  bottom: auto;
  top: 0;
  /* flip, then shear. The shear is small on purpose: past about three degrees the buildings lean
     and it stops reading as water and starts reading as a mistake. */
  transform: translateX(-50%) scaleY(-1) skewX(-2.1deg);
  transform-origin: 50% 50%;
  /* dimmer and less saturated than the thing it reflects, which is true of every real reflection */
  filter: brightness(0.80) saturate(0.74) contrast(0.96);
}

/* The band no longer fades in at the top: the top edge IS the water surface and it has to be a
   hard, deliberate line. It still leaves at zero into the section below. */
.page-world[data-role="reflect"] {
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 74%, rgba(0,0,0,0) 100%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 74%, rgba(0,0,0,0) 100%);
}

/* THE WATERLINE. The single thing that decides whether a stranger sees water or an upside-down
   picture: a surface for the reflection to be reflecting FROM, with the reflected horizon meeting
   it. A thin lit line, a short bright wash under it where the surface catches light, and a soft
   glow above it so the surface has thickness rather than being a drawn rule. */
.page-world[data-role="reflect"] + .pw-waterline,
.page-world[data-role="reflect"] .pw-waterline,
.pw-waterline {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  /* 74px tall with the lit line at its middle put the surface ON TOP of the reflected city, which
     is the one part of the painting a viewer can actually recognise. The line sits at the very top
     now and everything below it is a short falloff. */
  height: 46px;
  /* above every plane. The planes carry an inline z-index of 1..3, so a surface at 2 was being
     painted under the nearest one and the crest simply never appeared. */
  z-index: 9;
  pointer-events: none;
  /* The lit line is the whole point, so it is a real line: a hard 2px crest with light spilling a
     little way down into the water and nothing above it. Weak, this reads as the top of a picture;
     strong, it reads as a surface the picture is sitting under. */
  background:
    linear-gradient(to bottom,
      rgba(255, 245, 228, 0.94) 0px,
      rgba(255, 245, 228, 0.94) 2px,
      rgba(255, 226, 190, 0.55) 4px,
      rgba(210, 226, 255, 0.30) 10px,
      rgba(150, 190, 255, 0.14) 22px,
      rgba(120, 170, 255, 0) 46px);
  -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 9%, #000 91%, transparent 100%);
  mask-image: linear-gradient(to right, transparent 0%, #000 9%, #000 91%, transparent 100%);
}

/* THE SURFACE. This used to be a repeating-linear-gradient, which is by definition even pitch,
   full width and uniform from top to bottom: a scanline generator. Two people read it as
   interference rather than ripple, and they were reading exactly what it was. It is now drawn once
   into a canvas by reflect.js, with broken crests, summed octaves at unrelated frequencies,
   wavelength compressing toward the waterline, and specular glints. See surface() there. */
.pw-surface {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  z-index: 8;
  pointer-events: none;
  /* A 22% ramp at the top hid the surface exactly where the crests are most compressed, which is
     the perspective cue itself. It fades in fast now and only the far end dissolves. */
  -webkit-mask-image: linear-gradient(to bottom, rgba(0,0,0,0) 0%, #000 7%, #000 80%, rgba(0,0,0,0) 100%);
  mask-image: linear-gradient(to bottom, rgba(0,0,0,0) 0%, #000 7%, #000 80%, rgba(0,0,0,0) 100%);
}

/* Static water reads as texture, so the surface drifts, very slowly, and ONLY while the band is on
   screen: a page nobody is looking at does no work. The canvas is drawn taller than the band so the
   drift never exposes an edge. */
.pw-surface.is-adrift { animation: pwDrift 34s linear infinite; }

@keyframes pwDrift {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(0, var(--pw-drift, -60px), 0); }
}

html[data-motion="still"] .pw-surface.is-adrift,
.pw-surface.is-adrift[data-static] { animation: none; }

@media (prefers-reduced-motion: reduce) {
  .pw-surface.is-adrift { animation: none; }
}

html[data-motion="still"] .page-world[data-role="reflect"] .page-world-stack {
  filter: brightness(0.80) saturate(0.74) contrast(0.96);
}

/* ---------- Deep water ----------
   The judgement call Echo asked for: the stretch between the route and the architecture cards is a
   GAP, not restraint. Act 2 says the world does not end, and it currently ends in the middle and
   comes back at the foot, which is the same complaint as two screens of identical hero, just in
   reverse.

   But the fix is not more painting there. The route has to read without competition, and a lit
   valley behind four cards is competition. Once act 2 is water, the water is the answer: it carries
   on underneath, dark and almost featureless, so the ground is continuous from the hero to the foot
   and the route is crossing something rather than floating on flat colour.

   No image, no extra bytes: a depth wash and the same surface streaks, at a level low enough that
   the cards and the route stay the brightest things in the section. */
[data-water="deep"] { position: relative; }

[data-water="deep"]::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  /* depth only. The surface itself is the same generated canvas the reflection uses, added by
     reflect.js, so the two cannot drift apart and the ripple is improved once rather than twice. */
  background:
    linear-gradient(to bottom, rgba(18, 26, 62, 0.55) 0%, rgba(10, 14, 40, 0.34) 46%, rgba(6, 4, 22, 0.42) 100%);
  -webkit-mask-image: linear-gradient(to bottom, rgba(0,0,0,0) 0%, #000 18%, #000 82%, rgba(0,0,0,0) 100%);
  mask-image: linear-gradient(to bottom, rgba(0,0,0,0) 0%, #000 18%, #000 82%, rgba(0,0,0,0) 100%);
}

[data-water="deep"] > .container { position: relative; z-index: 2; }

/* deeper water: the same surface, slower, and it never competes with the route because depth
   falloff in reflect.js already decides how much surface structure survives down here. One knob,
   not two: a CSS opacity on top of that would just hide where the real control is. */
[data-water="deep"] .pw-surface {
  z-index: 1;
}

[data-water="deep"] .pw-surface.is-adrift { animation-duration: 52s; }

/* Zooming the reflection on a narrow frame puts more lit water behind the section header and less
   dark depth, which took the 12px section label from 6.04 to 3.77 against a 4.5 floor at 390x844.
   The local band answers it where the words are, rather than dimming the water everywhere. */
.page-world[data-role="reflect"] ~ .container .section-header::before {
  inset: -1.4em -8%;
  background: linear-gradient(to bottom,
    rgba(4, 1, 11, 0) 0%,
    rgba(4, 1, 11, 0.82) 24%,
    rgba(4, 1, 11, 0.82) 76%,
    rgba(4, 1, 11, 0) 100%);
}
