
:root{color-scheme:dark}
/* ONE self-hosted font everywhere → desktop lab and Android game render identically (no SF-Pro-vs-Roboto drift). */
@font-face{font-family:"Inter";src:url("assets/fonts/inter.woff2") format("woff2");
  font-weight:100 900;font-style:normal;font-display:block}
*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none;touch-action:pan-x pan-y}
/* touch-action: pan-x pan-y, NOT manipulation (2026-10-22): manipulation = pan + PINCH-ZOOM, so iOS still zoomed the whole app on a pinch (and a
   thumb on the edge counts as one) — WebKit honours pan-x/pan-y/none/pinch-zoom since iOS 13 (bug 193447) and viewport user-scalable=no is
   ignored since iOS 10. pan-x pan-y = scrolling and swiping allowed, no zoom GESTURE. It does NOT stop the double-tap zoom: that one is a
   failed synthetic click, not a gesture (main.js, the html mouseup listener — read in the WebKit source 2026-10-22). Only a page that is
   ALREADY zoomed (an old tab, iOS keeps it) gets the pinch back so the player can zoom out: main.js sets html.zoomed. */
html.zoomed, html.zoomed *{touch-action:manipulation}   /* manipulation = pan + pinch-zoom (Angel 2026-10-20: fast taps zoomed the game in mid-play; viewport user-scalable=no is ignored by iOS). On every element, not only html: WebKit restarts touch-action below each scroll box. -webkit-user-select + -webkit-touch-callout: iOS Safari reads only the prefixed one, so a long press selected game text or opened the image menu (found in the iOS simulator 2026-10-20, owner 2026-10-21 "fixaj") */
input,textarea,select,[contenteditable]{user-select:text!important;-webkit-user-select:text!important;-webkit-touch-callout:default!important}   /* fields stay typeable and selectable (iOS: -webkit-user-select:none on a field blocks typing). !important: WebKit INHERITS -webkit-user-select, and the fields with all:unset (profile .pf-fld / .pf-fv, login .fld) took the parent's none */
html,body{height:100%;overflow:hidden;background:#0c1720;
  font-family:"Luckiest Guy",sans-serif;font-weight:400;font-synthesis:none;letter-spacing:.02em;color:#fff}
button,input,select,textarea{font-family:inherit;font-synthesis:none}   /* form controls do not inherit the font by default */
/* Luckiest Guy sits high in its line box — trim to cap height so button text is optically centred (owner 2026-09-28) */
button,[class*="btn"],[class*="play"],.si-txt{text-box:trim-both cap alphabetic}
/* browsers without text-box (Firefox, Safari < 18.2): the cap ink sits 0.152em above the line-box centre (measured) →
   a transparent top border of 0.304em moves the centred content down by exactly that */
@supports not (text-box:trim-both cap alphabetic){button,[class*="btn"],[class*="play"]{border-top:.304em solid transparent!important;background-clip:padding-box}}   /* ONE game font (owner 2026-09-28): Luckiest Guy everywhere; sizes/positions tuned in the labs */

/* ── THE ONE BACKGROUND SYSTEM ── two cover layers, DAY + NIGHT, cross-faded by the
   theme service. object-fit:cover fills any phone edge-to-edge. This is the ONLY place
   a background is ever painted — screens are transparent and never paint their own. */
#appbg{position:fixed;inset:0;z-index:0;overflow:hidden;background:#0c1720}
#appbg .layer{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center;
  opacity:0;transition:opacity .45s ease}
#appbg .layer.on{opacity:1}
/* NIGHT placeholder tint — fades in when a scene has no dedicated night art yet (intro/lobby),
   so the day/night switch is visible everywhere until the real night backgrounds land. */
#appbg::after{content:'';position:absolute;inset:0;pointer-events:none;z-index:1;opacity:0;transition:opacity .45s ease;
  background:radial-gradient(120% 95% at 50% 10%,rgba(34,44,96,.30),rgba(6,10,30,.62) 80%)}
#appbg.nightfx::after{opacity:1}
/* PORTRAIT-ONLY rotate prompt — only on a phone in landscape (short height), never on desktop.
   Same look as the TIME'S UP card (D3 peek-over, owner 2026-09-27): character on his grass patch peeking over a dark card. */
#rotate{position:fixed;inset:0;z-index:9999;display:none;align-items:center;justify-content:center;padding:16px;
  background:rgba(10,8,18,.96);color:#fff;font-family:"Luckiest Guy",sans-serif}
#rotate .rt-card{width:300px;max-width:100%;position:relative;margin-top:130px}
#rotate .rt-char{position:absolute;top:-136px;left:50%;transform:translateX(-50%);width:190px;height:190px;object-fit:contain;
  filter:drop-shadow(0 10px 16px rgba(0,0,0,.5));animation:rotTilt 2.6s ease-in-out infinite;transform-origin:50% 90%}
#rotate .rt-body{background:linear-gradient(180deg,#2a2038,#161022);border:1.5px solid #ffffff22;border-radius:22px;
  padding:50px 20px 16px;text-align:center;box-shadow:0 18px 44px rgba(0,0,0,.55)}
#rotate .rt-t{font-size:24px;font-weight:900;color:#ffd94a;letter-spacing:.5px;text-shadow:0 2px 10px rgba(0,0,0,.5)}
#rotate .rt-s{font-size:13.5px;color:#cdbfe6;margin-top:6px;line-height:1.4}
@keyframes rotTilt{0%,100%{transform:translateX(-50%) rotate(-4deg)}50%{transform:translateX(-50%) rotate(4deg)}}
@media (orientation:landscape) and (max-height:560px) and (hover:none){#rotate{display:flex}}   /* a PHONE held sideways — not a short desktop window (owner 2026-10-09: Brave at ~530 px tall showed TURN YOUR PHONE UP over the desktop lobby) */
html.desk #rotate{display:none!important}

/* ── THE SINGLE MOUNT POINT ── exactly one screen lives here at a time (see shell/router.js). */
#view{position:fixed;inset:0;z-index:1;overflow:hidden}
/* ARTBOARD stage rule: app/stage.css (shared with the lab). */

