/* Homepage room. Green means "this is a link" and is used for nothing else. */
:root {
  --bg: #000;
  --ink: #c9c9c9;
  --plane: #1b1b1b;
  --go: #3fe06a;
  --dead: #474747;
  --mono: ui-monospace, "SFMono-Regular", Menlo, Consolas, "Liberation Mono", monospace;
}

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; height: 100%; background: var(--bg); overflow: hidden; }

.vh {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- stage: fixed aspect, sized by the visible viewport ---------- */
.room { position: fixed; inset: 0; display: grid; place-items: center; }

.stage {
  position: relative;
  aspect-ratio: 16 / 9;
  width: min(100vw, 100svh * 16 / 9);
  width: min(100vw, 100dvh * 16 / 9);
}

.scene {
  position: absolute; inset: 0; width: 100%; height: 100%;
  display: block; overflow: visible;
  --ink-w: 1.6px;
}
/* Portrait draws its objects small, so its lines are lighter than desktop's:
   at 2.4px the detailed drawings (fan grille, bike, junk) turned to mush. */
.scene-portrait { display: none; --ink-w: 1.4px; }

@media (max-aspect-ratio: 1/1) {
  .stage {
    aspect-ratio: 9 / 16;
    width: min(100vw, 100svh * 9 / 16);
    width: min(100vw, 100dvh * 9 / 16);
  }
  .scene-landscape { display: none; }
  .scene-portrait { display: block; }
}

/* dev override (/?dev); must come after the media query */
html[data-force="landscape"] .stage { aspect-ratio: 16 / 9; width: min(100vw, 100dvh * 16 / 9); }
html[data-force="landscape"] .scene-landscape { display: block; }
html[data-force="landscape"] .scene-portrait { display: none; }
html[data-force="portrait"] .stage { aspect-ratio: 9 / 16; width: min(100vw, 100dvh * 9 / 16); }
html[data-force="portrait"] .scene-landscape { display: none; }
html[data-force="portrait"] .scene-portrait { display: block; }

/* ---------- line art ---------- */
.ink {
  fill: none;
  stroke: var(--ink);
  stroke-width: var(--ink-w);
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  pointer-events: none;
}
.ink2 { opacity: 0.5; }
.cord { stroke-width: calc(var(--ink-w) * 1.7); }

.obj .fill { fill: var(--bg); }
.obj .plane { fill: var(--plane); pointer-events: none; }
.obj .screen { fill: none; stroke: none; pointer-events: none; }
.floor-stop { stop-color: var(--plane); }
.room-bg { pointer-events: none; }

/* Hit area = the closed outline. It is painted (bg colour, so objects behind
   are hidden) and pointer-events:all keeps it clickable whatever the fill. */
.link { cursor: pointer; outline: none; }
.link .fill { pointer-events: all; }
.link .fill, .link .plane { transition: fill 0.12s; }
.link .ink { transition: stroke 0.12s; }
/* Lit: hovered (real hover only; phones fake a sticky one on tap), focused,
   pressed, or armed by a first tap on a touch screen (room.js). */
@media (hover: hover) {
  .link:hover .fill, .link:hover .plane { fill: var(--go); }
  .link:hover .ink { stroke: #000; }
  .link:hover .overlay { fill: #000; }
}
.link:focus-visible .fill, .link:focus-visible .plane,
.link:active .fill, .link:active .plane,
.link.armed .fill, .link.armed .plane { fill: var(--go); }
.link:focus-visible .ink, .link:active .ink, .link.armed .ink { stroke: #000; }
/* hand-added logos print in the line color and go black with the lines */
.obj .overlay { fill: var(--ink); pointer-events: none; transition: fill 0.12s; }
.link:focus-visible .overlay, .link:active .overlay, .link.armed .overlay { fill: #000; }

/* ---------- labels ---------- */
.label { pointer-events: none; opacity: 0; transition: opacity 0.12s; }
.label text { font-family: var(--mono); fill: var(--go); letter-spacing: 0.02em; }
.label rect { fill: var(--bg); }

/* Labels sit in their own top layer; room.js flags them from the link. */
.label.focus, .label.armed { opacity: 1; }
@media (hover: hover) {
  .label.hover { opacity: 1; }
}
/* Touch (decided 2026-10-11): data-touch-labels="tap" on <html>, the first tap
   lights an object and shows its label, the second goes. "always" keeps every
   label up; "none" hides them and taps go straight through. */
@media (hover: none) {
  html[data-touch-labels="always"] .label { opacity: 1; }
}
html[data-labels="always"] .label { opacity: 1; }
html[data-labels="none"] .label { opacity: 0; }

/* ---------- neon sign (a title, not a link) ---------- */
.sign { pointer-events: none; }
.sign text { font-family: "Tilt Neon", system-ui, sans-serif; text-anchor: middle; letter-spacing: 0.04em; }
/* A thin stroke on the core makes every font read as a tube, even hairlines. */
.sign .halo { fill: #fff; stroke: #fff; stroke-width: 4; opacity: 0.38; }
.sign .sign-box { fill: var(--plane); }
/* traced sign: glass tubes glow, the wires are plain room lines */
.sign-art .tube-halo path, .sign-art .tube-core path {
  fill: none; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke;
}
.sign-art .tube-halo path { stroke: #fff; stroke-width: 7px; opacity: 0.4; }
.sign-art .tube-core path { stroke: #fafafa; stroke-width: 2.6px; }
.sign-art .tube-core .dead { stroke: var(--dead); }
.sign-art .tube-halo .dead { display: none; }
/* the sign is much smaller on a phone: thinner tubes so letters don't smear */
.scene-portrait .sign-art .tube-halo path { stroke-width: 4px; }
.scene-portrait .sign-art .tube-core path { stroke-width: 1.6px; }
.sign .core { fill: #fafafa; stroke: #fafafa; stroke-width: 1.6; stroke-linejoin: round; }
.sign .core .dead { fill: var(--dead); stroke: var(--dead); }
.sign .halo .dead { fill-opacity: 0; stroke-opacity: 0; }

@media (prefers-reduced-motion: no-preference) {
  .sign .flicker { animation: flicker 7s infinite steps(1, end); }
}
@keyframes flicker {
  0%, 61%, 63%, 66%, 100% { opacity: 1; }
  62%, 64.5% { opacity: 0.15; }
  65% { opacity: 0.6; }
  88% { opacity: 1; }
  88.4% { opacity: 0.2; }
  88.8% { opacity: 1; }
}

/* ---------- the one video, laid over the visible CRT ---------- */
.crt-video {
  position: absolute;
  object-fit: cover;
  pointer-events: none;
  background: #0c0c0c;
}
.crt-video[hidden] { display: none; }

/* ---------- no-JS fallback ---------- */
.nojs { position: fixed; left: 16px; bottom: 16px; font-family: var(--mono); }
.nojs a { color: var(--go); display: block; }

/* ---------- dev tools (/?dev only) ---------- */
html.dev-hits .obj .fill { stroke: #39c6ff; stroke-width: 1px; stroke-dasharray: 4 3; vector-effect: non-scaling-stroke; }
html.dev-hits .decoy .fill { stroke: #777; }
html.dev-drag .obj { cursor: move; }
html.dev-drag .sign { pointer-events: bounding-box; cursor: move; }
.sign.dev-selected { outline: 1px dashed #39c6ff; }
.dev-selected .ink { stroke: #39c6ff !important; }

.dev-panel {
  position: fixed; left: 8px; bottom: 8px; z-index: 10;
  font: 11px/1.5 var(--mono); color: #aaa;
  background: rgba(0, 0, 0, 0.85); border: 1px solid #333; padding: 6px 8px;
  max-width: calc(100vw - 16px);
}
.dev-panel.dev-hidden { display: none; }
.dev-row { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; margin-top: 4px; }
.dev-row span { width: 44px; color: #666; }
.dev-panel button {
  font: inherit; color: #bbb; background: #111; border: 1px solid #333; padding: 1px 6px; cursor: pointer;
}
.dev-panel button[aria-pressed="true"] { color: #000; background: #ddd; border-color: #ddd; }
.dev-sel { color: #39c6ff; margin-top: 4px; min-height: 1.5em; }
