/* A page's world: the same landscape grammar as the index hero, at backdrop scale.

   Three depth planes instead of the hero's five, because a page header is passed in well under one
   screen and the extra planes buy separation the eye cannot resolve at that travel.

   The framing rule is the index crop lesson, unchanged: framed to the painting's WIDTH, anchored to
   the floor, never cover-cropped. Where the band is taller than the painting, the painting's own top
   edge is continued upward and dissolved, which is a continuation of a near-uniform colour rather
   than a stretch of content. Every plane carries a skirt made from its own bottom edge so no plane
   edge can enter the frame while the planes are moving.

   One module, driven by a manifest path, so every secondary page uses the same code. */

.page-world {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

.page-world-stack {
  position: absolute;
  left: 50%;
  bottom: 0;
  transform: translateX(-50%);
}

.page-world .pw-plane {
  position: absolute;
  left: 0;
  width: 100%;
  background-repeat: no-repeat;
  background-position: 0 100%;
}

.page-world .pw-plane img {
  display: block;
  width: 100%;
  height: auto;
}

/* Density in two parts, which is the lesson from the index hero rather than a preference.

   A single band-level radial cannot hold density across copy that spans a tall, brightly lit
   painting: aimed at the headline it left the pills on lit valley, aimed lower it left the tagline
   there, and raising the fill from 0.62 to 0.80 barely moved the numbers because the problem was
   WHERE the density sat, not how much of it there was. So:

   1. a light band-level wash, for separation between the world and everything on it
   2. a band on the copy column itself, sized to the copy, so the density is where the words are and
      the painting stays bright everywhere else

   Both are flat fills with the falloff in a mask, because a gradient's own falloff has to finish
   inside its box and that ceiling is what put text on bare artwork in the first place. */
/* THE DENSITY BUDGET.

   Three darkening layers stack over the same pixels: the band scrim, the band on the copy column,
   and the band on each line or block inside it. Every one of them was defensible on its own and
   nobody had ever measured what they come to TOGETHER, which is why "too dark behind the copy" came
   back three times and each time a single value was shaved.

   The number to manage is COMBINED TRANSMISSION: the painting's luminance behind a block of copy
   with the veils on, divided by the same pixels with them off, measured rather than computed. See
   the standing check in SECONDARY_PAGE_WORLDS.md.

   The defaults below are exactly what guardian-forge ships, which Giovanni has accepted. A page
   that needs more of its painting through lowers them on its own root, and nothing else changes. */
:root {
  --pw-scrim: 0.30;   /* the whole band */
  --pw-copy: 0.50;    /* the copy column */
  --pw-band: 0.72;    /* each line or block of copy */
}

.page-world-scrim {
  position: absolute;
  left: 50%;
  top: -20%;
  width: min(138%, 104rem);
  height: 140%;
  transform: translateX(-50%);
  z-index: 1;
  pointer-events: none;
  background: rgba(4, 1, 11, var(--pw-scrim));
  -webkit-mask-image: radial-gradient(50% 88% at 50% 58%, #000 0%, #000 52%, rgba(0, 0, 0, 0.6) 76%, rgba(0, 0, 0, 0) 100%);
  mask-image: radial-gradient(50% 88% at 50% 58%, #000 0%, #000 52%, rgba(0, 0, 0, 0.6) 76%, rgba(0, 0, 0, 0) 100%);
}

.page-world-copy {
  position: relative;
}

/* The ellipse must reach zero INSIDE its own box. At a 66% vertical radius it was still at a
   visible value when the box ended, so it cut off square and drew a horizontal edge above and below
   the copy. Radii are 50% now, so the fade completes exactly at the edges, and the box is enlarged
   so that a 50% radius still covers the words. Same reasoning as the crossing scrim. */
.page-world-copy::before {
  content: '';
  position: absolute;
  inset: -26% -24%;
  z-index: -1;
  pointer-events: none;
  background: rgba(4, 1, 11, var(--pw-copy));
  -webkit-mask-image: radial-gradient(50% 50% at 50% 50%, #000 0%, #000 44%, rgba(0, 0, 0, 0.6) 70%, rgba(0, 0, 0, 0) 100%);
  mask-image: radial-gradient(50% 50% at 50% 50%, #000 0%, #000 44%, rgba(0, 0, 0, 0.6) 70%, rgba(0, 0, 0, 0) 100%);
}

/* A single line can still fall short when its ink is mid-luminance. Pure cyan, rgb(0,212,255), has
   a relative luminance of 0.543, so at the 4.5 required of small text it needs everything behind it
   below about rgb(80,80,80). No amount of column density fixes that without veiling the painting
   the section exists to show, so the line gets its own band. Density, not a changed brand colour. */
.page-world-line,
.page-world-block {
  position: relative;
}

/* A block of copy gets the same band as a line, just taller. Density belongs where the words are:
   three banded blocks over a light wash keeps the painting visible everywhere else, where pushing
   one global veil up to cover the worst line dimmed the whole picture to do it. */
.page-world-block::before {
  inset: -0.6em -12%;
}

/* Four soft edges, not two. The mask faded left and right but the background ran to the box top
   and bottom at full strength, which is the horizontal edge above and below the line. The fade runs
   down the gradient and across the mask, one axis each, the construction the index trusted strip
   settled on. */
.page-world-line::before,
.page-world-block::before {
  content: '';
  position: absolute;
  inset: -0.9em -10%;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(4, 1, 11, 0) 0%, rgba(4, 1, 11, var(--pw-band)) 34%, rgba(4, 1, 11, var(--pw-band)) 66%, rgba(4, 1, 11, 0) 100%);
  -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 14%, #000 86%, transparent 100%);
  mask-image: linear-gradient(to right, transparent 0%, #000 14%, #000 86%, transparent 100%);
}

/* Tall frames crop harder into a near 2:1 painting, which lands the copy on more lit detail. */
@media (max-aspect-ratio: 5 / 4) {
  .page-world-copy::before {
    background: rgba(4, 1, 11, calc(var(--pw-copy) * 1.0));
  }
}

html[data-motion="still"] .page-world .pw-plane {
  transform: none !important;
}

/* ---------- Acts 2 and 5: the world persists, and returns ----------
   The hero's ground carries on behind the content and comes back at the foot of the page, so the
   visitor reads what the product does while still standing in the valley rather than on a black
   panel. Same module, quieter, because these bands are under body copy rather than a title. */
.page-world[data-role="persist"] { opacity: 0.42; }
.page-world[data-role="foot"]    { opacity: 0.55; }

/* ---------- Act 3: the route ----------
   The pipeline drawn between the workflow steps, with the work travelling it. */
.route-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 3;
  pointer-events: none;
  overflow: visible;
}

/* The route is drawn OVER the cards, not behind them. Behind, the pulse vanishes into a panel at
   exactly the moment it matters, which is the hand-over at a station. In front it reads as the work
   moving down the pipeline, which is what the section is describing. The stroke is thin enough that
   it never competes with the card text. */
[data-route] { position: relative; }
[data-route-stop] { position: relative; z-index: 1; }

/* A stop lights as the work reaches it. Scroll-driven, never a timer. */
[data-route-stop] .workflow-step,
[data-route-stop].workflow-step {
  transition: border-color 420ms ease, box-shadow 420ms ease, transform 420ms ease;
}

[data-route-stop].is-lit .workflow-step,
[data-route-stop].is-lit.workflow-step {
  border-color: rgba(255, 107, 0, 0.55);
  box-shadow: 0 0 30px rgba(255, 107, 0, 0.18), 0 18px 48px rgba(4, 1, 11, 0.55);
}

[data-route-stop] .workflow-number { transition: color 420ms ease, text-shadow 420ms ease; }
[data-route-stop].is-lit .workflow-number { text-shadow: 0 0 18px rgba(255, 107, 0, 0.7); }

/* ---------- Act 4: the guard ----------
   One orb comes forward and stops, and waits while you read. Scoped to its section, not the page. */
/* Placed on the middle of the section, at the size a thing at reading distance would be. The first
   attempt was 220px pinned to the section's top edge, which the section's own overflow clipped into
   a smudge in the corner: present in the numbers, absent to the eye. */
.page-guard {
  position: absolute;
  left: 50%;
  top: 63%;
  width: 560px;
  height: 560px;
  margin-left: -280px;
  margin-top: -280px;
  border-radius: 50%;
  z-index: 0;
  pointer-events: none;
  opacity: 0;
  will-change: transform, opacity;
  /* A long falloff from a small core. The first pass had a dense fill out to 64%, which read as an
     opaque disc and put the section label on top of it. It is light in the distance, not a shape. */
  background:
    radial-gradient(circle at 42% 34%, rgba(255, 240, 214, 0.55) 0%, rgba(255, 240, 214, 0) 14%),
    radial-gradient(circle at 50% 50%, rgba(255, 160, 70, 0.50) 0%, rgba(255, 107, 0, 0.30) 22%,
                    rgba(170, 60, 200, 0.16) 46%, rgba(255, 0, 255, 0) 72%);
  /* No box-shadow. A shadow on a border-radius:50% box draws its glow from the box's own perimeter,
     which puts a hard-edged arc in the frame: the same fault as a gradient stop landing on a
     boundary. All of the falloff is in the gradient, which reaches zero well inside the box. */
}

html[data-motion="still"] .page-guard { display: none; }

/* A band inside a content section, rather than behind a page header, has section boundaries above
   and below it. Those boundaries are exactly where fault 2 came from, so the band fades out into
   them on both axes and never presents an edge. Copy sits above the world, not under it. */
/* Fading in from zero at the top put a DARK NOTCH at the section seam, measured at -13.7 on the
   outer 120 px: the section above ends dark, and a band starting at nothing exposes an even darker
   section background before the world arrives. So the band starts already partly present and only
   the last stretch of the fade does the work. It still leaves at zero into the next section. */
.page-world[data-role] {
  -webkit-mask-image: linear-gradient(to bottom, rgba(0,0,0,0.42) 0%, #000 26%, #000 76%, rgba(0,0,0,0) 100%);
  mask-image: linear-gradient(to bottom, rgba(0,0,0,0.42) 0%, #000 26%, #000 76%, rgba(0,0,0,0) 100%);
}

.page-world[data-role] ~ .container,
[data-guard] > .container {
  position: relative;
  z-index: 2;
}

/* The section label is 12 px, which is the tightest contrast case on the page: over the act 2 band
   it measured 4.30 against a 4.5 floor. It gets the same local band as a line of hero copy rather
   than a heavier wash over the whole section, which is the distributed-density rule again. */
.page-world[data-role] ~ .container .section-header {
  position: relative;
  z-index: 1;
}

.page-world[data-role] ~ .container .section-header::before {
  content: '';
  position: absolute;
  inset: -1.2em -8%;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(4, 1, 11, 0) 0%, rgba(4, 1, 11, 0.66) 30%, rgba(4, 1, 11, 0.66) 70%, rgba(4, 1, 11, 0) 100%);
  -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 16%, #000 84%, transparent 100%);
  mask-image: linear-gradient(to right, transparent 0%, #000 16%, #000 84%, transparent 100%);
}
