/* HYPERPRIOR / liquid chrome: the stage the module puts behind a host (story, page or band mode).
   Link this in <head> on any page that mounts the liquid, so the still shows before (and without) JavaScript.
   Colours, timing and the pause control's sizes come from shell.css :root. */

/* story: the home page's black run. The container is black (also without JavaScript); a rail the container's
   height carries a stage the screen's height, sticky at its top, behind the parts' own content. */
[data-mount="liquid-story"], .lq-host--story {
  display: flow-root;   /* its own block formatting context: the pause disc's margins stay inside it */
  position: relative;
  isolation: isolate;
  background: var(--dark-bg);
  color-scheme: dark;
}
.lq-rail { position: absolute; inset: 0; z-index: -1; pointer-events: none; }
.lq-stage--story { position: sticky; top: 0; width: 100%; height: 100vh; height: 100lvh; }
/* a part's plate (the phone): the empty stretch above its text where its world grows. Hidden on a wide screen,
   where each world grows beside its text; its lower fifth dissolves into the black. The first part's is a little
   taller: it is the first thing the black shows, straight under the hero. */
.lq-plate { display: none; }
@media (max-width: 820px) {
  .lq-plate { display: block; position: relative; height: 36vh; height: 36svh; }
  .lq-host--story [data-part]:first-of-type .lq-plate { height: 40vh; height: 40svh; }
  .lq-plate::after {
    content: ""; position: absolute; left: calc(-1 * var(--frame)); right: calc(-1 * var(--frame)); bottom: 0; height: 20%; pointer-events: none;
    background: var(--dark-bg); -webkit-mask-image: var(--ramp); mask-image: var(--ramp);
  }
  /* a plate at a part's foot (Contact's, under the communicator, so its chrome is on screen to the bottom of the
     page): it comes out of the black at its top as well */
  .lq-plate--foot { height: 30vh; height: 30svh; }
  .lq-plate--foot::before {
    content: ""; position: absolute; left: calc(-1 * var(--frame)); right: calc(-1 * var(--frame)); top: 0; height: 20%; pointer-events: none;
    background: var(--dark-bg); -webkit-mask-image: var(--ramp-up); mask-image: var(--ramp-up);
  }
}

/* stirring: a finger moved sideways across a part stirs the metal (liquid.js); a vertical move still scrolls the page
   and two fingers still zoom it */
.lq-host--story [data-part] { touch-action: pan-y pinch-zoom; }

/* band: a black section; the field sits behind the section's own content (no page uses band or page mode now:
   their posters went with the old dark band and the research page, so they show plain black before the first frame) */
.lq-host--band {
  position: relative;
  isolation: isolate;
  background: var(--dark-bg);
  color-scheme: dark;
}
.lq-stage {
  pointer-events: none;
  overflow: hidden;
  background: var(--dark-bg);
}
.lq-stage--band { position: absolute; inset: 0; z-index: -1; }
/* page: fixed behind everything; the root is black and the body transparent so the field shows through */
html.lq-page { background: var(--dark-bg); }
html.lq-page body { background: transparent; }
.lq-stage--page { position: fixed; left: 0; top: 0; width: 100%; height: 100vh; height: 100lvh; z-index: -1; }

/* the still under the canvas: the frame before the first draw, and what you see without WebGL */
.lq-poster { position: absolute; inset: 0; background: var(--dark-bg) center / cover no-repeat; }
.lq-stage--story .lq-poster { background-image: url("story-poster.jpg"); background-position: center; }
@media (max-width: 820px) {
  .lq-stage--story .lq-poster { background-image: url("story-poster-m.jpg"); background-position: center top; }
}
/* landing deep in a page: no opening-screen still behind a later part's text; black until the first frame */
.lq-stage--page.is-deep .lq-poster, .lq-stage--story.is-deep .lq-poster { opacity: 0; }
.lq-canvas { position: absolute; left: 0; top: 0; width: 100%; height: 100%; display: block; opacity: 0; transition: opacity var(--t-ui) var(--ease); }
.lq-stage.is-ready .lq-canvas { opacity: 1; }
.lq-stage.is-still .lq-canvas { display: none; }
/* page mode without WebGL: the still belongs to the opening screen and scrolls away with it */
.lq-stage--page.is-still { position: absolute; height: 100vh; height: 100svh; }
.lq-stage--page.is-still .lq-poster { opacity: 0.8; }
/* story without WebGL: the still sits behind the first screen of the black only, and dissolves at its foot */
.lq-stage--story.is-still { position: absolute; -webkit-mask-image: linear-gradient(#000 62%, transparent); mask-image: linear-gradient(#000 62%, transparent); }

/* the pause control (WCAG 2.2.2): a 28px disc, dark on dark, on a 44px hit area (the button is the hit area;
   the disc is drawn as its background, because ::before and ::after draw the icon). Its disc stands 22px
   above the host's bottom. The band carries it on the frame's right edge; the story and the page ride the
   bottom right of the screen, the disc centred in the frame's right margin (never over the right-hand column's
   text; on a phone, whose margin is narrower than the disc, as far right as it fits). In the tab order it comes
   early (liquid.js): first in its host. */
.lq-toggle {
  --pad: calc((var(--hit) - var(--toggle)) / 2);
  --tog-r: calc(max(calc(var(--frame) / 2), calc(var(--hit) / 2 + 2px)) - var(--hit) / 2);
  position: absolute; z-index: 3; right: calc(var(--frame) - var(--pad)); bottom: calc(var(--toggle-inset) - var(--pad));
  width: var(--hit); height: var(--hit); padding: 0; margin: 0; border: 0; border-radius: 50%;
  background: radial-gradient(circle closest-side, var(--dark-disc) calc(var(--toggle) / 2 - 1px), var(--dark-disc-edge) calc(var(--toggle) / 2 - 1px), var(--dark-disc-edge) calc(var(--toggle) / 2), transparent calc(var(--toggle) / 2 + 0.5px));
  color: var(--dark-2); cursor: pointer;
  transition: color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
  -webkit-tap-highlight-color: transparent;
}
/* page, wide: the first child of <main>, so it is the first stop after the header (keyboard readers can stop the
   motion before reading), and it rides the bottom of the screen for as long as the page's black runs. It is held by a
   sticky top of a full screen and lifted by its height and inset; its negative bottom margin takes no room in the
   flow, and at the end of the black it stops with its disc the usual inset above the foot of <main>. */
.lq-toggle--page, .lq-toggle--story {
  --lift: calc(var(--hit) + max(calc(var(--toggle-inset) - var(--pad)), env(safe-area-inset-bottom)));
  position: sticky; display: block; top: 100vh; bottom: auto; right: auto; translate: 0 calc(-1 * var(--lift));
  margin: 0 var(--tog-r) calc(-1 * var(--hit)) auto;
}
/* story: the black starts below the white hero, so the disc rests a lift lower and its margins cancel the lift in
   the flow. It stays below the black's top edge: it never sits over the white hero, and rides the screen's foot
   once the black has reached it. */
.lq-toggle--story { margin-top: var(--lift); margin-bottom: calc(-1 * var(--hit) - var(--lift)); }
/* before the black has come up the story's disc waits at the same place on the screen, docked (liquid.js), so it is
   on the first screen and focusing it never scrolls the page; it takes up its sticky ride as the black arrives */
.lq-toggle--story.is-docked { position: fixed; top: auto; bottom: calc(var(--lift) - var(--hit)); right: var(--tog-r); translate: none; margin-bottom: 0; margin-right: 0; }
@media (max-width: 820px) { .lq-toggle--page { position: absolute; top: auto; right: calc(var(--frame) - var(--pad)); bottom: calc(var(--toggle-inset) - var(--pad)); translate: none; margin: 0; } }
.lq-toggle:hover {
  color: var(--dark-full);
  background: radial-gradient(circle closest-side, var(--dark-disc) calc(var(--toggle) / 2 - 1px), var(--dark-disc-edge-on) calc(var(--toggle) / 2 - 1px), var(--dark-disc-edge-on) calc(var(--toggle) / 2), transparent calc(var(--toggle) / 2 + 0.5px));
}
.lq-toggle:focus-visible { color: var(--dark-full); outline: var(--ring-light); outline-offset: calc(-1 * var(--pad) + 2px); }
/* a phone: over a block of text the disc steps aside (liquid.js); focus brings it back */
.lq-toggle { transition: color var(--t-fast) var(--ease), background var(--t-fast) var(--ease), opacity var(--t-ui) var(--ease); }
.lq-toggle.is-aside:not(:focus-visible) { opacity: 0; pointer-events: none; }
.lq-toggle::before, .lq-toggle::after { content: ""; position: absolute; top: 50%; translate: 0 -50%; }
.lq-toggle[data-state="playing"]::before, .lq-toggle[data-state="playing"]::after { width: 2px; height: 9px; background: currentColor; border-radius: 0.5px; }
.lq-toggle[data-state="playing"]::before { left: calc(50% - 3px); }
.lq-toggle[data-state="playing"]::after { left: calc(50% + 1px); }
.lq-toggle[data-state="paused"]::before { left: calc(50% - 3px); width: 0; height: 0; border-style: solid; border-width: 5px 0 5px 8px; border-color: transparent transparent transparent currentColor; }

@media (prefers-reduced-motion: reduce) {
  .lq-canvas { transition: none; }
  .lq-toggle { display: none; }
}
