/* THE SECOND GROUND — a colour scheme the three dials travel, not a new sky.
 *
 * Victor, 5 Oct 2026: "Standardize the theatre, never standardize the
 * performance." The sky is not a backdrop, it is six layers the dials move
 * through -- pitch dark, faint stars, stars glowing, twilight, clear
 * afternoon. He wants the same MECHANISM on a colour scheme, so the ground
 * becomes a choice while the nine canvases stay identical.
 *
 * ── WHY THIS IS A SEPARATE FILE AND NOT A REFACTOR OF sky.css ─────────────
 *
 * The obvious move is to lift every literal in sky.css into a token and let a
 * ground redefine the tokens. It is also the move that would cost the sky.
 * sky.css is 1,500 lines of tuning where almost every number is an argument --
 * the vault's four stops are four cross-fades led by --day, the shine is a hump
 * rather than a slope, the panel glow is a six-part box-shadow whose ORDER is
 * load-bearing. Generalising that surface means touching all of it to add the
 * second ground, and GALA-UI.md §10 records five separate occasions where a
 * replacement in this file accounted for what it meant to change and not for
 * what the region contained. A glow added that way silently deleted five
 * shadows; gating the stars deleted the entire night.
 *
 * So the ground is PURELY ADDITIVE. Every rule here is qualified by
 * html[data-ground="ember"], which no page sets unless it is asked to, and
 * every selector is therefore strictly more specific than the sky's own. With
 * the attribute absent this file contributes nothing: not a token sky.css
 * reads, not a value it computes, not one declaration that could win a
 * cascade. The sky's computed values are byte-identical with and without it,
 * which was measured at dial 0, 50 and 100 rather than argued.
 *
 * The cost of being additive is duplication: the vault's gradient and the
 * shine's five layers are restated here in ember's colours, so a change to
 * their GEOMETRY has to be made twice. That is the trade and it is the right
 * way round -- a duplicated gradient is visible the moment you look at the
 * screen, and a deleted shadow is not.
 *
 * ── THE DIAL VARIABLES ARE NOT OVERRIDABLE, AND THAT IS THE GUARANTEE ─────
 *
 * setSky() writes --day --t --clear --stars --sky-layer --shine --shine-white
 * --vault-hue --vault-sat --vault-bright --depth --dark --cloud to
 * document.documentElement.style, which is an INLINE style and outranks every
 * rule in this file. So a ground physically cannot move the dial's curves; it
 * can only say what colour each value means. That is what makes "the sliders
 * traverse it exactly as they traverse the sky" a fact about the cascade
 * rather than a promise about my arithmetic.
 *
 * ── data-ground ON html IS NOT data-ground ON body ────────────────────────
 *
 * nine/shell.css already publishes body[data-ground="paper|stage|pack"], which
 * is the shell's BACKDROP TREATMENT -- a different thing with the same word on
 * it. They never collide as selectors because they are different elements, and
 * every rule here is written html[...] rather than [...] so that stays true by
 * construction. If a third ground arrives, qualify it the same way.
 *
 * ── THE SIX LAYERS ────────────────────────────────────────────────────────
 *
 *   base     the thing that is always there          .sky's own fill
 *   vault    the twilight layer, cross-faded by --day .sky::before
 *   field    the travelling particles                 void.js, by option
 *   wash     the nebula                               --nebula
 *   source   the shine                                .sky::after
 *   bloom    the panel tint                           --sky-tint
 *
 * They are the same six the blue sky has, in the same paint order, driven by
 * the same variables. Nothing here is a new layer and nothing is removed.
 */

/* ══ EMBER ═════════════════════════════════════════════════════════════════
 *
 *   dial 0    near-black plum, faint ember sparks, no vault and no source
 *   dial 50   twilight: aubergine to magenta to rose
 *   dial 100  coral and warm gold, no sparks
 *
 * The ladder Victor named is aubergine #2A0A2E, magenta #6B1050, rose #C62368,
 * coral #F2724B, and it is travelled TWICE over: up the dial, and up the frame
 * at any dial setting. That is what a real sunset does -- the deep colour is
 * overhead and the warm one is at the horizon -- and it is why this reads as
 * one world moving rather than six unrelated colours. Add warm gold at the
 * foot for the top of the travel and the arc closes.
 */
html[data-ground="ember"] {
  /* LAYER 4 · THE WASH. Smoke at the dark end, warm haze at the bright one.
     The nebula's own opacity is max(--stars, --depth) and is untouched, so
     this is a night layer in ember exactly as it is in the blue sky.

     var(--day) inside a custom property is safe HERE and only here: §7 records
     that a var() in a custom property resolves where the property is COMPUTED,
     and --nebula computes on html -- which is the very element setSky writes
     --day to. So it tracks the dial. Declared one level down it would not. */
  --nebula:
    radial-gradient(70% 120% at 18% 120%,
      color-mix(in srgb,
        color-mix(in srgb, #F2724B calc(var(--day, 0) * 100%), #4A3A42) 46%,
        transparent) 0%, transparent 62%),
    radial-gradient(60% 140% at 86% -30%,
      color-mix(in srgb,
        color-mix(in srgb, #C62368 calc(var(--day, 0) * 100%), #3A2E36) 30%,
        transparent) 0%, transparent 58%);
}

/* LAYER 1 · THE BASE. What is left when the vault has gone and the sparks are
   all that is in it. It matches the fill void.js paints on its own canvas
   exactly -- the ember palette passes the same #0B0407 -- because §5a records
   the two disagreeing at every opacity in between when they were allowed to.
   background-color rather than the shorthand: the longhand wins on
   specificity and leaves background-image, -position and -repeat alone, so
   nothing is reset that the sky did not reset itself. */
html[data-ground="ember"] .sky { background-color: #0B0407; }

/* LAYER 2 · THE VAULT. Four stops, each cross-faded from its night colour to
   its day colour by --day, which is structurally the same declaration the blue
   sky makes -- the hues are all that changed.

   THE NIGHT END IS LIGHT, NOT DARK, and that is not a mistake. The blue sky's
   night stops are --teal and --olive mixed toward --ink, and --ink is the near
   WHITE of the dark pack; the darkness comes entirely from
   brightness(--vault-bright), which runs 0.03 at the bottom of the dial to
   1.21 at the top. Choosing genuinely dark plums here would be darkness twice
   and the twilight vault would come out near-black -- which is the state the
   base and the field are for, not the state the vault is for. So the night
   stops are ember hues mixed toward --ink at the same ratios the sky uses
   (70 / 34 / 30 / a trace), and the filter does the rest.

   --vault-hue, --vault-sat and --vault-bright are deliberately NOT overridden.
   They are inline on html and could not be anyway, and they behave correctly
   on these hues: hue-rotate is 0deg at twilight and at full day, and the
   -22deg it reaches in the stars-only band rotates rose toward violet, which
   is the plum the bottom of this ground is meant to be. */
html[data-ground="ember"] .sky::before {
  background-image:
    linear-gradient(to bottom,
      color-mix(in srgb, #6B1050 calc(var(--day, 0) * 100%),
                color-mix(in srgb, #2A0A2E 70%, var(--ink))) 0%,
      color-mix(in srgb, #C62368 calc(var(--day, 0) * 100%),
                color-mix(in srgb, #6B1050 34%, var(--ink))) 42%,
      color-mix(in srgb, #F2724B calc(var(--day, 0) * 100%),
                color-mix(in srgb, #C62368 30%, var(--ink))) 78%,
      color-mix(in srgb, #FFC58A calc(var(--day, 0) * 100%),
                color-mix(in srgb, #F2724B 14%, var(--ink))) 100%);
}

/* LAYER 5 · THE SOURCE. Absent at 0 because --shine is 0 there and stays 0
   through the stars-only band; warm gold at full travel.

   THE GEOMETRY IS COPIED EXACTLY and only the colours move. Five layers: the
   specular core, the near field, the parallel wash, the horizon band, and the
   coloured patch high right. A far light is a small bright point over a wide
   even wash (§5a), and that argument is about falloff rather than about hue,
   so it survives the recolour unchanged. Count them before editing: five, and
   a background-image list replaces rather than accumulates, the same way
   box-shadow does.

   --ochre and --teal are replaced by literals rather than by redefining the
   pack tokens. Redefining --ochre under this selector would repaint every
   accent, rule and label on the page, which is a theme and not a ground. */
html[data-ground="ember"] .sky::after {
  background-image:
    /* the specular core: a warm white, not a neutral one */
    radial-gradient(3.5% 7% at 50% -15%,
      rgba(255, 244, 226, calc(var(--shine, .9) * .78)) 0%,
      rgba(255, 232, 198, calc(var(--shine, .9) * .30)) 46%,
      transparent 76%),
    /* the near field around the source */
    radial-gradient(44% 46% at 50% -15%,
      color-mix(in srgb,
        color-mix(in srgb, #fff var(--shine-white, 0%), #F0A24A)
        calc(26% * var(--shine, .9)), transparent) 0%,
      transparent 76%),
    /* the parallel wash, wide enough that the gradient across it is gentle */
    radial-gradient(150% 120% at 50% -15%,
      color-mix(in srgb,
        color-mix(in srgb, #fff var(--shine-white, 0%), #F0A24A)
        calc(22% * var(--shine, .9)), transparent) 0%,
      transparent 86%),
    /* the horizon band: twilight is brightest low */
    linear-gradient(to top,
      color-mix(in srgb,
        color-mix(in srgb, #fff var(--shine-white, 0%), #F0A24A)
        calc(13% * var(--shine, .9)), transparent) 0%,
      transparent 42%),
    /* the coloured patch high right -- rose here, teal in the blue sky */
    radial-gradient(34% 26% at 78% 18%,
      color-mix(in srgb, #C62368 34%, transparent) 0%,
      transparent 72%);
}

/* LAYER 6 · THE BLOOM. A panel holds the hue of the sky it is sitting in, and
   --sky-tint is already the channel that says so -- it reads --t, the dial, so
   the surface walks the travel on its own. Only the two colours change: the
   plum the panel is at dark night, and the rose it takes on toward full day.
   --panel is computed per canvas from this and is left alone. */
html[data-ground="ember"] .vista {
  --night-panel: #120409;
  --sky-tint: color-mix(in srgb, #C62368 calc(var(--t, 0) * 30%), var(--night-panel));
}

/* THE BIAS LIGHT BEHIND A PANEL IS THE ONE COOL THING LEFT, and at dial 0 it
   is also the brightest -- --dark is 1 there, so a 34% #cfe4ff halo rings every
   panel on a near-black plum ground. That is a blue lamp in an ember world and
   it undoes the whole scheme in the one state the scheme is most itself.

   THE WHOLE LIST IS RESTATED, ALL SIX PARTS, BECAUSE box-shadow DOES NOT
   ACCUMULATE. §7 and §10: a later declaration REPLACES the list, which is how
   a glow added to these panels once deleted the specular ring, the lit top
   edge, the reflected foot and two more. Everything below is the sky's own
   list verbatim -- same offsets, same blurs, same spreads, same ORDER, because
   the first shadow paints on top and the light has to go last so it sits
   behind the rim. Only the final colour is warm. Counted: 6 in, 6 out. */
html[data-ground="ember"] .vista > .canvas:not([data-space="talk"]) {
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--ink)
      calc((15% - 6% * var(--dark)) * var(--presence)), transparent),
    0 1px 0 color-mix(in srgb, var(--ink) calc(30% * var(--presence)), transparent) inset,
    0 -1px 0 color-mix(in srgb, var(--ink) calc(12% * var(--presence)), transparent) inset,
    inset 0 -14px 20px -16px color-mix(in srgb, var(--paper) 70%, transparent),
    0 5px 12px -7px color-mix(in srgb, var(--paper)
      calc(62% * (1 - var(--dark)) * var(--presence)), transparent),
    0 0 13px -5px color-mix(in srgb, #ffd7b0
      calc(34% * var(--dark) * var(--presence)), transparent);
}

/* ══ DEEP ══════════════════════════════════════════════════════════════════
 *
 * Victor, 6 Oct 2026: "The fundament is not a page. Its a screen. A clear
 * screen. A 3d screen."
 *
 * Two of those three were already built. The screen is the nine-canvas field,
 * and the clear state is the bottom of the sky dial, where the vault leaves,
 * html computes rgb(0,0,0) and an additive display renders that as the room.
 * The third was not: measured 6 Oct, sky.css and shell.css between them hold
 * ZERO perspective, ZERO translateZ and ZERO preserve-3d. The dimensionality
 * was entirely light -- 30 uses of --presence, 13 backdrop-filters, 9
 * box-shadows, 4 --lift. It READS dimensional and it is geometrically flat.
 *
 * This ground gives it distance. Additively, under html[data-ground="deep"],
 * exactly as ember does, for the reason ember's header gives: generalising
 * sky.css into tokens means touching all 1,500 lines of it, and GALA-UI.md
 * §10 records five occasions where a replacement in that file accounted for
 * what it meant to change and not for what the region contained.
 *
 * ── THE ONE THING THAT MAY NOT MOVE ───────────────────────────────────────
 *
 * The grid is solved and measured: columns 1:3:1, rows .3164:1:.2379, gaps
 * 1.1% and 1.956%, and the aspects are exact -- 1.777813 at the top corners,
 * 0.562491 at the side middles, 1.687472 for the stage. Those four numbers
 * are the point of the whole thing.
 *
 * Under perspective(P), an element at translateZ(Z) renders LARGER by
 * P/(P-Z). Naive depth therefore scales every canvas and breaks every aspect
 * ratio. The compensation is scale((P-Z)/P), which cancels the magnification
 * exactly -- and the numbers here are chosen so that it cancels in two
 * decimal places rather than in a repeating fraction:
 *
 *     P = 2400px             = 24 x 100
 *     Z = -720px   k = 1.30  = (2400 + 720) / 2400     the vault
 *     Z = -480px   k = 1.20  = (2400 + 480) / 2400     the cosmos
 *     Z =  + 12px  k = 0.995 = (2400 -  12) / 2400     a picked canvas
 *
 * ── WHY THE NINE SIT AT Z = 0, AND IT IS THE TRADE WORTH KNOWING ──────────
 *
 * The obvious build is the one the eye wants: the stage forward of the
 * shallow cells, the registers nearer the plane, nine depths for nine
 * canvases. It cannot be had, for two separate reasons, and both were
 * measured rather than argued.
 *
 * ONE. A transform on .canvas destroys the one sheen. §6 of GALA-UI records
 * that nine radial-gradients read as nine little suns in nine different
 * skies, and the fix is background-attachment: fixed on .vista > .canvas
 * ::before, which resolves ONE gradient against the viewport so every panel
 * shows its own window onto one light. A fixed background positions against
 * the nearest transformed ancestor, not the viewport -- so the moment a
 * canvas carries any transform at all, its share of the sheen snaps back to
 * its own box. Proved with a hard-edged red/cyan half-and-half in place of
 * the sheen: with no transform the boundary is one straight line at viewport
 * 50% crossing every panel; with transform: translateZ(0.0001px) on .canvas
 * each panel splits at its own midpoint. 0.0001px of depth, the entire
 * guarantee. perspective on an ANCESTOR does not do this -- the same probe
 * with perspective on .gala-full keeps the single line -- which is why the
 * container below is safe and the children are not.
 *
 * TWO. Under one camera, cells at different depths cannot keep both their
 * size and their place. translateZ magnifies about the PERSPECTIVE ORIGIN;
 * the compensating scale shrinks about the element's OWN centre. The two
 * cancel in size and leave a residual displacement of (c - o) * Z/(P - Z),
 * where c is the canvas centre and o the perspective origin. You may keep
 * the size or keep the position; a grid of nine cannot have both. The grid
 * is the product. So the nine stay at zero, and the depth goes where it
 * costs nothing: behind them.
 *
 * ── WHAT ACTUALLY CARRIES THE DEPTH ───────────────────────────────────────
 *
 *   .sky            a real perspective, so the weather is a VOLUME
 *   .sky::before    the vault, deepest, at -720
 *   .sky > .cosmos  the travelling field, at -480, in front of the vault
 *   .night, ::after the nebula and the shine, at 0 -- see below
 *   .vista          the camera for the nine -- perspective reaches CHILDREN
 *   the nine        z = 0. Nothing moves, nothing grows.
 *   a picked canvas +12, compensated: the one moment a user causes
 *
 * THE DEPTHS KEEP THE PAINT ORDER THEY ALREADY HAD, and that is a constraint
 * rather than a preference. Inside a 3D rendering context elements sort by
 * their z position and not by document order, so a vault placed in front of
 * the cosmos would COVER the stars -- the thing §5a says must always be
 * running. The vault paints first today, so it is the deeper of the two.
 *
 * THE NEBULA AND THE SHINE STAY AT ZERO BECAUSE THEY ALREADY OWN THEIR
 * transform. .night runs the 900s `cosmos` keyframes and .sky::after runs the
 * 240s `light` keyframes, both of which animate transform -- and §7 records
 * that an important author declaration outranks an animation declaration, so
 * the only way to put them at depth is to delete their drift. That is the §10
 * failure exactly: a change that accounts for what it means to do and not for
 * what the region contains. They keep their drift and lose their depth. The
 * cost is that the nebula does not parallax with the cosmos it belongs to --
 * it is a soft radial wash and a few pixels of relative motion on one is not
 * visible, which was checked by looking rather than assumed. An element with
 * no translateZ is unaffected by an ancestor's perspective, so adding the
 * property to .sky changes nothing for either of them.
 *
 * ── THE CAMERA MOVES, NOT THE WORLD ───────────────────────────────────────
 *
 * The parallax is driven by perspective-origin, which is the only honest way
 * to do it: a hand-written offset per layer is a drawing of parallax, and
 * this is the arithmetic. Shifting the origin by o moves a layer at depth Z
 * by exactly o * Z/(P + Z), so the vault travels 0.231 of the swing, the
 * cosmos 0.167, and everything at zero -- the nebula, the shine, all nine
 * canvases -- travels nothing at all. The relative motion is the depth.
 *
 * index.html writes --par-x and --par-y from pointermove and CSS transitions
 * them. §5 and the brief: requestAnimationFrame does not fire in a hidden
 * tab, so anything awaited on it deadlocks when a tab goes to the background.
 * A custom property plus a transition cannot.
 */
html[data-ground="deep"] {
  --deep-p: 2400px;
  --par-x: 0px;
  --par-y: 0px;
}

/* THE SKY BECOMES A VOLUME. perspective here and nowhere above it: §5 and
   trap 2 of the brief both record that .sky paints at the ROOT's negative-z
   step precisely BECAUSE body creates no stacking context, so a transform or
   a perspective on body or html would move where the sky paints and the
   symptom is the sky vanishing while every variable still reads correctly.
   .sky is already position: fixed with z-index -2, so it is already a
   stacking context and already the containing block for its own absolute
   children; adding perspective to it changes neither. */
html[data-ground="deep"] .sky {
  perspective: var(--deep-p);
  perspective-origin: calc(50% + var(--par-x)) calc(50% + var(--par-y));
  transition: perspective-origin .55s cubic-bezier(.22, .61, .36, 1);
}
/* The vault, deepest. 1.3 is (2400 + 720)/2400 exactly, so the layer still
   covers the viewport at precisely the size it covered it before. */
html[data-ground="deep"] .sky::before { transform: translateZ(-720px) scale(1.3); }
/* The travelling field, in front of the vault and behind everything else --
   the order it already painted in. 1.2 is (2400 + 480)/2400 exactly. At rest
   the composite matrix is the identity, so the canvas rasterises 1:1 and no
   star is resampled; only the parallax translates it. */
html[data-ground="deep"] .sky > .cosmos { transform: translateZ(-480px) scale(1.2); }

/* THE CAMERA FOR THE NINE, AND IT HAS TO BE ON .vista.
   It was on .gala-full first, which is one step further from the element that
   owns the solved template and therefore looked like the safer place. It is
   not a safer place, it is an inert one: PERSPECTIVE REACHES DIRECT CHILDREN
   ONLY. .gala-full's only child is .vista, so the canvases -- its
   grandchildren -- were outside the 3D context entirely, and a control that
   put translateZ(24px) on all nine moved not one pixel of one rect. Nothing
   errored and every computed value read correctly: perspective 2400px on
   .gala-full, matrix3d on the canvas, zero difference on the screen. That is
   §2 in a stylesheet -- an instrument reporting a verdict it could not reach.
   The alternative is transform-style: preserve-3d on .vista to propagate it,
   and that is trap 1: preserve-3d stops overflow: hidden clipping 3D
   descendants, and the canvases clip. Putting the perspective one level down
   keeps preserve-3d out of the file altogether.

   A perspective on an ancestor does NOT break background-attachment: fixed --
   re-proved with the half-and-half probe after this moved -- so the one sheen
   survives it. A transform on a canvas does, which is why there is not one.

   THE TRANSITION IS RESTATED, BOTH PARTS, BECAUSE transition DOES NOT
   ACCUMULATE EITHER. shell.css transitions grid-template-columns and
   grid-template-rows on .vista, which is how the drag handles move weight
   over .42s; a later, more specific `transition: perspective-origin` replaces
   that list and the handles would snap. GALA-UI §10 is a list of exactly this
   mistake. Counted: 2 in, 3 out. */
html[data-ground="deep"] .vista {
  perspective: var(--deep-p);
  perspective-origin: calc(50% + var(--par-x)) calc(50% + var(--par-y));
  transition: grid-template-columns var(--shift, .42s cubic-bezier(.22, .61, .36, 1)),
              grid-template-rows    var(--shift, .42s cubic-bezier(.22, .61, .36, 1)),
              perspective-origin    .55s cubic-bezier(.22, .61, .36, 1);
}

@media (hover: hover) {
  /* THE ONE MOMENT A USER CAUSES. A picked canvas comes 12px toward the
     viewer and is scaled by 0.995 = (2400 - 12)/2400, so its width, its
     height and its aspect ratio are unchanged to the pixel -- measured, not
     assumed. What is left is the residual the header describes: it slides
     away from the frame centre by (c - o)/199, which is 0.08px at the stage
     and 2.4px at a corner on a 1280 frame. That is what coming toward a
     camera off its axis looks like, and it is the ONLY geometry this ground
     moves.

     IT WAS 24px FIRST, AND THAT IS THE NUMBER TO CHANGE IF THIS IS WRONG.
     At 24 the slide is 4.8px, and at a corner that is enough to break the
     column edge against the panel above it -- visible in a screenshot as a
     misalignment rather than as depth, which is the wrong trade in a layout
     whose whole language is that the edges line up. Halved, the lift still
     reads because the surface lifts with it (--lift: 8% and the active gloss
     are sky.css's own, untouched) and the edge no longer breaks. The slide
     scales with the frame, so it is 4.8px at 2560 wide: if it ever reads
     wrong on a large display, this is one number and it is here.

     THE SHEEN COSTS NOTHING HERE, and that is why the lift is affordable on
     hover and nowhere else. sky.css's own hover rule restates ::before's
     background with the SHORTHAND, which resets background-attachment to its
     initial `scroll` -- so the panel under the cursor already draws its own
     highlight rather than its share of the one sky. Verified in the browser
     rather than read off the source: a probe element with
     background-attachment: fixed followed by a shorthand computes `scroll`.
     The transform takes a guarantee that hover had already given up.

     THE TRANSITION LIST IS RESTATED IN FULL. sky.css line 705 transitions
     box-shadow and transform, and its own @media (hover: hover) block then
     replaces that list with background-color, box-shadow, backdrop-filter and
     opacity -- dropping transform. box-shadow does not accumulate and neither
     does transition; a later declaration REPLACES the list. So all four are
     written out again and transform is added. Counted: 4 in, 5 out. */
  html[data-ground="deep"] .vista > .canvas:not([data-space="talk"]) {
    transition: background-color .34s ease, box-shadow .34s ease,
                backdrop-filter .34s ease, opacity .34s ease,
                transform .34s cubic-bezier(.22, .61, .36, 1);
  }
  html[data-ground="deep"] .vista > .canvas:not([data-space="talk"]):hover,
  html[data-ground="deep"] .vista > .canvas:not([data-space="talk"]):focus-within {
    transform: translateZ(12px) scale(.995);
  }
}

/* THE LIGHT AGREES WITH THE CAMERA RATHER THAN FIGHTING IT.
   The panels do not move, so the only way they can belong to a scene that
   does is for the light on them to answer to it: swing the camera and the
   cast shadow and the bias light swing the other way, which is what a fixed
   surface under a moving viewpoint does. It is a few pixels and it moves the
   SHADOW, never the box -- box-shadow offsets cannot touch a bounding rect.

   THE WHOLE LIST IS RESTATED, ALL SIX PARTS, BECAUSE box-shadow DOES NOT
   ACCUMULATE -- the same reason ember restates it fifty lines above, and the
   same failure GALA-UI §10 records: a glow added to these panels once
   silently deleted the specular ring, the lit top edge, the reflected foot
   and two more. Everything here is sky.css's own list verbatim -- same
   colours, same blurs, same spreads, same ORDER, because the first shadow
   paints on top and the light has to go last so it sits behind the rim. Only
   the two offsets of the last two parts gain a term, and they are divided
   down so the swing is 2.4px at the extremes rather than 48. Counted: 6 in,
   6 out. */
html[data-ground="deep"] .vista > .canvas:not([data-space="talk"]) {
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--ink)
      calc((15% - 6% * var(--dark)) * var(--presence)), transparent),
    0 1px 0 color-mix(in srgb, var(--ink) calc(30% * var(--presence)), transparent) inset,
    0 -1px 0 color-mix(in srgb, var(--ink) calc(12% * var(--presence)), transparent) inset,
    inset 0 -14px 20px -16px color-mix(in srgb, var(--paper) 70%, transparent),
    calc(var(--par-x) / -20) calc(5px - var(--par-y) / 20) 12px -7px
      color-mix(in srgb, var(--paper)
      calc(62% * (1 - var(--dark)) * var(--presence)), transparent),
    calc(var(--par-x) / -20) calc(var(--par-y) / -20) 13px -5px
      color-mix(in srgb, #cfe4ff
      calc(34% * var(--dark) * var(--presence)), transparent);
}

/* Reduced motion keeps the depth and loses the travel. The geometry is not
   the thing that moves; the camera is, and index.html does not attach the
   listener at all under this query, so --par-x and --par-y hold the 0px they
   are declared with above and every calc() falls out to the sky's own
   numbers. The transitions go so nothing eases on a resize. */
@media (prefers-reduced-motion: reduce) {
  html[data-ground="deep"] .sky,
  html[data-ground="deep"] .vista      { transition: none; }
}
