.shape-waves{position:relative;width:100%;height:100%;overflow:hidden;pointer-events:none;isolation:isolate}.shape-waves__canvas{position:absolute;inset:0;display:block;width:100%;height:100%;opacity:0;transition:opacity .6s cubic-bezier(.22,1,.36,1);pointer-events:none}.shape-waves[data-ready=true] .shape-waves__canvas{opacity:1}@media(prefers-reduced-motion:reduce){.shape-waves__canvas{transition:none}}:root{--base: #1e1e2e;--text: #cdd6f4;--subtext: #a6adc8;--surface: #313244;--green: #a6e3a1;--mauve: #cba6f7;--blue: #89b4fa;--red: #f38ba8;--peach: #fab387;--pink: #f5c2e7;--discord: #5865f2}@font-face{font-family:JetBrains Mono;font-style:normal;font-weight:100 800;font-display:swap;src:url(/fonts/jetbrains-mono.woff2) format("woff2")}@font-face{font-family:Fira Code;font-style:normal;font-weight:300 700;font-display:swap;src:url(/fonts/fira-code.woff2) format("woff2")}html,body,#root{height:100%}html,body{margin:0;padding:0;background:var(--base);color:var(--text);font-family:JetBrains Mono,Fira Code,Consolas,Menlo,monospace;font-size:14px;overflow:hidden}.webgpu-fallback{position:absolute;left:16px;right:16px;bottom:16px;border:1px solid var(--surface);border-left:3px solid var(--red);background:color-mix(in srgb,var(--base) 88%,transparent);color:var(--text);padding:10px 12px;white-space:pre-wrap;word-break:break-word;pointer-events:none}.webgpu-fallback__title{color:var(--red);font-weight:700;margin-bottom:4px}.webgpu-fallback__detail{color:var(--subtext)}.webgpu-fallback__hint{color:var(--surface);margin-top:4px}#log-toggle{position:fixed;right:10px;bottom:10px;z-index:2;padding:3px 9px;border:1px solid var(--surface);border-radius:3px;background:var(--base);color:var(--subtext);font-family:inherit;font-size:11px;line-height:1.4;letter-spacing:.06em;text-transform:uppercase;cursor:pointer;opacity:.6}#log-toggle:hover{opacity:1;color:var(--green);border-color:var(--green)}#log-panel{position:fixed;inset:0 0 0 auto;z-index:1;box-sizing:border-box;width:min(46ch,100%);height:100%;margin:0;padding:10px 12px 34px;overflow:auto;overscroll-behavior:contain;border-left:1px solid var(--surface);background:color-mix(in srgb,var(--base) 92%,transparent);color:var(--subtext);font-family:inherit;font-size:11px;line-height:1.5;white-space:pre-wrap;word-break:break-word;pointer-events:auto}

/* ==========================================================================
   Page chrome: caption, viewport sizing, touch.
   Added for mobile, where the layout had no rules at all for these.
   ========================================================================== */

/* --- full-height background ---------------------------------------------
   `100%` resolves against the layout viewport, which on iOS is sized for the
   toolbar *hidden*: the bottom of the canvas ends up behind the toolbar.
   `svh` is the smallest viewport height (toolbar shown), so it is stable while
   the toolbar animates and never clips. Deliberately not `dvh`, which resizes
   on every toolbar frame and forces a mask rebuild each time. */
html,body,#root{height:100%}
@supports (height:100svh){html,body,#root{height:100svh}}

html,body{
  overscroll-behavior:none;              /* no pull-to-refresh over the canvas */
  -webkit-text-size-adjust:100%;         /* stop iOS inflating the fallback text */
  text-size-adjust:100%;
}
body{position:relative}

/* --- the caption ---------------------------------------------------------
   It is a sibling of #root, which is 100% tall inside an overflow:hidden
   body, so without this it is laid out entirely below the fold and is never
   seen. Pin it, and keep it clear of notches and the home indicator. */
.logo-caption{
  position:fixed;
  left:50%;
  transform:translateX(-50%);
  bottom:calc(10px + env(safe-area-inset-bottom,0px));
  z-index:2;
  margin:0;
  max-width:min(92vw,60ch);
  text-align:center;
  color:var(--subtext);
  font-size:11px;
  line-height:1.5;
  letter-spacing:.04em;
  pointer-events:none;
  text-wrap:balance;
  /* the dot field is busy; a soft halo keeps the caption readable without a box */
  text-shadow:0 1px 2px var(--base),0 0 8px var(--base),0 0 16px var(--base);
}

/* --- pointer behaviour on the animated background ------------------------ */
.shape-waves{touch-action:pan-y;overscroll-behavior:none}

/* --- "WebGPU unavailable" notice -----------------------------------------
   The most likely thing a phone visitor sees, because WebGPU is still missing
   on plenty of mobile builds. Give it a real layout instead of a thin strip. */
.webgpu-fallback{
  position:fixed;
  left:50%;
  top:50%;
  transform:translate(-50%,-50%);
  right:auto;
  bottom:auto;
  z-index:3;
  width:min(92vw,42ch);
  box-sizing:border-box;
  border:1px solid var(--surface);
  border-left:3px solid var(--red);
  border-radius:6px;
  background:color-mix(in srgb,var(--base) 94%,transparent);
  padding:14px 16px;
  pointer-events:auto;
}
.webgpu-fallback__title{font-size:14px;margin-bottom:6px}
.webgpu-fallback__detail{font-size:12px;overflow-wrap:anywhere}
.webgpu-fallback__hint{
  margin-top:8px;
  padding-top:8px;
  border-top:1px solid var(--surface);
  font-size:12px;
  line-height:1.55;
  overflow-wrap:anywhere;
}
/* the hint reads as a second sentence on small screens */
.webgpu-fallback__hint::before{content:"Try "}

/* --- debug panel controls, clear of the home indicator ------------------- */
#log-toggle{right:calc(10px + env(safe-area-inset-right,0px));bottom:calc(10px + env(safe-area-inset-bottom,0px))}
#log-panel{
  width:100%;
  padding-bottom:calc(34px + env(safe-area-inset-bottom,0px));
  font-size:12px;
}

/* --- narrow and short screens -------------------------------------------- */
@media (max-width:560px){
  .logo-caption{font-size:10px;bottom:calc(8px + env(safe-area-inset-bottom,0px))}
  .webgpu-fallback{padding:12px 14px}
  .webgpu-fallback__title{font-size:13px}
}
@media (max-height:520px){
  .logo-caption{display:none}      /* no room for it without covering the art */
}
