/* ky-world — the per-world runtime's own surfaces.
   ==========================================================================
   Only the things ky/ky-world.js creates: the canvas layers it hands out and
   the one cursor element it owns. Every world's OWN look lives in
   ky/worlds/ky-w-<key>.css, scoped to html[data-kyw-world="<key>"].

   Nothing here paints a colour. The runtime is plumbing; the worlds decide
   what it carries. */

/* ---- canvas layers ---------------------------------------------------------
   Fixed, not absolute: a world's field is a property of the VIEWPORT, so it
   must not scroll away from the content it is behind, and must not stretch
   the document to the size of a canvas nobody asked to be 12000px tall.

   contain:strict is the important one. Without it a full-screen canvas
   invalidates layout for the whole document on every resize, and on the two
   pages that carry a video wallpaper underneath, that is the difference
   between a smooth scroll and a stutter. */
.kyw-cv {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  contain: strict;
  display: block;
}
/* behind the page's content but IN FRONT of the wallpaper (.ky-wall is at
   z-index -1), which is the band a world's weather belongs in */
.kyw-cv-under { z-index: 0; }
/* in front of content, for the few effects that are genuinely overlays —
   below the music dock (9000), the calendar (9400/9500) and the flood
   (12000), so a world can never paint over the site's own chrome */
.kyw-cv-over { z-index: 40; }

/* ---- the cursor ------------------------------------------------------------
   ONE element, repainted by whichever world is live. Two parts: a dot pinned
   to the true pointer position (so clicking always feels exact) and a ring
   that eases toward it (so the world has something to express character
   with). A world restyles these in its own stylesheet; it never rebuilds
   them.

   z-index sits above everything the site draws, including the flood, because
   a cursor that disappears under a transition looks like a dropped frame. */
.kyw-cur {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 2147483001;
  pointer-events: none;
  contain: layout style size;
  width: 0;
  height: 0;
}
.kyw-cur-dot,
.kyw-cur-ring {
  position: absolute;
  top: 0;
  left: 0;
  display: block;
  border-radius: 50%;
  will-change: transform;
  /* transform is written every frame by the runtime — never transition it,
     or the ring eases twice and reads as lag */
  transition: width .22s ease, height .22s ease, opacity .22s ease,
              background-color .22s ease, border-color .22s ease;
}
.kyw-cur-dot {
  width: var(--kyw-cur-size, 10px);
  height: var(--kyw-cur-size, 10px);
  background: var(--kyp-heroInk, #fff);
}
.kyw-cur-ring {
  width: var(--kyw-cur-ring, 34px);
  height: var(--kyw-cur-ring, 34px);
  border: 1px solid color-mix(in srgb, var(--kyp-heroInk, #fff) 55%, transparent);
}

/* THE NATIVE CURSOR GOES ONLY ONCE OURS HAS PAINTED.
   .kyw-curon is added by the runtime on the first frame in which the pointer
   has actually reported a position. A page that hides the system cursor and
   then fails to draw a replacement — because the module 404'd, because the
   canvas threw, because the machine is on the survival rung — is unusable,
   and that failure would be invisible in review because it only happens on
   the machines we do not test on. */
html.kyw-curon,
html.kyw-curon body { cursor: none; }
/* except where the native cursor is doing real work: text you can select and
   controls you can operate keep their own affordance */
html.kyw-curon :is(input, textarea, select, [contenteditable="true"]) { cursor: auto; }

/* ---- the two queries that switch all of it off ----------------------------
   The runtime already refuses to build a cursor under either of these; these
   rules are the belt to that pair of braces, and cover the case where the
   class is already on <html> when the query flips. */
@media (prefers-reduced-motion: reduce) {
  .kyw-cur { display: none; }
  html.kyw-curon, html.kyw-curon body { cursor: auto; }
}
@media (pointer: coarse), (hover: none) {
  .kyw-cur { display: none; }
  html.kyw-curon, html.kyw-curon body { cursor: auto; }
}
/* the governor's glass-off rung means the machine is already behind; a
   full-screen canvas field is the first thing that should stop */
html.ky-perf-noVideo .kyw-cv { display: none; }
