/* orbend.css — the manifesto's ending, and the meet page's optional one.
 *
 * ⚠ ONE FILE, LOADED BY BOTH. This started life inside tools/inject-chrome.py's own
 * <style>, and the moment the meet page grew a `Footer: orb` setting it would have had
 * to exist in css/app.css as well — two copies of the geometry an interaction depends
 * on, in two files, one of them generated. The injected chrome links this instead.
 *
 * A short scroll-linked transition replaces the former long, weighted hold.
 * Progress follows native scroll directly; the preceding headline stays in flow.
 */
.man-orb { position: relative; z-index: 20; height: 160svh; margin-top: -100svh; }
.man-orb-sticky { position: sticky; top: 0; height: 100svh; overflow: hidden; }
/* ⚠ THE CANVAS IS THE SECTION'S GROUND, not an overlay on it: the engine's main pass
   returns the background for every pixel outside the shape, so this sheet IS the page
   here — which is what lets the copy be painted BEHIND the glass and bent by it. It
   takes no pointer, or it would swallow every press meant for the page. */
.man-orb-canvas { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
/* ⚠ THE COPY IS PAINTED ON THE CANVAS, so this is the same two lines for a reader who
   is not looking at the screen — and the only visible copy when there is no orb (v2
   solves the same problem with `display: none`, which leaves nothing for a screen
   reader). Hidden the accessible way rather than with `display`, which would take it
   out of the accessibility tree as well. */
.man-orb-line {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
/* ⚠ THE SECTION'S OWN CLOSING LINE, at v2's own content1 position — `top: calc(23% +
   180px)` with a half-height pull, which is where its headline sits over the glass. Only
   built when the page cannot lend one (see manorb.js); the manifesto uses its real one. */
.man-orb-c1 {
  position: absolute; left: 0; right: 0; z-index: 2;
  top: calc(23% + 180px);
  margin: 0; padding: 0 clamp(16px, 4vw, 40px);
  text-align: center;
  font-family: Selecta, -apple-system, sans-serif; font-weight: 400;
  font-size: clamp(30px, 4.6vw, 67px); line-height: 1.02; letter-spacing: -.03em;
  color: var(--scroll-text-color, #191919);
  will-change: transform, opacity;
}
/* the pull is on a wrapper transform written by JS, so the -50% lives here */
.man-orb-c1 { transform-origin: center; }
.man-orb-sticky > .man-orb-c1 { margin-top: -0.5em; }

/* the + on the orb once it has landed, exactly centred on it by manorb.js */
.man-orb-plus {
  position: absolute; left: 50%; top: 0; transform: translate(-50%, -50%);
  display: grid; place-items: center;
  appearance: none; border: 0; background: transparent; padding: 0;
  color: var(--scroll-text-color, #191919);
  opacity: 0; pointer-events: none; cursor: pointer;
  border-radius: 50%;
}
.man-orb-plus:focus-visible { outline: 2px solid currentColor; outline-offset: 4px; }
/* ⚠ WITHOUT THE ENGINE THE SECTION IS NOT A SECTION AT ALL. `is-plain` is set when
   WebGL2, the float-buffer extension or reduced motion say no: 80svh of empty page
   would be a scroll into nothing, the pull-up would lay this on top of the closing
   line, and the copy has to come back out of the screen-reader corner and be read. */
.man-orb.is-plain { height: auto; margin-top: 0; }
.man-orb.is-plain .man-orb-sticky {
  position: static; height: auto;
  padding: clamp(30px, 8vh, 90px) clamp(16px, 4vw, 40px) 0;
}
.man-orb.is-plain .man-orb-canvas, .man-orb.is-plain .man-orb-plus { display: none; }
.man-orb.is-plain .man-orb-line {
  position: static; width: auto; height: auto; margin: 0;
  overflow: visible; clip-path: none; white-space: normal;
  text-align: center;
  font-family: Selecta, -apple-system, sans-serif; font-weight: 400;
  font-size: clamp(26px, 3.6vw, 53px); line-height: 1.12; letter-spacing: -.04em;
  color: var(--scroll-text-color, #191919);
}
/* ⚠ THE CLOSING PANEL IS content1, AND IT HAS TO SIT ABOVE THE CANVAS. v2's own first
   beat is a headline over the glass sheet that fades and drifts up as you scroll; here
   that is the manifesto's real closing line, which — because the panel is not sticky
   and the section under it is — scrolls away on its own. That is the drift, for free,
   with no second copy of the line anywhere. Without the lift it is behind an opaque
   canvas for the whole beat; the panel paints no ground of its own (the manifesto
   colours the document, not its sections), so lifting it hides nothing. */
#waitlist { position: relative; z-index: 21; }
/* ══ the sunset ════════════════════════════════════════════════════════════
   ⚠ A CANVAS, NOT A GRADIENT, and js/sky.js says why: the orb's own background sheet
   draws THIS canvas into itself, so the pixels either side of the sheet's top edge are
   the same bytes rather than the same ramp computed twice — which is what was leaving a
   seam. The element is created by manorb.js (it owns the painting); this only places it
   and applies the strength, which the sky itself chooses via --sky-at. */
#man-sunset {
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  width: 100%; height: 100%;
  opacity: calc(var(--sunset, 0) * var(--sky-at, 0.16));
  /* Match the canvas sky immediately, without a second scroll lag. */
}

/* ══ the meet page's own ending, when it is set to `orb` ═══════════════════
   ⚠ THE STAGE HAS TO GO. It is a fixed full-screen panel with a WebGL scene in it, so
   left in the page it sits behind this section's own ground for the whole beat — and
   its spacer is 40-62vh of scroll that now leads nowhere. `#hint` belongs to it too. */
html[data-footer="orb"] .panel,
html[data-footer="orb"] .spacer,
html[data-footer="orb"] #hint { display: none !important; }
/* the surface's rounded foot is for lifting off the stage; with no stage under it, it
   is a rounded corner over the sky and reads as a cut */
html[data-footer="orb"] .page { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
/* ⚠ AND THE PAGE HAS TO LET THE SKY THROUGH AT ITS FOOT, or there is a hard step where
   it ends. `.page` is an opaque paper sheet at `z-index: 1` and the sky is a fixed layer
   at 0 — so the sky is hidden behind the page, and the orb's sheet (which paints paper
   AND sky) meets bare paper at exactly the sheet's top edge: measured, a 32-64 level
   line straight across the page, against 1-2 on the manifesto, which has no such sheet.
   Fading the page's own background out over its last screen puts the same paper+sky
   composite either side of the join. The BODY is `var(--paper)`, which is the colour the
   sheet fills with, so what shows through is the same ground and not a different one. */
html[data-footer="orb"] .page {
  background-color: transparent;
  background-image: linear-gradient(180deg,
    #fff 0, #fff 92vh, var(--blocks-paper, var(--paper)) 177vh,
    var(--blocks-paper, var(--paper)) calc(100% - 100svh), rgba(248, 248, 248, 0) 100%);
}
/* ⚠ AND THE CLOSING SECTION IS THE ONE THAT GETS HELD, so it needs to sit above the
   sheet exactly as the manifesto's panel does. */
html[data-footer="orb"] #get { position: relative; z-index: 21; }
