/* RAD HQ — colours come from the app themes (RADTheme.swift + Weather's ThemeManager).
   Type follows the RAD SPACE site's precedent: the apps use .system(design: .monospaced),
   so the web uses the native mono stack. Same intent, no font download, nothing to go
   stale. (Brief §23 asks for a distinctive dot-matrix display face for short labels —
   that needs a font decision from Sam, so it is deliberately not invented here.) */
:root{
  --void:#04050c;
  --green:#5bf58c; --cyan:#57e0e0; --yellow:#f2c14e; --orange:#e8843c;
  --red:#ff5c4d; --purple:#b48cf0; --amber:#ffb020;
  --text:#cff7dc; --text2:#7fa89a;
  --mono:"SF Mono",ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
}
*{box-sizing:border-box;min-width:0}
html,body{margin:0;overflow-x:hidden;max-width:100%}
html{scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
body{
  background:var(--void);color:var(--text);
  font-family:var(--mono);font-size:14px;-webkit-text-size-adjust:100%;
}
canvas{image-rendering:pixelated}

.skip{position:fixed;left:-9999px;top:8px;z-index:50;background:#0a0d10;color:var(--text);
  padding:10px 14px;border:1px solid var(--green)}
.skip:focus{left:8px}

/* The world sits behind everything, fixed to the viewport. The document scrolls over it. */
.world{position:fixed;inset:0;width:100%;height:100%;z-index:0;display:block}

/* ─────────── NAV — compact terminal chrome, square, never rounded ─────────── */
.nav{
  position:fixed;top:0;left:0;right:0;z-index:20;
  display:flex;align-items:center;gap:18px;
  padding:10px 18px;
  background:rgba(6,8,14,.72);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  border-bottom:1px solid rgba(91,245,140,.16);
}
.brand{
  color:var(--green);text-decoration:none;font-weight:700;
  letter-spacing:3px;font-size:15px;white-space:nowrap;
}
.navlinks{display:flex;gap:6px;margin-left:auto;flex-wrap:wrap}
.navitem{display:inline-flex;align-items:stretch;border:1px solid rgba(255,255,255,.1)}
.navjump,.navopen{
  font-family:var(--mono);font-size:11px;letter-spacing:1.5px;
  background:transparent;color:var(--text2);border:0;cursor:pointer;
  padding:7px 10px;text-decoration:none;line-height:1;
}
.navjump{border-right:1px solid rgba(255,255,255,.1)}
.navjump:hover,.navjump:focus-visible,.navopen:hover,.navopen:focus-visible{
  color:var(--accent);background:rgba(255,255,255,.05);outline:none
}
.navjump[aria-current="true"]{color:var(--accent);background:rgba(255,255,255,.07)}
.navitem:focus-within{outline:2px solid var(--accent);outline-offset:1px}

/* ─────────── THE DOCUMENT — positioned against world coordinates ─────────── */
.scroller{position:relative;z-index:10}

/* Sam: "the one universe / everything rad top needs a similar box as the others so you can
   always read the text, since the spinning galaxy moves behind it."
   Right — and it is the one piece of copy on the page that had nothing behind it. Every
   region card already earns its legibility with a panel; the headline was relying on the
   sky staying dark where it happens to sit, which stopped being true the moment anything
   up there could move. Same panel, same rules: square, hairline, blurred backdrop. */
/* The brand's line, sitting with the brand. It is the one piece of copy that is ABOUT the
   whole page rather than about a place in it, so the chrome is where it belongs — and the
   sky it used to cover is now sky. The sub steps out below 1200px rather than squeezing
   the nav: the tagline is the headline, the sub is support, and support yields first. */
.brandline{
  margin:0;display:flex;align-items:baseline;gap:10px;min-width:0;
  color:var(--text);font-size:12px;letter-spacing:1.4px;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;
}
.brandline::before{
  content:"";flex:0 0 1px;align-self:stretch;background:rgba(91,245,140,.28);margin-right:2px;
}
.brandsub{color:var(--text2);font-size:11px;letter-spacing:.6px}
@media (max-width:1200px){ .brandsub{display:none} }
@media (max-width:820px){ .brandline{display:none} }

/* Region labels: terminal panels embedded in the world, not marketing blocks (§12). */
/* Sam: "the floating cards are amazing but a little too big and take up way too much
   space." They were sized for a world you scrolled through a screen at a time; on a
   one-screen desktop all four are up at once, over the city they are advertising, and
   430px each was covering the thing worth looking at. Trimmed about a third in every
   direction. They shrink themselves into better positions for free: placeSections()
   measures the real DOM box and fits it against the roofline, so a smaller card drops
   into gaps a bigger one could never reach. */
.region{
  position:absolute;left:5vw;max-width:min(292px,80vw);
  padding:10px 12px;
  background:rgba(6,9,14,.62);
  border:1px solid color-mix(in srgb,var(--accent) 42%,transparent);
  border-left:3px solid var(--accent);
  backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);
}
.rname{margin:0;font-size:clamp(14px,1.5vw,18px);letter-spacing:2px;color:var(--accent)}
.rsub{margin:4px 0 9px;color:var(--text);font-size:11px;letter-spacing:.3px;opacity:.9}
.rcta{
  display:inline-block;text-decoration:none;
  font-size:10px;letter-spacing:1.2px;
  color:var(--accent);border:1px solid var(--accent);
  padding:6px 10px;
}
.rcta:hover,.rcta:focus-visible{background:var(--accent);color:#05070c;outline:none}
/* Alt text for the artwork: the canvas is aria-hidden, so the world is described here
   for anyone who cannot see it. Visible only to assistive tech. */
.ralt{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

/* ─────────── THE END OF THE WORLD — integrated, not a slab (§21) ─────────── */
.foot{
  position:relative;z-index:10;
  display:flex;flex-wrap:wrap;align-items:center;gap:10px 22px;
  padding:22px 5vw 30px;
  background:linear-gradient(180deg,rgba(26,20,24,0) 0%,rgba(12,10,12,.9) 55%,#0a080a 100%);
  border-top:0;
}
.more{margin:0;color:var(--amber);font-size:12px;letter-spacing:2px;flex:1 1 100%}
.footlinks{display:flex;gap:16px;flex-wrap:wrap}
.footlinks a{color:var(--text2);font-size:11px;letter-spacing:1px;text-decoration:none}
.footlinks a:hover,.footlinks a:focus-visible{color:var(--green)}
.copy{margin:0 0 0 auto;color:#4c6b60;font-size:11px;letter-spacing:1px}

/* ─────────── RESPONSIVE — recompose, never shrink (§19) ─────────── */
@media (max-width:720px){
  .nav{padding:7px 10px;gap:8px}
  .brand{font-size:12px;letter-spacing:1.5px}
  /* The Store must never be buried in a hamburger (§11) — but it should not be off the
     edge either. All four fit on a 390px phone now: tighter type and padding instead of a
     scroll nobody knows is there. The overflow rule stays as the backstop for a 320px
     screen, where they genuinely cannot all fit. */
  .navlinks{
    margin-left:auto;flex-wrap:nowrap;overflow-x:auto;gap:4px;
    scrollbar-width:none;-webkit-overflow-scrolling:touch;
  }
  .navlinks::-webkit-scrollbar{display:none}
  .navitem{flex:0 0 auto}
  .navjump,.navopen{font-size:9px;letter-spacing:.6px;padding:6px 5px}
  /* NOT full-bleed. A card pinned left AND right is a slab across the artwork, and on a
     phone that meant every screen was one card and nothing else. It keeps its left margin
     and gives the rest back to the city. */
  .region{left:4vw;right:auto;max-width:min(272px,74vw);padding:9px 11px}
  /* The footer fades in from nothing, which is right on a desktop where it meets empty
     asphalt. On a phone the world ends higher up, so that transparent top lands ON the
     city and the links sit unreadable over lit windows. It gets something to stand on. */
  .foot{background:linear-gradient(180deg,rgba(8,7,9,.86) 0%,rgba(10,8,10,.97) 45%,#0a080a 100%)}
  .rname{font-size:15px;letter-spacing:2px}
  .rsub{font-size:10.5px;margin:3px 0 7px}
  .rcta{font-size:9.5px;padding:5px 8px}
  .copy{margin:0;flex:1 1 100%}
}

/* The sun/moon's hit target. Invisible: the art IS the button, this just makes it a
   control rather than a picture. Square focus ring — nothing here is rounded. */
.bodybtn{
  /* z-index 15: ABOVE .scroller (10), below .nav (20).
     Sam: "clicking moon does nothing." It was z-index 6, and .scroller is 10 and covers
     the entire world — so every click on the moon landed on the scroller instead. It was
     never the handler. I verified the toggle with element.click(), which fires the
     listener directly and skips hit-testing altogether, so it passed while the actual
     control was unreachable. A click test that cannot fail is not a test: this is now
     checked with elementFromPoint, which is what a real cursor does. */
  position:absolute;z-index:15;
  background:none;border:0;padding:0;cursor:pointer;
  -webkit-appearance:none;appearance:none;
}
.bodybtn:focus-visible{outline:2px solid var(--green);outline-offset:4px}

/* ─────────── WHAT VEGA SAYS ───────────
   A speech panel, not a modal. She is in the world, so her voice is too. */
.vega-say{
  position:absolute;z-index:16;
  padding:11px 13px;
  background:rgba(6,9,14,.9);
  border:1px solid color-mix(in srgb,var(--purple) 46%,transparent);
  border-right:3px solid var(--purple);
  backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);
  opacity:0;transform:translateY(3px);
  transition:opacity .16s ease-out, transform .16s ease-out;
  pointer-events:none;
}
.vega-say.in{opacity:1;transform:none}
.vega-line{margin:0;color:var(--text);font-size:12px;line-height:1.6;letter-spacing:.2px}
.vega-more{margin:7px 0 0;color:var(--purple);font-size:9px;letter-spacing:2px;opacity:.75}
@media (max-width:720px){ .vega-say{font-size:11px} }

/* The card lights up with its building, so the link reads from either end. */
.region.lit{
  border-color:color-mix(in srgb,var(--cyan) 70%,transparent);
  box-shadow:0 0 0 1px color-mix(in srgb,var(--cyan) 30%,transparent), 0 0 22px rgba(87,224,224,.14);
}
.region{transition:border-color .18s ease-out, box-shadow .18s ease-out}

/* ─────────── THE ENTERING ───────────
   Everything here is scoped to .storeopen, which only exists while you are inside the RAD
   Store. With the door shut these rules select nothing, so the street — desktop included —
   cannot see them.

   The room is painted on the world canvas (z-index 0), and the copy panels and the nav sit
   in the document ABOVE it (z 10 and 20). So walking into the shop has to get the street's
   furniture out of the way, or you would be reading the RAD STORE card through the RAD
   Store's own ceiling. They fade rather than pop: the push-in is a camera move, and a
   camera move with things blinking out of it is a cut. */
.storeopen .scroller,
.storeopen .nav,
.storeopen .foot,
.storeopen #vega-link,
.storeopen #body-toggle,
.storeopen .vega-bubble{
  opacity:0;pointer-events:none;
}
/* .foot was missed the first time round and only a rendered pixel found it: the room is
   408px tall on a phone and does not reach the bottom of the screen, so "More destinations
   coming soon" and the whole link row sat UNDER the shop floor, on the street's own footer,
   in the middle of the shop. The old room happened to be tall enough to cover it. Nothing
   about the street may show through the room. */
.scroller,.nav,.foot{transition:opacity .5s ease-out}
/* No scroll while you are indoors. The world behind is frozen at the scroll position you
   tapped from (see storeScroll in world.js) so the shopfront the room grew out of is still
   exactly where it was when you leave again. */
.storeopen,.storeopen body{overflow:hidden}

.storeclose{
  display:none;
  position:fixed;top:14px;right:14px;z-index:40;
  align-items:center;gap:10px;
  background:rgba(10,13,16,.92);color:var(--text);
  border:1px solid color-mix(in srgb,var(--orange) 55%,transparent);
  border-radius:0;                      /* square chrome: this is a terminal, not iOS */
  font:inherit;font-size:11px;letter-spacing:1px;text-transform:uppercase;
  padding:9px 12px;cursor:pointer;
}
.storeopen .storeclose{display:flex}
.storeclose-x{font-size:15px;line-height:1;color:var(--orange)}
.storeclose:hover,.storeclose:focus-visible{
  border-color:var(--orange);
  box-shadow:0 0 0 1px color-mix(in srgb,var(--orange) 40%,transparent),0 0 18px rgba(232,132,60,.22);
  outline:none;
}
/* The label is the affordance on a desktop, where there is room for words. A phone gets the
   glyph and the whole 44px target, and the room gets the width back. */
@media (max-width:719px){
  .storeclose-t{display:none}
  .storeclose{padding:0;width:44px;height:44px;justify-content:center;top:10px;right:10px}
  .storeclose-x{font-size:20px}
}

/* The cart, opposite the way out. Same chrome, same square corners: the two are a pair and a
   row of buttons matches heights. The count stays dim until there is something in it — a
   bright "0" is a shop nagging you about a cart you have not got. */
.storecart{
  display:none;
  position:fixed;top:14px;left:14px;z-index:40;
  align-items:center;gap:8px;height:35px;
  background:rgba(10,13,16,.92);color:var(--text);
  border:1px solid color-mix(in srgb,var(--orange) 55%,transparent);
  border-radius:0;
  font:inherit;font-size:11px;letter-spacing:1px;text-transform:uppercase;
  padding:0 12px;cursor:pointer;
}
.storeopen .storecart{display:flex}
.storecart-n{
  min-width:18px;height:18px;line-height:18px;text-align:center;
  background:rgba(255,255,255,.08);color:var(--text2);
  font-size:10px;letter-spacing:0;
}
.storecart[data-any="1"] .storecart-n{background:var(--orange);color:#0a0d10}
.storecart:hover,.storecart:focus-visible{
  border-color:var(--orange);
  box-shadow:0 0 0 1px color-mix(in srgb,var(--orange) 40%,transparent),0 0 18px rgba(232,132,60,.22);
  outline:none;
}
@media (max-width:719px){
  .storecart{top:10px;left:10px;height:44px;padding:0 12px}
}

/* THE ROOM PANS BY FINGER. Without this the browser claims a horizontal drag for itself
   before a pointermove ever fires, and the rail simply does not move on a phone. Scoped to
   .storeopen: with the door shut it selects nothing, so the street's canvas keeps its default
   touch behaviour and desktop is untouched. */
.storeopen #world{touch-action:none}
