/*
 * The black-hole scene: layers, render modes, CSS poster and scale body.
 *
 * Copied verbatim from the base-v1 hybrid homepage's css/style.css (the final output of the
 * earlier black-hole renderer project): the composition custom properties are its lines 27-39
 * and 42-66, everything from "scene" down is its lines 72-357. Only this comment and the :root
 * wrapper around the custom properties are new.
 *
 * Layers inside the fixed #universe, bottom to top: #poster (static CSS rendition, also the
 * no-JS fallback), #fb (Canvas 2D fallback), #gl (WebGL), then the scale body (.scale-body SVG
 * stand-in, replaced by the #craft canvas once it has drawn). html[data-mode] is set by
 * main.js: poster | canvas2d | webgl. main.js overwrites --cx/--cy/--rs/--roll/--craft-* so
 * the poster lines up with the rendered scene; the defaults serve the first paint and no-JS.
 */

:root {
  /* Composition (landscape): the upper arc's glow reaches 1.55 shadow radii left of the hole and
     stays 3vw clear of the copy column. */
  --copy-right: calc(6vw + min(620px, 48vw));
  --cx: 86.5vw;
  --cy: 37.5vh;
  --rs: max(22vh, min(36vh, calc((var(--cx) - var(--copy-right) - 3vw) / 1.55)));
  --roll: -22deg;
  /* Scale body: between the copy and the arc, above the disk. */
  --craft-x: calc((var(--copy-right) + var(--cx) - var(--rs) * 1.55) / 2);
  --craft-y: calc(var(--cy) + (var(--craft-x) - var(--cx)) * -0.4041 - var(--rs) * 0.6);
  --craft-len: clamp(7px, calc(var(--rs) * 0.076), 34px);
  --craft-rot: 13deg;
  --fade: 0.9s;
}

@media (max-aspect-ratio: 33/20) {
  :root { --cx: 88vw; }
}

@media (max-aspect-ratio: 7/5) {
  :root { --cx: 90vw; }
}

@media (max-width: 1100px) and (orientation: landscape) {
  :root { --copy-right: 55vw; }
}

/* Portrait: the hole upper right, its lower arc and the disk above the copy (which starts at
   58svh); the scale body below the disk in the dark lower left. */
@media (orientation: portrait) {
  :root {
    --cx: 74vw;
    --cy: 23.5vh;
    --rs: max(20vw, min(31vw, 16.86vh));
    --roll: -28.65deg;
    --craft-x: calc(var(--cx) - var(--rs) * 1.005);
    --craft-y: calc(var(--cy) + var(--rs) * 1.54);
    --craft-rot: -87.6deg;
  }
}

/* ------------------------------------------------------------------------------ scene */

/* Sized to the large viewport so a collapsing mobile URL bar never resizes (and re-renders) it. */
#universe { position: fixed; z-index: 0; top: 0; left: 0; width: 100%; height: 100vh; height: 100lvh; overflow: hidden; isolation: isolate; background: #010203; pointer-events: none; }

#poster,
#fb,
#gl {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

#fb {
  z-index: 1;
}

#gl {
  z-index: 2;
}

/* ------------------------------------------------------------------------------ modes */

#fb,
#gl {
  opacity: 0;
  visibility: hidden;
  transition:
    opacity var(--fade) ease,
    visibility 0s linear var(--fade);
}

[data-mode='canvas2d'] #fb,
[data-mode='webgl'] #gl {
  opacity: 1;
  visibility: visible;
  transition:
    opacity var(--fade) ease,
    visibility 0s;
}

/* When WebGL takes over from the Canvas renderer, keep the Canvas frame up until the fade ends. */
[data-mode='webgl'] #fb {
  transition:
    opacity 0s linear var(--fade),
    visibility 0s linear var(--fade);
}

[data-mode='canvas2d'] #poster,
[data-mode='webgl'] #poster {
  visibility: hidden;
  transition: visibility 0s linear calc(var(--fade) + 0.1s);
}

/* A lost WebGL canvas shows a browser placeholder, not its last frame: swap without a fade. */
.gl-lost #gl {
  opacity: 0;
  visibility: hidden;
  transition: none;
}

.gl-lost #fb {
  transition: none;
}

/* ------------------------------------------------------------------------------ poster */

/*
 * A plain-CSS rendition of the scene: a near-black sky with only a faint warm glow around the
 * hole; the shadow as a black disc with a thin pale rim; the lensed arc over it and a narrower
 * one under it, both close outside the rim; and the pale peach-white disk crossing the shadow and
 * fanning out into amber-brown strands towards the lower left. Everything but the shadow and the
 * glow is drawn in the disk's own frame (.p-sys), rotated by --roll about the hole, in units of
 * the shadow radius (--rs). The uneven stops inside the arcs and across the disk stand in for
 * the filaments of the rendered disk.
 */
#poster {
  z-index: 0;
  overflow: hidden;
  background:
    radial-gradient(
      circle at var(--cx) var(--cy),
      rgba(52, 42, 40, 0.42) calc(var(--rs) * 1.1),
      rgba(38, 32, 32, 0.24) calc(var(--rs) * 1.7),
      rgba(22, 20, 24, 0.12) calc(var(--rs) * 2.3),
      rgba(10, 10, 14, 0.06) calc(var(--rs) * 2.8),
      transparent calc(var(--rs) * 3.4)
    ),
    #010203;
}

#poster i {
  position: absolute;
  display: block;
}

/* The shadow: black, with a thin pale rim (the photon ring). */
.p-hole {
  left: calc(var(--cx) - var(--rs));
  top: calc(var(--cy) - var(--rs));
  width: calc(var(--rs) * 2);
  height: calc(var(--rs) * 2);
  border-radius: 50%;
  background: radial-gradient(circle at 50% 50%, #010102 0%, #020203 70%, #07080a 100%);
  box-shadow:
    0 0 0 max(1.5px, calc(var(--rs) * 0.008)) rgba(244, 236, 230, 0.92),
    0 0 calc(var(--rs) * 0.03) calc(var(--rs) * 0.01) rgba(236, 226, 220, 0.35);
}

.p-sys {
  left: var(--cx);
  top: var(--cy);
  width: 0;
  height: 0;
  transform: rotate(var(--roll));
}

/* The lensed image of the far side of the disk: a broad bright arc over the shadow, from where it
   meets the disk on the left round to the right, with a soft outer glow. */
.p-arc {
  left: calc(var(--rs) * -2.4);
  top: calc(var(--rs) * -2.4);
  width: calc(var(--rs) * 4.8);
  height: calc(var(--rs) * 4.8);
  border-radius: 50%;
  background: radial-gradient(
    closest-side,
    transparent 45.4%,
    rgba(248, 230, 220, 0.8) 47.1%,
    rgba(255, 238, 228, 0.97) 49.2%,
    rgba(250, 228, 218, 0.95) 51.5%,
    rgba(255, 237, 226, 0.97) 54%,
    rgba(250, 226, 214, 0.95) 57%,
    rgba(248, 222, 208, 0.92) 60%,
    rgba(238, 206, 190, 0.8) 64.6%,
    rgba(226, 192, 174, 0.62) 67.5%,
    rgba(208, 176, 160, 0.45) 70.8%,
    rgba(176, 148, 136, 0.24) 77.1%,
    rgba(140, 122, 116, 0.12) 83.3%,
    rgba(100, 92, 92, 0.05) 91.7%,
    transparent 100%
  );
  -webkit-mask-image: conic-gradient(#000, rgba(0, 0, 0, 0.95) 70deg, rgba(0, 0, 0, 0.6) 92deg, transparent 104deg, transparent 252deg, rgba(0, 0, 0, 0.7) 264deg, #000 276deg);
  mask-image: conic-gradient(#000, rgba(0, 0, 0, 0.95) 70deg, rgba(0, 0, 0, 0.6) 92deg, transparent 104deg, transparent 252deg, rgba(0, 0, 0, 0.7) 264deg, #000 276deg);
}

/* The narrower secondary arc under the shadow. */
.p-arc2 {
  left: calc(var(--rs) * -2);
  top: calc(var(--rs) * -2);
  width: calc(var(--rs) * 4);
  height: calc(var(--rs) * 4);
  border-radius: 50%;
  background: radial-gradient(
    closest-side,
    transparent 54.5%,
    rgba(246, 228, 218, 0.8) 56%,
    rgba(248, 230, 220, 0.96) 58.5%,
    rgba(244, 222, 210, 0.94) 61%,
    rgba(248, 228, 218, 0.95) 63%,
    rgba(240, 216, 202, 0.9) 66.5%,
    rgba(236, 206, 190, 0.72) 71%,
    rgba(210, 176, 158, 0.3) 76%,
    rgba(160, 136, 126, 0.14) 82.5%,
    rgba(110, 100, 100, 0.05) 92.5%,
    transparent 100%
  );
  -webkit-mask-image: conic-gradient(transparent 84deg, rgba(0, 0, 0, 0.7) 96deg, #000 108deg, #000 256deg, rgba(0, 0, 0, 0.6) 266deg, transparent 276deg);
  mask-image: conic-gradient(transparent 84deg, rgba(0, 0, 0, 0.7) 96deg, #000 108deg, #000 256deg, rgba(0, 0, 0, 0.6) 266deg, transparent 276deg);
}

/* Soft glow where the arc comes down into the disk, and along the disk. */
.p-bloom {
  left: calc(var(--rs) * -4.6);
  top: calc(var(--rs) * -0.42);
  width: calc(var(--rs) * 5.6);
  height: calc(var(--rs) * 1.1);
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(244, 226, 214, 0.34), rgba(226, 200, 184, 0.16) 50%, rgba(170, 146, 134, 0.05) 80%, transparent);
}

/* Amber-brown strands spreading towards the lower left, brightest just under the disk. */
.p-spray {
  left: calc(var(--rs) * -6.6);
  top: calc(var(--rs) * -0.12);
  width: calc(var(--rs) * 6.2);
  height: calc(var(--rs) * 1.37);
  background: linear-gradient(
    180deg,
    transparent 0%,
    rgba(214, 166, 124, 0.4) 6%,
    rgba(222, 176, 136, 0.55) 10%,
    rgba(200, 150, 108, 0.48) 15%,
    rgba(212, 162, 120, 0.46) 20%,
    rgba(186, 136, 96, 0.38) 26%,
    rgba(198, 146, 104, 0.32) 32%,
    rgba(172, 124, 86, 0.25) 39%,
    rgba(184, 134, 94, 0.2) 46%,
    rgba(156, 110, 76, 0.13) 55%,
    rgba(140, 98, 68, 0.07) 66%,
    rgba(120, 86, 62, 0.03) 80%,
    transparent 100%
  );
  -webkit-mask-image: radial-gradient(48% 95% at 52% 15%, #000 0%, rgba(0, 0, 0, 0.85) 35%, rgba(0, 0, 0, 0.45) 65%, rgba(0, 0, 0, 0.12) 88%, transparent 100%);
  mask-image: radial-gradient(48% 95% at 52% 15%, #000 0%, rgba(0, 0, 0, 0.85) 35%, rgba(0, 0, 0, 0.45) 65%, rgba(0, 0, 0, 0.12) 88%, transparent 100%);
}

/* The near side of the disk: a crisp upper edge, a softer lower one. In front of the shadow
   (.p-band) it runs at the roll; to the left (.p-run) it is seen more obliquely and, as in the
   rendered scene, sits a little higher where the lensed arc comes down into it and runs ~2.5 deg
   steeper, fading out along its length into the strands. */
.p-band,
.p-run {
  height: calc(var(--rs) * 0.42);
  background: linear-gradient(
    180deg,
    transparent 0%,
    rgba(255, 232, 222, 0.35) 6%,
    rgba(255, 238, 230, 0.95) 12%,
    rgb(255, 240, 232) 22%,
    rgba(254, 234, 224, 0.97) 36%,
    rgba(250, 226, 212, 0.94) 50%,
    rgba(242, 212, 196, 0.84) 62%,
    rgba(230, 194, 172, 0.6) 74%,
    rgba(206, 166, 140, 0.3) 87%,
    transparent 100%
  );
}

.p-band {
  left: calc(var(--rs) * -1.6);
  top: 0;
  width: calc(var(--rs) * 3.4);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 18%);
  mask-image: linear-gradient(90deg, transparent, #000 18%);
}

.p-run {
  left: calc(var(--rs) * -4.4);
  top: calc(var(--rs) * -0.1);
  width: calc(var(--rs) * 3.4);
  transform-origin: 100% 22%;
  transform: rotate(-2.5deg);
  -webkit-mask-image: linear-gradient(90deg, transparent 17.6%, rgba(0, 0, 0, 0.12) 32.4%, rgba(0, 0, 0, 0.3) 44.1%, rgba(0, 0, 0, 0.5) 52.9%, rgba(0, 0, 0, 0.8) 64.7%, #000 76.5%, #000 88%, transparent);
  mask-image: linear-gradient(90deg, transparent 17.6%, rgba(0, 0, 0, 0.12) 32.4%, rgba(0, 0, 0, 0.3) 44.1%, rgba(0, 0, 0, 0.5) 52.9%, rgba(0, 0, 0, 0.8) 64.7%, #000 76.5%, #000 88%, transparent);
}

#poster::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at 40% 50%, transparent 62%, rgba(0, 0, 0, 0.15) 100%);
}

/* ------------------------------------------------------------------------------ scale body */

.scale-body,
#craft {
  position: absolute;
  z-index: 3;
  pointer-events: none;
}

/* The SVG stand-in: lit from +x, turned towards the bright stretch of the disk. */
.scale-body {
  left: calc(var(--craft-x) - var(--craft-len) * 0.6);
  top: calc(var(--craft-y) - var(--craft-len) * 0.6);
  width: calc(var(--craft-len) * 1.2);
  height: calc(var(--craft-len) * 1.2);
  overflow: visible;
  transform: rotate(var(--craft-rot));
}

#craft {
  visibility: hidden;
}

.craft-live #craft {
  visibility: visible;
}

.craft-live .scale-body {
  visibility: hidden;
}
