/* Aurora Village resort map: night-glass interface with gold hairlines.
   Theme tokens at the top; swap fonts and accents to re-brand for another resort. */
:root {
  --font-display: 'Cormorant Garamond', 'Times New Roman', serif;
  --font-ui: 'Manrope', system-ui, sans-serif;
  --gold: #d2b46e;
  --gold-deep: #b7994d;
  --ink: #0b0f17;
  --glass: rgba(14, 18, 27, 0.66);
  --glass-strong: rgba(12, 16, 24, 0.86);
  --shell: rgba(255, 255, 255, 0.055);
  --hair: rgba(255, 255, 255, 0.09);
  --hair-strong: rgba(255, 255, 255, 0.16);
  --text: #f4efe6;
  --muted: rgba(244, 239, 230, 0.58);
  --faint: rgba(244, 239, 230, 0.36);
  --r-xl: 28px;
  --r-lg: 22px;
  --ease: cubic-bezier(0.32, 0.72, 0, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --c-cabin: #e8b04a;
  --c-suite: #c9a961;
  --c-tower: #8fb0d8;
  --c-towerSuite: #b8a3e0;
  --unit-badge: 21px; /* WS-15: unit number badge height (was 24px); resort.json brand.unitBadge overrides */
}
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; overflow: hidden; background: var(--ink); color: var(--text); font: 400 14px/1.55 var(--font-ui); -webkit-font-smoothing: antialiased; user-select: none; -webkit-user-select: none; }
#scene { position: fixed; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; }
button { font: inherit; color: inherit; cursor: pointer; border: 0; background: none; padding: 0; }
.ic { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.25; stroke-linecap: round; stroke-linejoin: round; flex: none; }
.grain { position: fixed; inset: 0; pointer-events: none; z-index: 30; opacity: 0.035; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); }

/* ------------------------------------------------ double-bezel shells */
.shell { background: var(--shell); border: 1px solid var(--hair); border-radius: var(--r-xl); padding: 5px; backdrop-filter: blur(22px) saturate(1.3); -webkit-backdrop-filter: blur(22px) saturate(1.3);
  box-shadow: 0 30px 60px -30px rgba(3, 6, 14, 0.55), 0 2px 6px rgba(3, 6, 14, 0.12); }
.shell > .core { background: var(--glass); border-radius: calc(var(--r-xl) - 5px); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08); height: 100%; }
.eyebrow { font: 500 10px/1 var(--font-ui); letter-spacing: 0.22em; text-transform: uppercase; color: var(--gold); }
.eyebrow.pill { display: inline-flex; align-items: center; gap: 7px; padding: 6px 11px 6px 9px; border-radius: 999px; background: color-mix(in srgb, var(--c) 14%, transparent); color: var(--c); border: 1px solid color-mix(in srgb, var(--c) 28%, transparent); }
.eyebrow.pill .ic { width: 13px; height: 13px; }

.round-btn { width: 40px; height: 40px; display: inline-grid; place-items: center; border-radius: 50%; background: var(--glass); border: 1px solid var(--hair); color: var(--text);
  backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px); transition: transform 0.5s var(--ease), background 0.4s var(--ease), border-color 0.4s var(--ease), color 0.4s var(--ease); }
.round-btn:hover { background: rgba(30, 36, 50, 0.85); border-color: var(--hair-strong); }
.round-btn:active { transform: scale(0.94); }
.round-btn.small { width: 32px; height: 32px; }
.round-btn.small .ic { width: 15px; height: 15px; }
.round-btn.toggle.on { color: var(--ink); background: var(--gold); border-color: transparent; }
.pill-btn { display: inline-flex; align-items: center; gap: 9px; height: 44px; padding: 0 18px 0 14px; border-radius: 999px; font-size: 13px; letter-spacing: 0.02em; transition: transform 0.5s var(--ease), background 0.4s var(--ease); }
.shell-btn { background: var(--glass); border: 1px solid var(--hair); backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px); }
.shell-btn:hover { background: rgba(30, 36, 50, 0.85); }
.shell-btn:active { transform: scale(0.97); }
.shell-btn.on { background: var(--gold); color: var(--ink); }

/* ------------------------------------------------ loader
   One look for every map style (owner 2026-10-18; redesigned to his picks of 2026-11-05). The client sets its picture,
   veil colour and strength, slow zoom, name, logo and height lines on the portal's Map style page; js/loader.js reads
   them from the boot meta `mapmystay-loader` and applies them before anything else loads. No twitch: the words wait
   (hidden) until their own font is in, and the loader keeps its own fonts (--ld-display, --ld-ui), so the brand fonts
   and the style arriving later change nothing on it.
   Computers ("Horizon", the wide block below): one row near the lower middle, the logo left of the name and centred on
   its capitals, the step's words | the percentage at the right of the same row, the comet bar under it. Phones and any
   tall or small screen ("Quiet line"): a centred stack, logo, name, comet bar, words | %. "3D map made by Map My Stay"
   at the bottom. An SVG logo drawn for dark grounds traces its outline, then fills (js/loader.js builds it inline). */
/* the styles' two fonts for the loader alone (the same files css/styles/brand-dark.css names; fetched only when a
   style's loader shows words in them) */
@font-face { font-family: 'Cal Sans'; font-weight: 400; font-display: swap; src: url(styles/fonts/CalSans-Regular.h-304325fde5.woff2) format('woff2'); }
@font-face { font-family: 'Poppins'; font-weight: 500; font-display: swap; src: url(styles/fonts/poppins-latin-500-normal.h-cd36de204a.woff2) format('woff2'); }
#loader { --p: 0.03; --ld-tint: #0b0f17; --ld-dim: 0.5; --ld-accent: var(--gold); --ld-glow: #1a2742;
  --ld-display: 'Cormorant Garamond', 'Times New Roman', serif; --ld-ui: 'Manrope', system-ui, sans-serif;
  --ld-fs: clamp(16px, 8.6vw, 54px); --ld-lgh: clamp(30px, 17vw, 110px); --ld-bw: 60vw; --ld-ws: clamp(10px, 3.4vw, 16px); /* Quiet line */
  --ld-name-at: 0.9s; --ld-rest-at: 1.3s; /* after the logo has drawn most of itself (no logo: .ld-solo) */
  position: fixed; inset: 0; z-index: 40; display: flex; align-items: center; justify-content: center; overflow: hidden;
  background: var(--ld-tint); background: radial-gradient(130% 95% at 50% 12%, var(--ld-glow) 0%, var(--ld-tint) 62%);
  transition: opacity 1.1s var(--ease), visibility 1.1s; }
#loader[data-style] { --ld-display: 'Cal Sans', system-ui, sans-serif; --ld-ui: 'Poppins', system-ui, sans-serif; --ld-accent: #CFC3B2; --ld-tint: #101a26; --ld-glow: #22344a; }
#loader.ld-solo { --ld-name-at: 0.15s; --ld-rest-at: 0.5s; }
body.ready #loader { opacity: 0; visibility: hidden; pointer-events: none; } /* the fading loader never takes a press meant for the map (visibility only turns hidden at the end of its 1.1 s fade) */
#loader .ld-pic { position: absolute; inset: 0; background: center / cover no-repeat; opacity: 0; transform: scale(1.08); transition: opacity 1.4s ease, transform 30s linear; } /* the very slow zoom */
#loader.has-pic .ld-pic { opacity: 1; transform: scale(1); }
#loader.no-motion .ld-pic { transform: none; }
#loader .ld-veil { position: absolute; inset: 0; opacity: 0; transition: opacity 1.4s ease;
  background: radial-gradient(48% 40% at 50% 50%, rgba(0, 0, 0, 0.32), transparent), linear-gradient(rgba(0, 0, 0, 0.12), rgba(0, 0, 0, 0.42)); }
#loader .ld-veil::before { content: ''; position: absolute; inset: 0; background: var(--ld-tint); opacity: var(--ld-dim); }
#loader.has-pic .ld-veil { opacity: 1; }
body.ready #loader .ld-pic { transform: scale(1.03); transition-duration: 1.1s; }
#loader .ld-lines { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; opacity: 0; transition: opacity 1.2s ease; } /* "Fine survey" (js/loader.js): fades in once built */
#loader .ld-lines.is-in { opacity: 1; }
.loader-inner { position: relative; z-index: 2; display: flex; flex-direction: column; align-items: center; gap: 4.6vw; max-width: 100%; padding: 0 24px 6vh; box-sizing: border-box; text-align: center; color: #F3F5F8; }
.loader-inner .ld-say { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.loader-inner .ld-id { display: flex; flex-direction: column; align-items: center; gap: 4vw; max-width: 100%; }
.loader-inner h2 { margin: 0; max-width: 16em; font: 400 var(--ld-fs)/1.08 var(--ld-display); letter-spacing: 0.01em; text-wrap: balance; text-shadow: 0 2px 30px rgba(0, 0, 0, 0.3); opacity: 0; }
#loader:not([data-style]) .loader-inner h2 { letter-spacing: 0.02em; }
#loader.is-in .loader-inner h2 { animation: ld-name 1.4s cubic-bezier(0.2, 0.7, 0.2, 1) var(--ld-name-at) both; }
@keyframes ld-name { from { opacity: 0; letter-spacing: 0.1em; filter: blur(4px); } to { opacity: 1; filter: blur(0); } }
@keyframes ld-fade { from { opacity: 0; } to { opacity: 1; } }
/* the logo: a picture fades in when its file is in; an SVG drawn for dark grounds (js/loader.js) traces its outline per
   part (pathLength 1, a dash run out), then its fill fades in; a faint sheen passes over it every 7 s afterwards */
.loader-inner .ld-logo { display: flex; align-items: center; gap: calc(var(--ld-lgh) * 0.28); }
.loader-inner .ld-logo img { display: block; box-sizing: border-box; width: var(--ld-lgh); height: var(--ld-lgh); border-radius: 50%; background: #fff; padding: calc(var(--ld-lgh) * 0.11); opacity: 0; transition: opacity 0.7s ease;
  box-shadow: 0 0 0 1px var(--hair), 0 0 60px rgba(210, 180, 110, 0.25); }
.loader-inner .ld-logo img:not([src]), .loader-inner .ld-logo img[hidden] { display: none; }
.loader-inner .ld-logo img.is-in { opacity: 1; }
.ld-lg { position: relative; display: inline-grid; height: var(--ld-lgh); }
.ld-lg.is-wide { height: calc(var(--ld-lgh) * 0.42); }
.ld-sep { width: 1px; height: calc(var(--ld-lgh) * 0.7); background: rgba(255, 255, 255, 0.3); }
.ld-sep + .ld-lg { height: calc(var(--ld-lgh) * 0.82); }
.ld-sep[hidden] { display: none; }
.ld-lg > svg { grid-area: 1 / 1; display: block; width: auto; height: 100%; overflow: visible; }
.ld-lg .ld-fl { opacity: 0; }
.ld-lg .ld-ds path { fill: none; stroke: var(--lc); stroke-width: var(--sw); stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1 1; stroke-dashoffset: 1; opacity: 0; }
.ld-lg .ld-sh { opacity: 0; fill: #fff3d8; mix-blend-mode: screen; pointer-events: none;
  -webkit-mask: linear-gradient(100deg, transparent 36%, #000 50%, transparent 64%) 0 0 / 300% 100% no-repeat; mask: linear-gradient(100deg, transparent 36%, #000 50%, transparent 64%) 0 0 / 300% 100% no-repeat; }
#loader.is-in .ld-lg .ld-ds path { animation: ld-draw 2.7s cubic-bezier(0.55, 0, 0.25, 1) calc(var(--i) * 90ms) both; }
#loader.is-in .ld-lg .ld-fl { animation: ld-fade 1s ease 1.55s both; }
#loader.is-in .ld-lg .ld-sh { animation: ld-sheen 7s ease-in-out 3.8s infinite; }
body.ready #loader .ld-lg .ld-sh { animation: none; }
@keyframes ld-draw { 0% { stroke-dashoffset: 1; opacity: 1; } 68% { stroke-dashoffset: 0; opacity: 1; } 100% { stroke-dashoffset: 0; opacity: 0; } }
@keyframes ld-sheen { 0% { -webkit-mask-position: 100% 0; mask-position: 100% 0; opacity: 0; } 6% { opacity: 0.5; } 26% { -webkit-mask-position: 0 0; mask-position: 0 0; opacity: 0.5; } 30%, 100% { -webkit-mask-position: 0 0; mask-position: 0 0; opacity: 0; } }
/* the comet bar: the filled part fades in from nothing to a bright tip, a soft glow just behind it; moved by transforms
   alone, so it glides on while the page is busy */
.loader-inner .ld-bar { position: relative; width: var(--ld-bw); max-width: 100%; height: 1px; background: linear-gradient(90deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0.11)); }
.ld-bar i { position: absolute; inset: 0; transform-origin: left; transform: scaleX(var(--p)); transition: transform 0.6s var(--ease);
  background: linear-gradient(90deg, transparent, var(--ld-accent)); background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--ld-accent), transparent 50%) 55%, var(--ld-accent)); }
.ld-bar b { position: absolute; inset: 0; transform: translateX(calc((var(--p) - 1) * 100%)); transition: transform 0.6s var(--ease); }
.ld-bar b::before { content: ''; position: absolute; top: -1px; right: 0; width: 9vmin; height: 3px; border-radius: 3px; filter: blur(1.5px);
  background: linear-gradient(90deg, transparent, var(--ld-accent)); background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--ld-accent), #fff 40%)); }
.ld-bar b::after { content: ''; position: absolute; top: -1.5px; right: -2px; width: 4px; height: 4px; border-radius: 50%; background: #fff;
  box-shadow: 0 0 8px 2px var(--ld-accent), 0 0 24px 6px var(--ld-accent); box-shadow: 0 0 8px 2px var(--ld-accent), 0 0 24px 6px color-mix(in srgb, var(--ld-accent), transparent 60%); }
/* the step's words and the percentage on one line: the words left-aligned in a box as wide as the longest step (every
   step's words stacked unseen in the same grid cell), so the number never moves */
.loader-inner .ld-words { display: flex; align-items: baseline; font: 500 var(--ld-ws)/1.25 var(--ld-ui); letter-spacing: 0.04em; color: rgba(243, 245, 248, 0.72); white-space: nowrap; }
.ld-wbox { display: grid; text-align: left; }
.ld-wbox > * { grid-area: 1 / 1; }
.ld-wbox .ld-sizer { visibility: hidden; font-style: normal; }
.ld-wbox span { transition: opacity 0.55s ease, translate 0.7s cubic-bezier(0.2, 0.7, 0.2, 1), filter 0.55s ease; }
.ld-wbox span.pre { opacity: 0; translate: 0 0.4em; filter: blur(3px); }
.ld-wbox span.out { opacity: 0; translate: 0 -0.4em; filter: blur(3px); }
.ld-num { display: inline-flex; align-items: baseline; font-size: 1.5em; line-height: 1; color: #fff; font-variant-numeric: tabular-nums; letter-spacing: 0.01em; }
.ld-num::before { content: ''; align-self: center; width: 1px; height: 0.62em; margin: 0 0.7em 0 0.62em; background: rgba(255, 255, 255, 0.26); }
.ld-num b { min-width: 2ch; font-weight: inherit; text-align: right; }
.ld-num i { margin-left: 0.14em; font-size: 0.52em; font-style: normal; color: rgba(255, 255, 255, 0.55); }
#loader .ld-credit { position: absolute; left: 0; right: 0; bottom: max(4.2vh, env(safe-area-inset-bottom)); z-index: 2; display: flex; justify-content: center; align-items: center; gap: 0.55em; margin: 0; padding: 0 16px;
  font: 500 clamp(9px, 1.9vmin, 13px)/1 var(--ld-ui); letter-spacing: 0.06em; color: rgba(243, 245, 248, 0.55); }
#loader .ld-credit[hidden], #loader[data-state="cover"] .ld-credit, #loader[data-state="opening"] .ld-credit { display: none; }
.ld-mark svg { display: block; width: auto; height: 1.6em; fill: rgba(243, 245, 248, 0.75); }
.loader-inner .ld-words, .loader-inner .ld-bar, #loader .ld-credit { opacity: 0; }
#loader.is-in :is(.loader-inner .ld-words, .loader-inner .ld-bar, .ld-credit) { animation: ld-fade 1s ease var(--ld-rest-at) both; }
/* Horizon: on a screen wider than tall and at least 640 px, unless a start failed (its message keeps the stack). The
   name's box is trimmed to its capitals and the logo, in a box of no height, is centred on it: on the capitals' middle */
@media (min-width: 640px) and (min-aspect-ratio: 1/1) {
  #loader:not([data-state="failed"]) { --ld-fs: clamp(18px, 7.6vmin, 100px); --ld-lgh: calc(var(--ld-fs) * 1.3); --ld-bw: 100%; --ld-ws: clamp(10px, 2.35vmin, 17px); }
  #loader:not([data-state="failed"]) .loader-inner { position: absolute; left: 7vw; right: 7vw; bottom: 41vh; flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: 5.4vmin 0; padding: 0; text-align: left; }
  #loader:not([data-state="failed"]) .ld-id { flex-direction: row; align-items: baseline; gap: calc(var(--ld-fs) * 0.36); min-width: 0; }
  #loader:not([data-state="failed"]) .ld-logo { align-self: center; height: 0; }
  #loader:not([data-state="failed"]) .loader-inner h2 { max-width: 14em; line-height: 1; text-box: trim-both cap alphabetic; }
  #loader:not([data-state="failed"]) .ld-words { order: 2; margin-left: auto; padding-left: 4vw; }
  #loader:not([data-state="failed"]) .ld-bar { order: 3; flex-basis: 100%; }
  #loader:not([data-state="failed"]) .ld-lighter { order: 4; flex-basis: 100%; margin: 0; max-width: none; text-align: left; }
  #loader .ld-credit { justify-content: flex-end; padding-right: 7vw; }
}
.loader-inner .ld-lighter { margin: 0; max-width: 22em; font: 500 14px/1.4 var(--ld-ui); color: rgba(255, 255, 255, 0.92); text-wrap: balance; text-shadow: 0 1px 12px rgba(0, 0, 0, 0.35); } /* the rescue set's start (js/loader.js) */
#loader[data-state="failed"] .ld-lighter { display: none; }
#loader.no-name h2, #loader.no-logo .ld-logo { display: none; }
@media (prefers-reduced-motion: reduce) {
  #loader .ld-pic { transition: opacity 1.4s ease; transform: none; }
  #loader .ld-lg .ld-ds, #loader .ld-lg .ld-sh { display: none; }
  #loader.is-in .ld-lg .ld-fl { animation-duration: 0.4s; animation-delay: 0s; }
  #loader.is-in .loader-inner h2 { animation: ld-fade 0.6s ease 0.1s both; }
  .ld-wbox span { transition: opacity 0.3s ease; }
  .ld-wbox span.pre, .ld-wbox span.out { translate: none; filter: none; }
}
/* VIS-206 (begin): a start that failed (js/loader.js, data-state="failed"; owner's pick, canvas row 3): the still
   picture under a stronger veil, the resort's logo and name, a short rule in the accent, the words and the buttons the
   reason allows. It shows over a map that was already up too (a lost device). A small website box keeps the words. */
body.ready #loader[data-state="failed"] { opacity: 1; visibility: visible; pointer-events: auto; }
body:has(#loader[data-state="failed"]) #chrome, body:has(#loader[data-state="failed"]) #labels { visibility: hidden; }
#loader[data-state="failed"] :is(.ld-bar, .ld-words) { display: none; }
#loader[data-state="failed"] .ld-veil { opacity: 1; }
#loader[data-state="failed"] .ld-veil::before { opacity: max(var(--ld-dim), 0.62); }
#loader[data-state="failed"] .loader-inner h2, #loader[data-state="failed"] .ld-lg .ld-fl { animation: none; opacity: 1; filter: none; }
#loader[data-state="failed"] .ld-lg :is(.ld-ds, .ld-sh) { display: none; }
#loader .ld-fail { display: flex; flex-direction: column; align-items: center; gap: 10px; color: #F8F6F0; font: 400 14px/1.5 var(--ld-ui); }
#loader .ld-fail[hidden] { display: none; }
#loader .ld-rule { display: block; width: 36px; height: 2px; margin: 14px 0 4px; border-radius: 2px; background: var(--ld-accent); }
#loader .ld-fail h3 { margin: 0; font: 600 18px/1.3 var(--ld-ui); text-wrap: balance; }
#loader .ld-fail p { margin: 0; max-width: 30em; color: rgba(248, 246, 240, 0.8); text-wrap: pretty; }
#loader .ld-acts { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; margin-top: 8px; }
#loader .ld-acts button { min-height: 44px; padding: 0 20px; border-radius: 999px; border: 0; background: #F8F6F0; color: var(--cv-ink, #16222e); font: 500 14px var(--ld-ui); cursor: pointer; transition: transform 0.15s var(--ease), background 0.2s ease; }
#loader .ld-acts [data-act="wait"]:not([hidden]) + [data-act="retry"] { background: rgba(248, 246, 240, 0.08); color: #F8F6F0; box-shadow: inset 0 0 0 1px rgba(248, 246, 240, 0.35); }
#loader .ld-acts button:active { transform: scale(0.97); }
#loader .ld-acts button:focus-visible, #loader .ld-play:focus-visible, .ld-close:focus-visible { outline: 2px solid var(--ld-accent); outline-offset: 3px; }
#loader .ld-acts button[hidden] { display: none; }
@media (max-height: 420px) {
  #loader[data-state="failed"] { --ld-lgh: 44px; }
  #loader[data-state="failed"] .loader-inner h2 { font-size: 24px; }
  #loader .ld-rule { margin: 8px 0 2px; }
  #loader .ld-fail { gap: 6px; font-size: 13px; }
  #loader .ld-fail h3 { font-size: 16px; }
}
@media (max-height: 300px) { #loader[data-state="failed"] .ld-logo, #loader[data-state="failed"] .loader-inner h2, #loader .ld-rule { display: none; } }

/* The website cover (js/loader.js, data-state "cover", then "opening" after the click; owner's pick 1A, canvas row 1):
   the still picture without the slow zoom and the name, one centred glass button in the resort's own colours
   (--cv-ink, --ld-accent from the cover's brand). The whole picture takes the click. Back over a map that was opened
   and closed again on a phone: body.covered. */
#loader { --cv-ink: #16222e; }
#loader[data-state="cover"], #loader[data-state="opening"] { cursor: pointer; }
body.ready.covered #loader[data-state="cover"] { opacity: 1; visibility: visible; pointer-events: auto; }
#loader[data-state="cover"] .loader-inner, #loader[data-state="opening"] .loader-inner { display: none; }
#loader[data-state="cover"] .ld-pic, #loader[data-state="opening"] .ld-pic { transform: none; transition: opacity 0.6s ease, transform 0.6s var(--ease-out); }
#loader[data-state="cover"] .ld-veil::before { opacity: 0.12; }
#loader[data-state="opening"] .ld-veil::before { opacity: 0.3; }
#loader .ld-cover { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; padding: 0 16px; }
#loader:not([data-state="cover"]):not([data-state="opening"]) .ld-cover { display: none; }
#loader .ld-play, #loader .ld-pill { display: inline-flex; align-items: center; gap: 12px; height: 50px; padding: 0 24px 0 8px; border-radius: 999px; box-sizing: border-box;
  background: color-mix(in srgb, var(--cv-ink) 58%, transparent); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  border: 1px solid rgba(248, 246, 240, 0.3); color: #F8F6F0; font: 500 15px/1 var(--ld-ui); box-shadow: 0 10px 30px rgba(6, 12, 20, 0.35);
  transition: background 0.25s ease, color 0.25s ease, border-color 0.25s ease, transform 0.15s var(--ease); }
#loader .ld-play { cursor: pointer; max-width: 100%; }
#loader .ld-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#loader .ld-dot { flex: none; display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%; background: #F8F6F0; color: var(--cv-ink); transition: background 0.25s ease, color 0.25s ease; }
#loader .ld-dot svg { width: 14px; height: 14px; margin-left: 2px; fill: currentColor; }
@media (hover: hover) {
  #loader[data-state="cover"]:hover .ld-play { background: #F8F6F0; color: var(--cv-ink); border-color: #F8F6F0; }
  #loader[data-state="cover"]:hover .ld-dot { background: var(--cv-ink); color: #F8F6F0; }
  #loader[data-state="cover"]:hover .ld-pic { transform: scale(1.03); }
}
#loader[data-state="cover"]:active .ld-play { transform: scale(0.97); }
#loader[data-state="opening"] .ld-play { display: none; }
#loader .ld-opening { display: none; }
#loader[data-state="opening"] .ld-opening { display: flex; flex-direction: column; align-items: center; gap: 10px; }
#loader .ld-pill { flex-direction: column; justify-content: center; align-items: stretch; gap: 8px; width: 230px; height: 58px; padding: 0 24px; font-size: 14px; text-align: center; }
#loader .ld-o-bar { display: block; height: 3px; border-radius: 3px; background: rgba(248, 246, 240, 0.18); overflow: hidden; }
#loader .ld-o-bar span { display: block; height: 100%; border-radius: inherit; background: var(--ld-accent); transform-origin: left; transform: scaleX(var(--p)); transition: transform 0.6s var(--ease); }
#loader .ld-o-msg { min-height: 1.5em; font: 500 11px/1.5 var(--ld-ui); letter-spacing: 0.08em; text-transform: uppercase; color: rgba(248, 246, 240, 0.75); text-shadow: 0 1px 10px rgba(6, 12, 20, 0.6); }
@media (max-width: 380px), (max-height: 220px) {
  #loader .ld-play { height: 40px; gap: 9px; padding: 0 16px 0 6px; font-size: 13px; }
  #loader .ld-dot { width: 28px; height: 28px; }
  #loader .ld-dot svg { width: 12px; height: 12px; }
}
/* Close, for a map full window over a hotel's page (owner's pick 2A): only when the top's own button cannot be it */
.ld-close { position: fixed; z-index: 41; top: max(12px, env(safe-area-inset-top)); right: max(12px, env(safe-area-inset-right)); display: none; align-items: center; height: 40px; padding: 0 16px; border-radius: 999px;
  background: color-mix(in srgb, var(--cv-ink, #16222e) 62%, transparent); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px); border: 1px solid rgba(248, 246, 240, 0.22); color: #F8F6F0; font: 500 13px var(--ld-ui, system-ui); cursor: pointer; }
html[data-expanded] body.ready:not(.covered):not(:has(#full-btn[data-close])) .ld-close, html[data-expanded] #loader[data-state="failed"] ~ .ld-close { display: inline-flex; }
/* VIS-206 (end) */

/* ------------------------------------------------ brand + top actions */
.top-left { position: fixed; top: 20px; left: 20px; z-index: 10; display: flex; align-items: center; gap: 10px; } /* round 6: brand + season switch */
.brand { border-radius: 999px; }
.brand > .core { display: flex; align-items: center; gap: 12px; padding: 7px 22px 7px 7px; border-radius: 999px; }
.brand img { border-radius: 50%; background: #fff; padding: 3px; }
.brand h1 { margin: 0; font: 500 23px/1 var(--font-display); letter-spacing: 0.01em; }
.brand p { margin: 3px 0 0; font-size: 10px; letter-spacing: 0.22em; text-transform: uppercase; color: var(--muted); }
/* round 6: logo-only header (brand.showName false); a logo drawn for dark grounds sits bare (brand.logoPlate false) */
.brand.mark-only > .core { padding: 7px 16px; }
.brand.mark-only img { width: auto; height: 40px; }
[data-logo="bare"] .brand img, [data-logo="bare"] .loader-inner .ld-logo img { background: none; border-radius: 0; padding: 0; box-shadow: none; }
[data-logo="bare"] .loader-inner .ld-logo img { width: auto; max-width: calc(var(--ld-lgh) * 3); height: var(--ld-lgh); filter: drop-shadow(0 2px 24px rgba(0, 0, 0, 0.35)); }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; margin: 0; }
/* round 6: season switch (ui.seasons) */
.seasons { display: flex; gap: 3px; padding: 4px; border-radius: 999px; background: var(--glass); border: 1px solid var(--hair); backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px);
  box-shadow: 0 30px 60px -30px rgba(3, 6, 14, 0.55); }
.season { position: relative; display: inline-flex; align-items: center; gap: 7px; height: 38px; padding: 0 15px 0 12px; border-radius: 999px; color: var(--muted); font-size: 12.5px; letter-spacing: 0.02em;
  transition: background 0.45s var(--ease), color 0.45s var(--ease); }
.season .ic { width: 16px; height: 16px; }
.season:hover { color: var(--text); background: rgba(255, 255, 255, 0.05); }
.season.on { background: var(--gold); color: var(--ink); }
.season .soon { font-style: normal; font-size: 8.5px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; padding: 2px 5px; border-radius: 6px; color: var(--gold); border: 1px solid color-mix(in srgb, var(--gold) 40%, transparent); }
.season.on .soon { color: var(--ink); border-color: rgba(11, 15, 23, 0.3); }
.season:focus-visible, .date:focus-visible, #explore-fold:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.top-actions { position: fixed; top: 24px; right: 24px; z-index: 10; display: flex; gap: 8px; transition: transform 0.7s var(--ease), opacity 0.5s; }
body.card-open .top-actions { transform: translateX(-412px); }

/* ------------------------------------------------ explore panel */
#explore { position: fixed; top: 92px; left: 20px; bottom: 20px; width: 330px; z-index: 9; }
#explore > .core { display: flex; flex-direction: column; overflow: hidden; }
.explore-head { padding: 20px 20px 10px; display: grid; gap: 12px; }
/* round 6: collapsible panel */
.explore-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin: -6px -6px 0 0; }
#explore-fold .ic { transition: transform 0.6s var(--ease); }
@media (min-width: 761px) {
  body.explore-collapsed #explore { bottom: auto; }
  body.explore-collapsed #explore #search, body.explore-collapsed #explore .cats, body.explore-collapsed #explore #browse, body.explore-collapsed #explore .legend { display: none; }
  body.explore-collapsed .explore-head { padding: 14px 14px 14px 20px; }
  body.explore-collapsed .explore-top { margin: 0; }
  body.explore-collapsed .explore-top .eyebrow { cursor: pointer; }
  body.explore-collapsed #explore-fold .ic { transform: rotate(180deg); }
  body:not(.explore-collapsed) #explore .cats, body:not(.explore-collapsed) #explore #browse { animation: chrome-in 0.7s var(--ease-out) both; }
}
#search { position: relative; }
#search .ic { position: absolute; left: 13px; top: 50%; transform: translateY(-50%); color: var(--faint); width: 16px; }
#search input { width: 100%; height: 42px; padding: 0 14px 0 38px; border-radius: 999px; border: 1px solid var(--hair); background: rgba(255, 255, 255, 0.04); color: var(--text); font: inherit; outline: none; transition: border-color 0.4s var(--ease), background 0.4s var(--ease); }
#search input::placeholder { color: var(--faint); }
#search input:focus { border-color: color-mix(in srgb, var(--gold) 60%, transparent); background: rgba(255, 255, 255, 0.07); }
#search.miss input { animation: shake 0.4s var(--ease); border-color: #c46a5a; }
@keyframes shake { 30% { transform: translateX(-5px); } 70% { transform: translateX(4px); } }
.cats { display: flex; gap: 6px; padding: 4px 20px 12px; overflow-x: auto; scrollbar-width: none; }
.cats::-webkit-scrollbar { display: none; }
.cat { display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 12px; border-radius: 999px; border: 1px solid var(--hair); color: var(--muted); font-size: 12px; white-space: nowrap; transition: all 0.45s var(--ease); }
.cat .ic { width: 14px; height: 14px; }
.cat:hover { color: var(--text); border-color: var(--hair-strong); }
.cat.on { background: var(--text); color: var(--ink); border-color: transparent; }
#browse { flex: 1; overflow-y: auto; padding: 0 10px 16px; scrollbar-width: thin; scrollbar-color: var(--hair-strong) transparent; }
#browse h3 { margin: 16px 10px 6px; font: 500 10px/1 var(--font-ui); letter-spacing: 0.22em; text-transform: uppercase; color: var(--faint); }
#browse .item { display: flex; align-items: center; gap: 12px; width: 100%; padding: 8px 10px; border-radius: 16px; text-align: left; transition: background 0.45s var(--ease), transform 0.6s var(--ease);
  animation: rise 0.8s var(--ease-out) both; animation-delay: var(--d); }
@keyframes rise { from { opacity: 0; transform: translateY(14px); filter: blur(4px); } to { opacity: 1; transform: none; filter: none; } }
#browse .item:hover { background: rgba(255, 255, 255, 0.06); }
#browse .thumb { width: 46px; height: 46px; border-radius: 12px; overflow: hidden; flex: none; background: linear-gradient(135deg, #24324c, #121827); box-shadow: inset 0 0 0 1px var(--hair); }
#browse .thumb img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.8s var(--ease); }
#browse .item:hover .thumb img { transform: scale(1.08); }
#browse .txt { flex: 1; min-width: 0; display: grid; }
#browse .txt b { font-weight: 500; font-size: 14px; }
#browse .txt small { color: var(--faint); font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#browse .num { font-size: 11px; color: var(--gold); max-width: 74px; text-align: right; line-height: 1.3; }
/* VIS-227: a single unit found by the search: its number on its type's photo */
#browse .thumb { position: relative; }
#browse .thumb .no { position: absolute; left: 4px; bottom: 4px; min-width: 18px; padding: 2px 5px; border-radius: 7px; background: var(--glass-strong); box-shadow: inset 0 0 0 1px var(--hair);
  color: var(--text); font: 600 11px/1.2 var(--font-ui); font-variant-numeric: tabular-nums; text-align: center; }
#browse .empty { color: var(--muted); padding: 20px; }

/* ------------------------------------------------ detail card */
#card { position: fixed; top: 20px; right: 20px; bottom: 84px; width: 392px; z-index: 11; padding: 5px; opacity: 0; pointer-events: none;
  transform: translateX(40px) scale(0.98); filter: blur(6px); transition: opacity 0.6s var(--ease), transform 0.8s var(--ease), filter 0.6s var(--ease); }
#card.open { opacity: 1; transform: none; filter: none; pointer-events: auto; }
#card > .core { overflow-y: auto; scrollbar-width: none; }
#card > .core::-webkit-scrollbar { display: none; }
#card .hero { position: relative; height: 230px; overflow: hidden; border-radius: calc(var(--r-xl) - 5px) calc(var(--r-xl) - 5px) 0 0; }
#card .hero img { width: 100%; height: 100%; object-fit: cover; transform: scale(1.06); animation: settle 1.6s var(--ease-out) forwards; }
@keyframes settle { to { transform: scale(1); } }
#card .hero::after { content: ''; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(10, 13, 20, 0) 45%, rgba(14, 18, 27, 0.95)); }
#card .hero-fallback { height: 100%; background: radial-gradient(80% 120% at 30% 10%, #2c4170, #121827); }
/* a place with no photo: no picture area (every style, card.js); the buttons it holds sit on the card's corner. The
   empty placeholder stays in the page (the styles size `.hero > :first-child`) but never shows. */
#card.no-photo .hero { display: contents; }
#card.no-photo .hero-fallback { display: none !important; }
#card.no-photo .hero::after, #card.no-photo .unit-no { display: none; }
#card .close { position: absolute; top: 14px; right: 14px; z-index: 2; background: rgba(8, 11, 18, 0.5); }
#card .unit-no { position: absolute; left: 22px; bottom: 6px; z-index: 2; font: 400 64px/1 var(--font-display); color: rgba(255, 255, 255, 0.92); letter-spacing: -0.01em; }
#card .body { padding: 16px 24px 26px; display: grid; gap: 14px; justify-items: start; }
#card h2 { margin: 0; font: 400 34px/1.04 var(--font-display); letter-spacing: 0.005em; }
#card .stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; width: 100%; }
#card .stats div { padding: 11px 12px; border-radius: 14px; background: rgba(255, 255, 255, 0.04); border: 1px solid var(--hair); }
#card .stats small { display: block; font-size: 10px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--faint); }
#card .stats b { display: block; margin-top: 3px; font-weight: 500; font-size: 13px; }
#card .blurb { margin: 0; color: var(--muted); font-size: 14px; line-height: 1.65; }
#card dl { display: grid; grid-template-columns: auto 1fr; gap: 8px 16px; margin: 0; width: 100%; padding: 14px 0; border-top: 1px solid var(--hair); border-bottom: 1px solid var(--hair); font-size: 13px; }
#card dt { color: var(--faint); }
#card dd { margin: 0; }
#card ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; font-size: 13px; color: var(--muted); }
#card li { display: flex; gap: 10px; align-items: flex-start; }
#card li .ic { width: 15px; height: 15px; color: var(--gold); margin-top: 2px; }
#card .actions { display: flex; align-items: center; justify-content: space-between; gap: 10px; width: 100%; margin-top: 4px; }
.cta { display: inline-flex; align-items: center; gap: 12px; height: 48px; padding: 0 6px 0 22px; border-radius: 999px; background: var(--gold); color: var(--ink); text-decoration: none; font-weight: 600; font-size: 13px; letter-spacing: 0.04em; transition: transform 0.5s var(--ease), background 0.4s var(--ease); }
.cta i { width: 36px; height: 36px; border-radius: 50%; display: grid; place-items: center; background: rgba(11, 15, 23, 0.12); transition: transform 0.6s var(--ease); }
.cta i .ic { width: 16px; height: 16px; }
.cta:hover { background: #dfc27e; }
.cta:hover i { transform: translate(2px, -1px) scale(1.06); }
.cta:active { transform: scale(0.98); }
.stepper { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
#card .confirm { margin: 0; font-size: 12px; color: #f0a3b3; }

/* ------------------------------------------------ time dock */
#dock { position: fixed; left: calc(50% - 10px); bottom: 20px; transform: translateX(-50%); z-index: 10; width: min(800px, calc(100% - 720px)); min-width: 600px; }
/* round 6: two rows, so the time slider gets the dock's full width (it was squeezed to ~150 px between the dates and the clock) */
#dock > .core { display: grid; grid-template-columns: 1fr auto; grid-template-areas: "dates readout" "line line"; align-items: center; gap: 0 16px; padding: 8px 18px 4px 8px; }
#dock .dates { grid-area: dates; } #dock .timeline { grid-area: line; margin: 0 2px 0 10px; } #dock .readout { grid-area: readout; justify-content: flex-end; }
.dates { display: flex; gap: 4px; }
.date { display: grid; justify-items: start; padding: 6px 10px; border-radius: 16px; color: var(--muted); transition: background 0.45s var(--ease), color 0.45s var(--ease); }
.date b { font: 500 12.5px/1.2 var(--font-ui); white-space: nowrap; }
.date small { font-size: 10px; letter-spacing: 0.08em; color: var(--faint); white-space: nowrap; }
.date:hover { background: rgba(255, 255, 255, 0.05); color: var(--text); }
.date.on { background: rgba(255, 255, 255, 0.09); color: var(--text); box-shadow: inset 0 0 0 1px var(--hair-strong); }
.date.on small { color: var(--gold); }
.date[hidden] { display: none; }
/* round 6: custom date chip; the native picker anchors on the invisible input inside it */
.date.custom { position: relative; }
.date.custom b { display: inline-flex; align-items: center; gap: 6px; }
.date.custom .ic { width: 13px; height: 13px; color: var(--gold); }
#date-pick { position: absolute; left: 0; bottom: 0; width: 100%; height: 1px; opacity: 0; pointer-events: none; border: 0; padding: 0; color-scheme: dark; }
/* WS-35: off-season notice on a service card */
#card .off-season { margin: 0 0 4px; padding: 7px 11px; border-radius: 10px; font-size: 12.5px; color: var(--text); background: rgba(255, 255, 255, 0.06); box-shadow: inset 0 0 0 1px var(--hair-strong); }
.timeline { position: relative; height: 52px; }
.timeline .curve { position: absolute; left: 0; right: 0; top: 0; width: 100%; height: 40px; overflow: visible; pointer-events: none; }
.curve .horizon { stroke: var(--hair-strong); stroke-width: 1; stroke-dasharray: 2 4; fill: none; vector-effect: non-scaling-stroke; }
.curve .sunline { stroke: var(--gold); stroke-width: 1.25; fill: none; opacity: 0.85; vector-effect: non-scaling-stroke; }
.curve .sundot { fill: #fff3d2; filter: drop-shadow(0 0 6px rgba(255, 210, 140, 0.9)); }
#hour { position: absolute; inset: 0 0 12px; width: 100%; height: 40px; margin: 0; background: transparent; -webkit-appearance: none; appearance: none; cursor: ew-resize; }
#hour::-webkit-slider-runnable-track { height: 40px; background: transparent; }
#hour::-moz-range-track { height: 40px; background: transparent; }
/* round 6: an 18 px grab zone around the 2 px hairline, so the thumb is easy to catch */
#hour { touch-action: none; }
#hour::-webkit-slider-thumb { -webkit-appearance: none; width: 18px; height: 40px; background: linear-gradient(90deg, transparent 8px, rgba(255, 255, 255, 0.6) 8px 10px, transparent 10px); border: 0; cursor: grab; }
#hour::-moz-range-thumb { width: 18px; height: 40px; background: linear-gradient(90deg, transparent 8px, rgba(255, 255, 255, 0.6) 8px 10px, transparent 10px); border: 0; border-radius: 0; cursor: grab; }
#hour:active::-webkit-slider-thumb { cursor: grabbing; background: linear-gradient(90deg, transparent 7px, var(--gold) 7px 11px, transparent 11px); }
#hour:active::-moz-range-thumb { cursor: grabbing; background: linear-gradient(90deg, transparent 7px, var(--gold) 7px 11px, transparent 11px); }
.ticks { position: absolute; left: 0; right: 0; bottom: 0; display: flex; justify-content: space-between; font-size: 9.5px; letter-spacing: 0.12em; color: var(--faint); pointer-events: none; }
.readout { display: flex; align-items: center; gap: 12px; min-width: 188px; }
.readout strong { display: block; font: 400 30px/1 var(--font-display); font-variant-numeric: tabular-nums; }
.readout small { display: block; font-size: 11px; color: var(--muted); white-space: nowrap; }

/* ------------------------------------------------ map controls + legend */
.controls { position: fixed; right: 20px; bottom: 26px; z-index: 12; display: flex; gap: 6px; align-items: center; padding: 4px; border-radius: 999px; background: rgba(255,255,255,0.05); border: 1px solid var(--hair); backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px); }
.controls .sep { width: 1px; height: 18px; background: var(--hair-strong); margin: 0 2px; }
.controls .round-btn { width: 36px; height: 36px; }
#compass { position: relative; }
#compass i { font: italic 500 13px/1 var(--font-display); color: var(--gold); position: absolute; inset: 0; display: grid; place-items: center; transform: rotate(var(--rot, 0rad)) translateY(-11px); }
#compass .needle { position: absolute; width: 1px; height: 12px; background: linear-gradient(var(--gold), transparent); transform: rotate(var(--rot, 0rad)) translateY(-1px); transform-origin: 50% 100%; top: 8px; }
.legend { display: flex; flex-wrap: wrap; gap: 6px 14px; padding: 12px 20px 16px; border-top: 1px solid var(--hair); font-size: 11px; color: var(--muted); }
.legend span { display: flex; align-items: center; gap: 8px; }
.dot { width: 9px; height: 9px; border-radius: 50%; box-shadow: 0 0 0 2px rgba(11, 15, 23, 0.6); }
.legend .dot { background: var(--gold); } /* VIS-128: any unit type gets a dot (the accent); the four named types below keep theirs */
.dot.cabin { background: var(--c-cabin); } .dot.suite { background: var(--c-suite); } .dot.tower { background: var(--c-tower); } .dot.towerSuite { background: var(--c-towerSuite); }

/* ------------------------------------------------ 3D labels */
#labels { position: fixed; inset: 0; z-index: 5; pointer-events: none; overflow: hidden; --pin-scale: 1; } /* --pin-scale: the size of every label and client pin on this screen, in every map style (js/chrome/labels.js, lazy/overlay.js); smaller on a phone (below) */
@media (max-width: 760px), (pointer: coarse) { :where(body:not(.kiosk, .lobby)) #labels { --pin-scale: 0.85; } } /* owner's pick 2026-10-26 (B): 85 % on a phone, still easy to tap; 72 % made Lantern's lamps ~7 px */
.label { position: absolute; left: 0; top: 0; pointer-events: auto; white-space: nowrap; will-change: transform; transition: background 0.35s var(--ease), color 0.35s var(--ease), box-shadow 0.35s var(--ease); }
.label.place { display: inline-flex; align-items: center; gap: 7px; height: 30px; padding: 0 13px 0 9px; margin-top: -8px; border-radius: 999px; background: rgba(12, 16, 24, 0.78); color: var(--text); font-size: 11.5px; letter-spacing: 0.04em;
  border: 1px solid var(--hair); box-shadow: 0 10px 24px -10px rgba(3, 6, 14, 0.6); } /* no backdrop blur: under a 78 % fill it did not show, and a computer redid it behind every pin on every frame the map moved (15 at Aurora's home view) */
.label.place .ic { width: 14px; height: 14px; color: var(--gold); }
.label.place::after { content: ''; position: absolute; left: 50%; bottom: -9px; width: 1px; height: 8px; background: linear-gradient(rgba(255, 255, 255, 0.7), transparent); }
.label.unit { min-width: var(--unit-badge); height: var(--unit-badge); padding: 0 calc(var(--unit-badge) * 0.25); margin-top: -4px; border-radius: calc(var(--unit-badge) / 2); color: var(--ink); font-size: calc(var(--unit-badge) * 0.44); font-weight: 600; line-height: var(--unit-badge); text-align: center; box-shadow: 0 0 0 2px rgba(11, 15, 23, 0.55), 0 6px 14px -6px rgba(0, 0, 0, 0.6); }
:where(.label).unit { background: var(--gold); } /* VIS-128: a readable badge for any unit type (the accent); one class of weight (beats the button reset, the u-<type> colours below win) */
.u-cabin { background: var(--c-cabin); } .u-suite { background: var(--c-suite); } .u-tower { background: var(--c-tower); } .u-towerSuite { background: var(--c-towerSuite); }
.label.active { background: #fff !important; color: var(--ink) !important; z-index: 2; box-shadow: 0 0 0 3px rgba(210, 180, 110, 0.6), 0 12px 30px -10px rgba(0, 0, 0, 0.6); }
.label.active .ic { color: var(--ink); }
#tooltip { position: fixed; left: 0; top: 0; z-index: 20; pointer-events: none; padding: 10px 14px; border-radius: 14px; background: var(--glass-strong); border: 1px solid var(--hair); display: grid; gap: 2px; backdrop-filter: blur(14px); box-shadow: 0 16px 30px -12px rgba(0, 0, 0, 0.5); }
#tooltip b { font: 500 17px/1.1 var(--font-display); }
#tooltip small { color: var(--muted); font-size: 11.5px; }

/* ------------------------------------------------ WS-4: label motion, toast, quality, entrance */
:root { --spring: cubic-bezier(0.34, 1.56, 0.64, 1); }
.label { transition: background 0.35s var(--ease), color 0.35s var(--ease), box-shadow 0.35s var(--ease), opacity 0.45s var(--ease), translate 0.5s var(--spring), scale 0.5s var(--spring); }
.label.culled { pointer-events: none; }
.label.place:hover, .label.place.hover, .label.active { translate: 0 -3px; }
/* WS-15 (round 4c): never use the CSS `scale` property on a label. It is applied before the inline
   translate3d() that positions the label, so it scaled the screen position too (a badge at x = 600 jumped to
   x = 708). Emphasis is a scale appended *after* the positioning (--ls in the inline transform, ui.js), so it
   grows in place. Unit badges keep their category colour when hovered or selected (white swap removed). */
@property --ls { syntax: '<number>'; inherits: false; initial-value: 1; }
.label { transition: background 0.35s var(--ease), color 0.35s var(--ease), box-shadow 0.35s var(--ease), opacity 0.45s var(--ease), translate 0.5s var(--spring), --ls 0.4s var(--spring); }
.label.unit:hover, .label.unit.hover, .label.unit.active { --ls: 1.08; }
.label.unit.active { color: var(--ink) !important; box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.95), 0 0 0 4px rgba(11, 15, 23, 0.45), 0 8px 18px -8px rgba(0, 0, 0, 0.6); }
.label.unit.active.u-cabin { background: var(--c-cabin) !important; } .label.unit.active.u-suite { background: var(--c-suite) !important; }
.label.unit.active.u-tower { background: var(--c-tower) !important; } .label.unit.active.u-towerSuite { background: var(--c-towerSuite) !important; }
.label.unit.active { translate: none; animation: none; }
.label.active { animation: label-focus 0.9s var(--ease-out); }
@keyframes label-focus { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--gold) 70%, transparent), 0 12px 30px -10px rgba(0, 0, 0, 0.6); } 100% { box-shadow: 0 0 0 14px color-mix(in srgb, var(--gold) 0%, transparent), 0 12px 30px -10px rgba(0, 0, 0, 0.6); } }
#tooltip { transition: opacity 0.25s var(--ease); }
#tooltip[hidden] { display: grid; opacity: 0; }

#toast { position: fixed; left: 50%; top: 26px; z-index: 21; display: flex; align-items: baseline; gap: 10px; padding: 11px 18px; border-radius: 999px; background: var(--glass-strong); border: 1px solid var(--hair);
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); box-shadow: 0 20px 40px -20px rgba(3, 6, 14, 0.7); pointer-events: none;
  opacity: 0; transform: translate(-50%, -14px) scale(0.97); filter: blur(4px); transition: opacity 0.5s var(--ease), transform 0.7s var(--ease), filter 0.5s var(--ease); }
#toast.show { opacity: 1; transform: translate(-50%, 0); filter: none; }
#toast b { font: 400 20px/1 var(--font-display); }
#toast small { color: var(--muted); font-size: 11px; }
/* ride view (VIS-181, js/lazy/rideview.js): riding along on a sled; the way out sits where the sky view's does, the panels and labels step aside (as for the room dive) */
.ride-bar { position: fixed; left: 50%; top: 24px; z-index: 20; transform: translateX(-50%); display: flex; align-items: center; gap: 12px; padding: 6px 6px 6px 16px; border-radius: 999px; background: var(--glass-strong); border: 1px solid var(--hair);
  backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px); color: var(--muted); font: 500 12px/1 var(--font-ui); white-space: nowrap; animation: chrome-in 0.6s var(--ease-out) both; }
.ride-bar[hidden] { display: none; }
.ride-bar button { height: 30px; padding: 0 14px; border-radius: 999px; background: var(--gold); color: var(--ink); font: 600 11.5px/1 var(--font-ui); letter-spacing: 0.03em; }
.ride-bar button:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
body.ride-view #chrome, body.ride-view #labels { opacity: 0; pointer-events: none; }
@media (max-width: 460px) { .ride-bar { padding: 4px; } .ride-bar > span { display: none; } }
.controls .round-btn:hover .ic { transform: scale(1.08); }
.controls .round-btn .ic { transition: transform 0.5s var(--spring); }

/* Interface arrives after the scene: shells slide and un-blur in, staggered. */
body:not(.ready) .top-left, body:not(.ready) #explore, body:not(.ready) #dock, body:not(.ready) .controls, body:not(.ready) .top-actions { opacity: 0; }
body.ready .top-left, body.ready #explore, body.ready #dock, body.ready .controls, body.ready .top-actions { animation: chrome-in 1.1s var(--ease-out) both; }
body.ready .top-left { animation-delay: 0.9s; }
body.ready #explore { animation-delay: 1.15s; }
body.ready .top-actions { animation-delay: 1.3s; }
body.ready #dock { animation-delay: 1.45s; }
body.ready .controls { animation-delay: 1.6s; }
@keyframes chrome-in { from { opacity: 0; translate: 0 16px; filter: blur(8px); } to { opacity: 1; translate: 0 0; filter: none; } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-delay: 0ms !important; transition-duration: 0.01ms !important; }
}

/* ------------------------------------------------ kiosk attract mode */
.attract-cta { position: fixed; left: 50%; top: 50%; z-index: 12; transform: translate(-50%, -50%); padding: 16px 28px; border-radius: 999px; background: var(--glass-strong); border: 1px solid var(--hair); font: 400 22px/1 var(--font-display); letter-spacing: 0.02em;
  opacity: 0; pointer-events: none; transition: opacity 1s var(--ease); }
/* the owner 2026-10-31: over a playing tour the prompt only says it once, briefly, then leaves the map to the tour */
body.attract .attract-cta { animation: attract-once 3.2s var(--ease) both; }
@keyframes attract-once { 15%, 70% { opacity: 1; } 42% { transform: translate(-50%, -50%) scale(1.03); } }

/* ------------------------------------------------ embed */
/* WS-49: a control the preset hides is not on the page at all (ui.js), so nothing is hidden here any more. Without
   the header row the explore panel moves up (WS-45: desktop only; on phones it pulled the sheet up over the dock). */
@media (min-width: 761px) { body.embed #explore, body.no-top-left #explore { top: 20px; } }
.mobile-explore { display: none; }

/* ------------------------------------------------ responsive */
/* VIS-128: the open card stops above the time bar wherever the two meet: the centred bar reaches the card's column up
   to about 1600 px (its right end, the clock, was under the card at 1401-1600 px) */
@media (max-width: 1640px) { #card { bottom: 200px; } }
@media (max-width: 1400px) {
  #dock { left: 370px; right: 20px; transform: none; width: auto; min-width: 0; bottom: 78px; }
  body.explore-collapsed #dock { left: 20px; } /* round 6 */
  #card { bottom: 214px; } /* VIS-142: the time bar stands 78 px up here, 124 px tall: the card stops above it */
}
@media (max-width: 1100px) {
  .season:not(.on) span, .season .soon { display: none; } /* round 6: icons only, so the open card's shifted top buttons clear it */
  #explore { bottom: 214px; } /* VIS-142: clear of the time bar's top (78 + its 124 px) */
  #dock { left: 20px; }
}
@media (max-width: 760px) {
  .top-left { top: 12px; left: 12px; gap: 6px; }
  .brand.mark-only > .core { padding: 6px 11px; }
  .brand.mark-only img { height: 32px; }
  .seasons { padding: 3px; }
  .season { height: 34px; padding: 0 10px; }
  .season:not(.on) span, .season .soon { display: none; }
  #explore-fold { display: none; }
  .brand h1 { font-size: 19px; }
  .brand p { display: none; }
  .top-actions { top: 14px; right: 12px; }
  .top-actions #tour-btn span { display: none; }
  .top-actions #tour-btn { padding: 0 13px; }
  #explore { top: auto; left: 8px; right: 8px; bottom: 8px; width: auto; height: 72dvh; z-index: 15; transform: translateY(110%); transition: transform 0.7s var(--ease); }
  body.menu-open #explore { transform: none; }
  .mobile-explore { display: inline-flex; position: fixed; left: 12px; bottom: 196px; z-index: 10; }
  #card { top: auto; left: 8px; right: 8px; bottom: 8px; width: auto; max-height: 70dvh; z-index: 16; transform: translateY(40px); }
  #card > .core { max-height: calc(70dvh - 12px); } /* VIS-128: the card's own 70dvh less its padding and rim: a long card scrolls inside the screen (height: 100% of a max-height alone never resolved, the booking button ran off the bottom) */
  #card .hero { height: 170px; }
  body.card-open .top-actions, body.card-open .controls { transform: none; }
  #dock { left: 8px; right: 8px; bottom: 8px; transform: none; width: auto; }
  #dock > .core { grid-template-columns: 1fr; grid-template-areas: "readout" "dates" "line"; gap: 6px; padding: 8px 12px 4px; } /* round 6: full-width slider on phones too */
  #dock .timeline { margin: 0 4px; }
  #dock .readout { justify-content: flex-start; }
  .readout > div { display: flex; align-items: baseline; gap: 10px; }
  .dates { grid-column: 1 / -1; overflow-x: auto; scrollbar-width: none; }
  .date { flex: none; }
  .readout { min-width: 0; }
  .readout strong { font-size: 24px; }
  .controls { right: 12px; bottom: 196px; flex-direction: column; border-radius: 26px; }
}
/* ---- mobile gestures / small screens (begin, 2026-10-19: "intuitive on any phone, no matter how small the screen").
   The default look only (a look kit, body.mms-style, has its own phone layout).
   A very narrow phone (under 360 px): the open season shows its icon only, so the top row clears the buttons on the
   right (at 320 px the tour button sat on the season switch; the row needs ~355 px with the season's name). */
@media (max-width: 359px) {
  body:not(.mms-style) .season.on span { display: none; }
  body:not(.mms-style) .season { padding: 0 9px; }
}
/* A phone held sideways (short and wide, up to ~930 x 500): the upright phone's layout, laid out across. Explore is the
   sheet behind its button (the desktop panel was cut off and lay over the dock), the time dock is two low rows beside
   the map buttons (it covered the middle of the map, and the buttons' column ran off the top of the screen). */
@media (orientation: landscape) and (max-height: 500px) {
  body:not(.mms-style) .top-left { top: 10px; left: 10px; gap: 6px; }
  body:not(.mms-style) .brand.mark-only > .core { padding: 6px 11px; }
  body:not(.mms-style) .brand.mark-only img { height: 32px; }
  body:not(.mms-style) .brand p { display: none; }
  body:not(.mms-style) .seasons { padding: 3px; }
  body:not(.mms-style) .season { height: 34px; padding: 0 10px; }
  body:not(.mms-style) .season:not(.on) span, body:not(.mms-style) .season .soon { display: none; }
  body:not(.mms-style) .top-actions { top: 12px; right: 10px; }
  body:not(.mms-style) .top-actions #tour-btn span { display: none; }
  body:not(.mms-style) .top-actions #tour-btn { padding: 0 13px; }
  body:not(.mms-style) #explore { top: 8px; left: 8px; right: auto; bottom: 8px; width: min(360px, 62vw); height: auto; z-index: 15; transform: translateX(-110%); transition: transform 0.7s var(--ease); }
  body.menu-open:not(.mms-style) #explore { transform: none; }
  body:not(.mms-style) #explore-fold { display: none; }
  body:not(.mms-style) .mobile-explore { display: inline-flex; position: fixed; left: 10px; top: 62px; bottom: auto; z-index: 10; }
  body:not(.mms-style) #dock { left: 8px; right: 62px; bottom: 8px; transform: none; width: auto; min-width: 0; }
  body:not(.mms-style) #dock > .core { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "dates readout" "line line"; gap: 0 10px; padding: 4px 12px 2px 6px; }
  body:not(.mms-style) .dates { overflow-x: auto; scrollbar-width: none; }
  body:not(.mms-style) .date { flex: none; padding: 4px 9px; }
  body:not(.mms-style) .readout { min-width: 0; gap: 8px; }
  body:not(.mms-style) .readout strong { font-size: 22px; }
  body:not(.mms-style) .timeline { height: 44px; }
  body:not(.mms-style) .controls { right: 8px; bottom: 8px; flex-direction: column; border-radius: 26px; gap: 4px; }
  body:not(.mms-style) .controls .sep { width: 18px; height: 1px; margin: 2px 0; }
  body:not(.mms-style) #card, body.cards-compact:not(.mms-style) #card { top: 8px; right: 8px; bottom: 8px; left: auto; width: min(360px, 56vw); max-height: none; z-index: 16; } /* (compact cards too: they stopped above the dock's top) */
  body:not(.mms-style) #card > .core, body.cards-compact:not(.mms-style) #card > .core { max-height: calc(100dvh - 28px); }
  body:not(.mms-style) #card .hero, body.cards-compact:not(.mms-style) #card .hero { height: 110px; }
  body.card-open:not(.mms-style) .top-actions, body.card-open:not(.mms-style) .controls { transform: none; }
}
@media (orientation: landscape) and (max-height: 500px) and (max-width: 700px) { body:not(.mms-style) .readout small { display: none; } } /* room for the dates */
/* ---- mobile gestures / small screens (end) */

/* ------------------------------------------------ calibration editor (?edit) */
body.editing #explore, body.editing .mobile-explore, body.editing #card, body.editing #tour-btn { display: none !important; }
#editor { position: fixed; top: 92px; left: 20px; bottom: 20px; width: 340px; z-index: 12; }
#editor > .core { display: flex; flex-direction: column; overflow-y: auto; padding: 20px; gap: 14px; }
#editor .status { margin: 6px 0 0; font-size: 12px; color: var(--muted); }
#editor .ed-hint { color: var(--muted); font-size: 13px; line-height: 1.7; margin: 0; }
#editor kbd { font: 500 11px var(--font-ui); padding: 1px 6px; border-radius: 6px; border: 1px solid var(--hair-strong); }
#editor .ed-sel { display: grid; gap: 10px; }
#editor .ed-sel small { color: var(--faint); font-size: 11px; letter-spacing: 0.06em; }
#editor h3 { margin: 0; font: 400 26px/1.1 var(--font-display); }
#editor label { display: grid; gap: 6px; font-size: 12px; color: var(--muted); }
#editor input, #editor textarea { width: 100%; padding: 9px 12px; border-radius: 12px; border: 1px solid var(--hair); background: rgba(255,255,255,0.05); color: var(--text); font: 12.5px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace; outline: none; user-select: text; }
#editor input:focus, #editor textarea:focus { border-color: var(--gold); }
#editor .ed-row { display: flex; gap: 6px; flex-wrap: wrap; }
#editor .ed-btn { display: inline-flex; align-items: center; height: 34px; padding: 0 14px; border-radius: 999px; background: var(--gold); color: var(--ink); font-size: 12px; font-weight: 600; text-decoration: none; transition: transform .4s var(--ease); }
#editor .ed-btn:active { transform: scale(.97); }
#editor .ed-btn.ghost { background: transparent; color: var(--text); border: 1px solid var(--hair-strong); font-weight: 500; }
#editor .ed-note { margin: 0; font-size: 11.5px; color: var(--faint); line-height: 1.5; }
#editor .ed-foot { margin-top: auto; display: flex; flex-wrap: wrap; gap: 6px; padding-top: 14px; border-top: 1px solid var(--hair); }

/* ------------------------------------------------ interior (WS-3: 360° walk-in tour, js/interior.js) */
#card .step-inside { position: absolute; right: 14px; bottom: 14px; z-index: 2; display: inline-flex; align-items: center; gap: 9px; height: 42px; padding: 0 16px 0 5px; border-radius: 999px;
  background: rgba(8, 11, 18, 0.55); border: 1px solid var(--hair-strong); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); font-size: 13px; font-weight: 500; letter-spacing: 0.02em;
  transition: transform 0.5s var(--ease), background 0.4s var(--ease); }
#card .step-inside i { width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center; background: var(--gold); color: var(--ink); transition: transform 0.7s var(--ease); }
#card .step-inside i .ic { width: 17px; height: 17px; stroke-width: 1.4; }
#card .step-inside small { font-size: 10px; letter-spacing: 0.16em; color: var(--gold); }
#card .step-inside:hover { background: rgba(14, 18, 27, 0.82); }
#card .step-inside:hover i { transform: rotate(-30deg) scale(1.05); }
#card .step-inside:active { transform: scale(0.97); }
#card .step-inside:focus-visible, #interior button:focus-visible, #interior .int-canvas:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

.int-veil { position: fixed; inset: 0; z-index: 38; pointer-events: none; opacity: 0; background: radial-gradient(90% 90% at 50% 45%, #121a2b 0%, #06080d 75%); transition: opacity 0.45s var(--ease); }
.int-veil.on { opacity: 1; pointer-events: auto; }
#interior { position: fixed; inset: 0; z-index: 36; background: #06080d; opacity: 0; transition: opacity 0.6s var(--ease); }
#interior.on { opacity: 1; }
#interior .int-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; cursor: grab; outline: none; }
#interior .int-canvas:active { cursor: grabbing; }
#interior::after { content: ''; position: absolute; inset: 0; pointer-events: none; background: radial-gradient(120% 90% at 50% 50%, transparent 55%, rgba(4, 6, 10, 0.45)), linear-gradient(180deg, rgba(4, 6, 10, 0.5), transparent 22%, transparent 70%, rgba(4, 6, 10, 0.55)); }
#interior > :not(canvas):not(.int-hots) { z-index: 2; }

.int-top { position: absolute; top: 0; left: 0; right: 0; display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; padding: 26px 28px; pointer-events: none; }
.int-top > * { pointer-events: auto; }
.int-title { max-width: min(520px, 60vw); }
.int-title h2 { margin: 8px 0 0; font: 400 46px/1 var(--font-display); letter-spacing: 0.005em; text-shadow: 0 2px 30px rgba(0, 0, 0, 0.45); }
.int-title .int-blurb { margin: 8px 0 0; color: var(--muted); font-size: 13.5px; text-shadow: 0 1px 12px rgba(0, 0, 0, 0.6); }
.int-title.swap h2, .int-title.swap .int-blurb { animation: int-rise 0.9s var(--ease-out) both; }
.int-title.swap .int-blurb { animation-delay: 0.08s; }
@keyframes int-rise { from { opacity: 0; transform: translateY(10px); filter: blur(4px); } to { opacity: 1; transform: none; filter: none; } }
.int-actions { display: flex; gap: 8px; align-items: center; }
.int-back .ic { width: 17px; height: 17px; }
.int-gyro.on { background: var(--gold); color: var(--ink); border-color: transparent; }

.int-hots { position: absolute; inset: 0; pointer-events: none; overflow: hidden; z-index: 1; }
.int-hot { position: absolute; left: 0; top: 0; padding-top: 30px; pointer-events: auto; transition: opacity 0.35s var(--ease); will-change: transform; }
.int-hot span { display: inline-block; padding: 6px 12px; border-radius: 999px; font-size: 11px; font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase; white-space: nowrap;
  background: rgba(8, 11, 18, 0.5); border: 1px solid var(--hair); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); color: rgba(244, 239, 230, 0.86); transition: background 0.3s var(--ease), color 0.3s var(--ease), transform 0.4s var(--ease); }
.int-hot:hover span, .int-hot.hover span, .int-hot:focus-visible span { background: var(--gold); color: var(--ink); transform: translateY(-2px); }

.int-bar { position: absolute; left: 50%; bottom: 22px; transform: translateX(-50%); border-radius: 26px; max-width: calc(100% - 32px); }
.int-bar > .core { display: flex; align-items: center; gap: 10px; padding: 8px; border-radius: 21px; }
.int-map { width: 128px; height: 74px; flex: none; padding: 4px; border-radius: 16px; background: rgba(255, 255, 255, 0.035); border: 1px solid var(--hair); }
.int-map-room { fill: rgba(255, 255, 255, 0.04); stroke: rgba(244, 239, 230, 0.4); stroke-width: 0.09; stroke-linejoin: round; }
.int-map-wall { stroke: rgba(244, 239, 230, 0.4); stroke-width: 0.12; stroke-linecap: round; }
.int-map-cone { fill: rgba(210, 180, 110, 0.28); }
.int-map-node { fill: rgba(244, 239, 230, 0.55); cursor: pointer; transition: fill 0.3s; }
.int-map-node.on { fill: var(--gold); }
/* WS-6: CAD plan fills, stairs, floor tabs (multi-floor tours), up/down marker on links to another floor */
.int-map-walls { fill: rgba(244, 239, 230, 0.55); }
.int-map-stairs { fill: none; stroke: rgba(210, 180, 110, 0.55); stroke-width: 0.06; stroke-dasharray: 0.12 0.08; }
.int-floors { display: flex; flex-direction: column; gap: 4px; flex: none; }
.int-floor { min-width: 44px; height: 32px; padding: 0 10px; border-radius: 12px; border: 1px solid var(--hair); font-size: 10px; font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted);
  transition: background 0.3s var(--ease), color 0.3s var(--ease), border-color 0.3s var(--ease); }
.int-floor:hover { background: rgba(255, 255, 255, 0.06); color: var(--text, #f4efe6); }
.int-floor.on { background: rgba(210, 180, 110, 0.14); border-color: rgba(210, 180, 110, 0.4); color: var(--gold); }
.int-hot[data-dir="up"] span::before { content: '↑'; margin-right: 6px; color: var(--gold); }
.int-hot[data-dir="down"] span::before { content: '↓'; margin-right: 6px; color: var(--gold); }
.int-hot[data-dir="up"]:hover span::before, .int-hot[data-dir="down"]:hover span::before, .int-hot.hover[data-dir] span::before { color: inherit; }
.int-rooms { position: relative; display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none; }
.int-rooms::-webkit-scrollbar { display: none; }
.int-room { display: flex; align-items: center; gap: 10px; padding: 5px 14px 5px 5px; border-radius: 16px; border: 1px solid transparent; text-align: left; flex: none; transition: background 0.35s var(--ease), border-color 0.35s var(--ease);
  animation: int-rise 0.8s var(--ease-out) both; animation-delay: calc(var(--d) + 0.3s); }
.int-room:hover { background: rgba(255, 255, 255, 0.05); }
.int-room.on { background: rgba(210, 180, 110, 0.12); border-color: rgba(210, 180, 110, 0.35); }
.int-thumb { width: 64px; height: 64px; border-radius: 12px; overflow: hidden; background: #141a26; flex: none; }
.int-thumb img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.8s var(--ease); }
.int-room:hover .int-thumb img { transform: scale(1.08); }
.int-room-txt { display: grid; gap: 2px; }
.int-room-txt small { font-size: 10px; letter-spacing: 0.18em; color: var(--gold); }
.int-room-txt b { font-weight: 500; font-size: 13px; white-space: nowrap; }

.int-hint { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); display: flex; align-items: center; gap: 10px; padding: 12px 20px; border-radius: 999px; pointer-events: none;
  background: rgba(8, 11, 18, 0.5); border: 1px solid var(--hair); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); font-size: 13px; color: var(--muted); transition: opacity 0.8s var(--ease), transform 0.8s var(--ease);
  animation: int-rise 0.9s var(--ease-out) 0.9s both; }
.int-hint.gone { animation: int-out 0.7s var(--ease) both; }
@keyframes int-out { to { opacity: 0; transform: translate(-50%, -40%); visibility: hidden; } }
.int-note { position: absolute; right: 28px; bottom: 124px; /* WS-6: above the room bar (it spans the width with 8-9 rooms) */ margin: 0; max-width: 260px; text-align: right; font-size: 11px; line-height: 1.5; color: var(--faint); pointer-events: none; }
.int-loading { position: absolute; left: 0; right: 0; top: 0; height: 2px; overflow: hidden; opacity: 0; transition: opacity 0.4s; }
.int-loading.on { opacity: 1; }
.int-loading span { position: absolute; inset: 0; width: 30%; background: linear-gradient(90deg, transparent, var(--gold), transparent); animation: int-load 1.2s linear infinite; }
@keyframes int-load { from { transform: translateX(-100%); } to { transform: translateX(340%); } }
.int-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
.int-debug { position: absolute; left: 16px; bottom: 130px; margin: 0; padding: 10px 12px; border-radius: 12px; background: rgba(0, 0, 0, 0.6); font: 11px/1.5 ui-monospace, monospace; color: #cfe; pointer-events: none; }
body.interior-open .grain { z-index: 37; }
body.interior-diving #chrome, body.interior-diving #labels { opacity: 0; pointer-events: none; transition: opacity 0.6s var(--ease); }
#chrome, #labels { transition: opacity 0.6s var(--ease); }

@media (max-width: 1100px) { .int-note { display: none; } }
@media (max-width: 760px) {
  .int-top { padding: 16px 14px; }
  .int-title h2 { font-size: 32px; }
  .int-title .int-blurb { display: none; }
  .int-back span { display: none; }
  .int-back { width: 44px; padding: 0; justify-content: center; }
  .int-bar { left: 8px; right: 8px; bottom: 10px; transform: none; max-width: none; }
  .int-map { width: 92px; height: 58px; }
  .int-floor { min-width: 36px; height: 27px; padding: 0 6px; font-size: 9px; letter-spacing: 0.08em; } /* WS-6 */
  .int-thumb { width: 48px; height: 48px; }
  .int-room { padding-right: 10px; }
  .int-hint { white-space: nowrap; font-size: 12px; padding: 10px 16px; }
}
@media (prefers-reduced-motion: reduce) {
  .int-title.swap h2, .int-title.swap .int-blurb, .int-room, .int-hint { animation: none; }
}

/* ------------------------------------------------ WS-18: tree settings popover (amount, style, snow) */
.trees-pop { position: fixed; right: 20px; bottom: 82px; z-index: 13; width: 248px; padding: 14px 16px 12px; border-radius: 20px; background: var(--glass-strong); border: 1px solid var(--hair); color: var(--text);
  backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px); box-shadow: 0 18px 40px -16px rgba(0, 0, 0, 0.6); display: grid; gap: 12px; animation: tp-in 0.35s var(--ease-out) both; }
.trees-pop[hidden] { display: none; }
@keyframes tp-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.trees-pop .eyebrow { font: 500 10px/1 var(--font-ui); letter-spacing: 0.22em; text-transform: uppercase; color: var(--gold); }
.tp-row { display: grid; gap: 7px; font-size: 12px; color: var(--muted); }
.tp-row > span { display: flex; justify-content: space-between; }
.tp-row b { color: var(--text); font-weight: 500; font-variant-numeric: tabular-nums; }
.tp-inline { grid-template-columns: 1fr auto; align-items: center; }
.trees-pop input[type="range"] { width: 100%; accent-color: var(--gold); margin: 0; height: 22px; }
.tp-seg { display: grid; grid-template-columns: 1fr 1fr; gap: 3px; padding: 3px; border-radius: 999px; border: 1px solid var(--hair); background: rgba(255, 255, 255, 0.03); }
.tp-seg button { font: 500 12px/1 var(--font-ui); color: var(--muted); background: none; border: 0; border-radius: 999px; padding: 8px 0; cursor: pointer; transition: background 0.3s var(--ease), color 0.3s var(--ease); }
.tp-seg button:hover { color: var(--text); }
.tp-seg button.on { color: var(--ink); background: var(--gold); }
.tp-switch { width: 38px; height: 22px; border-radius: 999px; border: 1px solid var(--hair-strong); background: rgba(255, 255, 255, 0.06); position: relative; cursor: pointer; padding: 0; transition: background 0.3s var(--ease); }
.tp-switch i { position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%; background: var(--text); transition: transform 0.35s var(--spring), background 0.3s var(--ease); }
.tp-switch.on { background: var(--gold); border-color: transparent; }
.tp-switch.on i { transform: translateX(16px); background: var(--ink); }
.tp-switch:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.tp-note { color: var(--faint); font-size: 11px; }
.tp-note:empty { display: none; }
#trees-btn.on, #credit-btn.on { color: var(--ink); background: var(--gold); border-color: transparent; }
@media (max-width: 760px) {
  .trees-pop { right: 64px; bottom: 196px; width: min(248px, calc(100vw - 80px)); }
}
/* WS-45: the info box behind the (i) button of the map controls (chrome/column.js), one in every style (owner's pick
   I2 "Logo header with tabs", 2026-10-29): Map My Stay's wordmark and the arrow to its website in one row, who made
   the map, then the tabs Map data (the licence lines word for word), Privacy and Offline. It takes the tree popover's
   place and glass; the engine tokens follow a map style (brand-dark.css), so it reads right on every map. The tabs
   share one cell, so the box keeps its height when another tab is picked. */
.credit-pop { width: 320px; max-width: calc(100vw - 32px); padding: 0; gap: 0; overflow: hidden; }
body.ph #credit-pop.credit-pop { max-width: calc(100vw - 88px); } /* a phone: clear of the rail on the right */
.credit-pop:focus { outline: none; } /* opened, the focus is on the box itself: no ring (the keyboard's Tab walks on into it) */
.credit-pop .ib-top { display: grid; gap: 10px; padding: 18px 18px 14px; background: linear-gradient(160deg, color-mix(in srgb, var(--gold) 16%, transparent), transparent 70%); }
.credit-pop .ib-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-right: -6px; }
.credit-pop .ib-logo { width: 121px; height: 26px; margin-left: -3px; background: var(--text); -webkit-mask: url(mms-logo.h-11d3a3cec2.svg) left center / contain no-repeat; mask: url(mms-logo.h-11d3a3cec2.svg) left center / contain no-repeat; }
.credit-pop .ib-go { flex: none; display: grid; place-items: center; width: 32px; height: 32px; border-radius: 50%; color: var(--muted); text-decoration: none; transition: color 0.2s ease, background-color 0.2s ease; }
.credit-pop .ib-go:hover { color: var(--text); background: color-mix(in srgb, var(--text) 8%, transparent); }
.credit-pop .ib-go .ic { width: 18px; height: 18px; }
.credit-pop .ib-made { margin: 0; font: 400 12.5px/1.45 var(--font-ui); color: var(--muted); }
.credit-pop .ib-body { display: grid; gap: 10px; padding: 12px 18px 18px; border-top: 1px solid var(--hair); }
.credit-pop .ib-tabs { display: flex; gap: 18px; }
.credit-pop [role="tab"] { padding: 2px 0 5px; border: 0; border-bottom: 2px solid transparent; border-radius: 0; background: none; color: var(--faint); font: 500 12.5px/1.2 var(--font-ui); cursor: pointer; transition: color 0.2s ease; }
.credit-pop [role="tab"]:hover { color: var(--text); }
.credit-pop [role="tab"][aria-selected="true"] { color: var(--text); border-bottom-color: var(--text); }
.credit-pop :is([role="tab"], .ib-go, a):focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.credit-pop .ib-pane { grid-area: 2 / 1; min-width: 0; }
.credit-pop .ib-pane[hidden] { display: block; visibility: hidden; }
.credit-pop .ib-pane p { margin: 0; font: 400 12px/1.45 var(--font-ui); color: var(--muted); }
.credit-pop ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; font: 400 11.5px/1.45 var(--font-ui); color: var(--muted); user-select: text; -webkit-user-select: text; }
.credit-pop a { color: inherit; text-decoration: underline; text-decoration-color: var(--hair-strong); text-underline-offset: 2px; transition: color 0.2s ease; }
.credit-pop a:hover, .credit-pop a:focus-visible { color: var(--text); }
/* VIS-231: "Save for offline", the Offline tab of the info box (lazy/save.js). */
.credit-pop .save { display: grid; gap: 7px; font: 400 12px/1.4 var(--font-ui); color: var(--muted); }
.credit-pop .save:empty { display: none; }
.credit-pop .save-go { justify-self: start; padding: 8px 14px; border-radius: 999px; border: 1px solid var(--hair-strong); background: rgba(255, 255, 255, 0.06); color: var(--text); font: 500 12px/1 var(--font-ui); cursor: pointer; transition: background 0.3s var(--ease), color 0.3s var(--ease); }
.credit-pop .save-go:hover { color: var(--ink); background: var(--gold); border-color: transparent; }
.credit-pop .save-go:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.credit-pop .save-msg { color: var(--text); }
.credit-pop .save-ok { color: var(--gold); font-weight: 500; }
.credit-pop .save progress { width: 100%; height: 4px; border: 0; border-radius: 999px; overflow: hidden; background: var(--hair); accent-color: var(--gold); appearance: none; -webkit-appearance: none; }
.credit-pop .save progress::-webkit-progress-bar { background: var(--hair); }
.credit-pop .save progress::-webkit-progress-value { background: var(--gold); border-radius: 999px; transition: width 0.3s var(--ease); }
.credit-pop .save progress::-moz-progress-bar { background: var(--gold); border-radius: 999px; }
/* Save to this computer (owner's pick B, 2026-10-31): the desktop guide under the save, one step at a time. */
.credit-pop .save-guide { display: grid; gap: 8px; margin-top: 4px; padding: 12px; border-radius: 14px; border: 1px solid var(--hair); background: rgba(255, 255, 255, 0.04); }
.credit-pop .sg-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; color: var(--text); font-size: 12.5px; }
.credit-pop .sg-x { width: 28px; height: 28px; margin: -6px -6px -6px 0; border: 0; border-radius: 50%; background: none; color: var(--muted); font: 400 18px/1 var(--font-ui); cursor: pointer; }
.credit-pop .sg-x:hover { color: var(--text); background: var(--hair); }
.credit-pop .sg-which { display: flex; align-items: center; gap: 8px; }
.credit-pop .sg-which select { flex: 1; min-width: 0; padding: 5px 8px; border-radius: 8px; border: 1px solid var(--hair-strong); background: var(--ink); color: var(--text); font: 400 12px/1.2 var(--font-ui); }
.credit-pop .sg-n { color: var(--gold); font-weight: 500; font-size: 11.5px; }
.credit-pop .save-guide p { margin: 0; }
.credit-pop .sg-t { color: var(--text); font-size: 13px; line-height: 1.45; }
.credit-pop .sg-app { display: flex; align-items: center; gap: 10px; color: var(--text); }
.credit-pop .sg-app img { width: 28px; height: 28px; border-radius: 7px; flex: none; }
.credit-pop .sg-nav { display: flex; justify-content: flex-end; gap: 8px; }
.credit-pop .sg-nav .save-go { justify-self: auto; }
.credit-pop .sg-b { padding: 8px 10px; border: 0; background: none; color: var(--muted); font: 500 12px/1 var(--font-ui); cursor: pointer; }
.credit-pop .sg-b:hover { color: var(--text); }
.credit-pop .save-guide :is(select, .sg-x, .sg-b):focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
/* WS-45: the start credit, only the showAtStart credits (OpenStreetMap), one line beside the (i) button for 5 s.
   Plain white text, no pill (owner, 2026-10-13); a soft dark shadow keeps it readable on bright snow (the OSMF
   guideline asks for a readable credit). column.js sets right/bottom from the controls; these are the fallback corner. */
.credit-chip { position: fixed; right: 20px; bottom: 84px; z-index: 13; max-width: calc(100vw - 80px); padding: 3px 6px;
  font: 500 11.5px/1.3 var(--font-ui); color: #fff; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6), 0 0 10px rgba(0, 0, 0, 0.45);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  opacity: 0; translate: 0 6px; transition: opacity 0.35s var(--ease), translate 0.35s var(--ease); }
.credit-chip.on { opacity: 1; translate: 0 0; }
.credit-chip a { color: inherit; text-decoration: none; }
.credit-chip a:hover, .credit-chip a:focus-visible { text-decoration: underline; text-underline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .credit-chip { translate: none; transition-duration: 0.15s; } }
/* Clear display (Space, lazy/clear.js; owner 2026-10-29): everything over the map goes (panels, buttons, the logo, place
   names, icons and room numbers, tour captions: every child of the page but the map), for the time being. One small (i)
   stays in the bottom right corner (the map-data credit is a licence duty) and opens the info box above it; a note in
   the bottom middle says how to come back, then fades. The same in every style: nothing here names one. */
body.clear-display > :not(#scene, .grain, .season-cover, #credit-pop, .clear-i, .clear-note, script) { opacity: 0 !important; visibility: hidden !important; pointer-events: none !important; }
html body.clear-display #credit-pop.credit-pop.trees-pop { top: auto; left: auto; right: 16px; bottom: 62px; }
.clear-i { position: fixed; right: 16px; bottom: 16px; z-index: 14; display: grid; place-items: center; width: 34px; height: 34px; padding: 0; border: 1px solid var(--hair); border-radius: 50%;
  background: var(--glass); -webkit-backdrop-filter: blur(18px); backdrop-filter: blur(18px); color: var(--muted); cursor: pointer; transition: color 0.2s ease; }
.clear-i:hover, .clear-i[aria-expanded="true"] { color: var(--text); }
.clear-i:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.clear-i .ic { width: 18px; height: 18px; }
.clear-note { position: fixed; left: 50%; bottom: 24px; z-index: 14; translate: -50% 0; padding: 8px 16px; border-radius: 999px; background: var(--glass-strong); border: 1px solid var(--hair);
  -webkit-backdrop-filter: blur(18px); backdrop-filter: blur(18px); font: 400 13px/20px var(--font-ui); color: var(--text); white-space: nowrap; pointer-events: none; transition: opacity 0.6s ease; }
.clear-note.out { opacity: 0; }
.clear-note kbd { display: inline-block; min-width: 20px; margin: 0 3px; padding: 0 5px; border: 1px solid var(--hair-strong); border-radius: 5px; background: color-mix(in srgb, var(--text) 10%, transparent); font: 600 11px/18px var(--font-ui); text-align: center; }
.clear-i[hidden], .clear-note[hidden] { display: none; }
/* WS-18 r3 / WS-40: snow-on-trees levels (n buttons) + fine slider in the trees popover */
.tp-seg.tp-seg-n { grid-template-columns: repeat(var(--n, 4), 1fr); }
.tp-seg.tp-seg-n button { padding: 8px 0; font-size: 11.5px; }
.tp-seg button:focus-visible, .trees-pop input[type="range"]:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* WS-41 live season switch: the last frame as a still over the map, faded out over the new season (under the labels
   and the UI). It also covers the ground repaint, and soft-fades animals that are moved out of / into a paddock. */
.season-cover { position: fixed; inset: 0; width: 100%; height: 100%; display: block; pointer-events: none; opacity: 1; transition: opacity 0.9s ease; }
.season-cover.out { opacity: 0; }
/* owner, 2026-10-26: "no visual feedback that it needs to load". From 0.35 s on (a quick switch shows none of it) the
   still goes soft, the place icons fade out and the website demo's Ripple loader (index.html #season-wait, lit centre
   first like the demo's .vx-ripple) pulses over it; at the reveal the loader fades with the still and the icons come
   back over the new season. CSS alone, keyed on the cover being up (no engine code: main.js only puts up the cover),
   and only filter, transform and opacity move, so it runs on the compositor while the switch holds the main thread. */
.season-cover { will-change: opacity, filter, transform; animation: season-still-soft 0.6s ease 0.35s both; }
@keyframes season-still-soft { to { filter: blur(7px) brightness(0.78); transform: scale(1.03); } } /* (the scale keeps the blur's soft rim off screen) */
body:has(.season-cover:not(.out)) :is(#labels, #marks-keep) { opacity: 0; transition: opacity 0.4s ease 0.3s; }
body:has(.season-cover:not(.out)) :is(#labels, #marks-keep) * { pointer-events: none !important; }
#season-wait { position: fixed; inset: 0; z-index: 4; display: none; place-items: center; pointer-events: none; transition: opacity 0.6s ease; }
body:has(.season-cover) #season-wait { display: grid; }
body:has(.season-cover.out) #season-wait { opacity: 0; }
#season-wait::before { content: ''; position: absolute; inset: 0; background: radial-gradient(circle at 50% 50%, rgb(8 12 20 / .36), rgb(8 12 20 / 0) 55%); }
#season-wait::before, .season-ripple { opacity: 0; will-change: opacity; animation: season-wait-in 0.6s ease 0.35s both; }
@keyframes season-wait-in { to { opacity: 1; } }
.season-ripple { position: relative; display: block; width: 120px; aspect-ratio: 880 / 960; fill: #F8F6F0; fill-rule: evenodd; }
.season-ripple svg { position: absolute; inset: 0; width: 100%; height: 100%; opacity: .16; will-change: opacity;
  animation: season-ripple 1600ms cubic-bezier(.4, 0, .2, 1) infinite; }
.season-ripple svg:nth-child(2) { animation-delay: 160ms; }
.season-ripple svg:nth-child(3) { animation-delay: 320ms; }
.season-ripple svg:nth-child(4) { animation-delay: 480ms; }
.season-ripple svg:nth-child(5) { animation-delay: 640ms; }
@keyframes season-ripple { 0%, 62%, 100% { opacity: .16; } 22% { opacity: 1; } }
@media (max-width: 619px) { .season-ripple { width: 88px; } }
@media (prefers-reduced-motion: reduce) { .season-cover { transition-duration: 0.2s; } .season-ripple svg { animation: none; opacity: 1; } }

/* ------------------------------------------------ WS-49: controls as components, layouts, languages */
/* a control that arrives after the page is up (a preset or the editor shows it) skips the staggered entrance */
body.chrome-live .top-left, body.chrome-live #explore, body.chrome-live .top-actions, body.chrome-live #dock, body.chrome-live .controls { animation-delay: 0s; animation-duration: 0.45s; }
/* language switch (language.switch) */
.langs { display: flex; gap: 2px; height: 44px; padding: 4px; border-radius: 999px; background: var(--glass); border: 1px solid var(--hair); backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px); }
.lang { min-width: 36px; padding: 0 10px; border-radius: 999px; color: var(--muted); font-size: 11.5px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; transition: background 0.45s var(--ease), color 0.45s var(--ease); }
.lang:hover { color: var(--text); }
.lang.on { background: var(--gold); color: var(--ink); }
.lang:focus-visible, .pop-item:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
/* With the tour list or the language switch in the top row and a card open, a laptop-wide window has no room for the
   tour button's words beside the season switch (measured at 1200 px: 84 px of overlap, 110 px in Finnish): the button
   keeps its icon, as it does on phones. Only where one of the two new controls is shown: the default page has neither. */
@media (min-width: 761px) and (max-width: 1340px) {
  body.card-open .top-actions:has(#tours-btn, .langs) #tour-btn span { display: none; }
  body.card-open .top-actions:has(#tours-btn, .langs) #tour-btn { padding: 0 13px; }
}
/* WS-51: on a phone the top row cannot hold the season switch AND the two new controls (measured at 390 px on a preset
   that shows them all: the tour button, the tour list and the language switch lay over the season switch). Where one
   of the two is shown, the row of buttons moves under the brand's row. The default page has neither and is unchanged. */
@media (max-width: 560px) {
  .top-actions:has(#tours-btn, .langs) { top: 76px; } /* VIS-128: was 64px, 4 px over the brand's row */
  body:has(.top-actions #tours-btn, .top-actions .langs) .menu-pop { top: 128px; } /* VIS-128: the tour list under that row, not on it */
}
/* tour list (tour.picker): the tree popover's shell with rows to press */
#tours-pop { gap: 4px; }
.menu-pop { top: 78px; right: 24px; bottom: auto; }
.pop-item { display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px 10px; border-radius: 12px; text-align: left; font-size: 13px; color: var(--muted); transition: background 0.3s var(--ease), color 0.3s var(--ease); }
.pop-item:hover, .pop-item.on { color: var(--text); background: rgba(255, 255, 255, 0.06); }
.pop-item b { flex: 1; font-weight: 500; }
.pop-item small { color: var(--faint); font-size: 11px; white-space: nowrap; }
.pop-item .dot { flex: none; opacity: 0.35; }
.pop-item.on .dot { opacity: 1; }
@media (min-width: 761px) { body.card-open .menu-pop { right: 436px; } }
@media (max-width: 760px) { .menu-pop { top: 66px; right: 12px; } }
/* the dock without date chips: a short bar, slider and clock on one row */
#dock.slim { width: min(460px, calc(100% - 40px)); min-width: 0; }
#dock.slim > .core { grid-template-columns: 1fr auto; grid-template-areas: "line readout"; padding: 8px 18px 4px 14px; }
/* labels.<category>: icon only / name only; map.pick hidden: labels are drawn but cannot be pressed */
.label.place.icons { padding: 0 8px; }
.label.place.text { padding: 0 13px; }
#labels[inert] .label { pointer-events: none; }
/* cards.size compact: a teaser that leaves most of the map visible (photo, type, key facts, link) */
body.cards-compact:not(.mms-style) #card { width: 292px; top: 14px; right: 14px; bottom: auto; }
body.cards-compact:not(.mms-style) #card > .core { height: auto; max-height: calc(100dvh - 110px); }
body.cards-compact:not(.mms-style) #card .hero { height: 128px; }
body.cards-compact:not(.mms-style) #card .close { top: 10px; right: 10px; }
body.cards-compact:not(.mms-style) #card .body { padding: 12px 16px 16px; gap: 10px; }
body.cards-compact:not(.mms-style) #card h2 { font-size: 25px; }
body.cards-compact:not(.mms-style) #card .stats div { padding: 7px 9px; border-radius: 11px; }
body.cards-compact:not(.mms-style) #card .stats small { font-size: 9px; letter-spacing: 0.12em; }
body.cards-compact:not(.mms-style) #card .stats b { font-size: 12px; }
body.cards-compact:not(.mms-style) #card .blurb { font-size: 13px; line-height: 1.55; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
body.cards-compact:not(.mms-style) #card dl, body.cards-compact:not(.mms-style) #card ul, body.cards-compact:not(.mms-style) #card .eyebrow { display: none; }
body.cards-compact:not(.mms-style) #card .actions { margin-top: 0; }
body.cards-compact:not(.mms-style).card-open .top-actions { transform: translateX(-312px); }
@media (max-width: 760px) {
  body.cards-compact:not(.mms-style) #card { top: auto; left: 8px; right: 8px; bottom: 8px; width: auto; }
  body.cards-compact:not(.mms-style) #card > .core { max-height: 42dvh; }
  body.cards-compact:not(.mms-style) #card .hero { height: 96px; }
  body.cards-compact:not(.mms-style).card-open .top-actions { transform: none; }
}
/* lobby layouts (layout.id): `lobby-map` is the map alone, `lobby-panel` adds a side panel with the caption of the
   tour stop on screen and that stop's place card */
body.lobby-map #card, body.lobby-map #tooltip, body.lobby-map #toast, body.lobby-map .attract-cta { display: none; }
#lobby { position: fixed; top: 20px; right: 20px; bottom: 20px; width: 400px; z-index: 11; }
#lobby > .core { display: flex; flex-direction: column; overflow: hidden; }
.lobby-cap { padding: 28px 26px 20px; display: grid; gap: 12px; }
.lobby-cap h2 { margin: 0; font: 400 38px/1.05 var(--font-display); letter-spacing: 0.005em; }
.lobby-cap p { margin: 0; color: var(--muted); font-size: 15px; line-height: 1.6; }
.lobby-cap p:empty, .lobby-cap .eyebrow[hidden] { display: none; }
#lobby #card { position: static; flex: 1; min-height: 0; width: auto; padding: 0; transform: none; filter: none; border-top: 1px solid var(--hair); transition: opacity 0.6s var(--ease); }
#lobby #card > .core { height: 100%; }
#lobby #card .hero { border-radius: 0; }
body.lobby-panel .top-actions, body.lobby-panel .controls, body.lobby-panel .trees-pop { right: 440px; }
body.lobby-panel.card-open .top-actions, body.lobby-panel.card-open .controls { transform: none; }
@media (max-width: 760px) {
  #lobby { top: auto; left: 8px; right: 8px; bottom: 8px; width: auto; max-height: 46dvh; }
  body.lobby-panel .top-actions, body.lobby-panel .controls { right: 12px; }
  body.lobby-panel .trees-pop { right: 64px; }
}

/* ---- WS-51 editor mode (js/bridge.js): only on a page that the portal's editor frames. A visitor's page never
   carries these attributes or classes. A ghost is a control the preset hides, drawn in the place it would have so the
   editor can tag it Hidden: dimmed, and (VIS-73) still pressable, so the editor can use it as the shown one. The
   outline marks what is being edited. */
[data-ghost] { opacity: 0.34 !important; filter: grayscale(1); transition: opacity 0.15s; }
[data-ghost]:hover, [data-ghost]:focus-within { opacity: 0.62 !important; }
[data-ghost] [data-ghost] { opacity: 1 !important; filter: none; }
#mms-outline { position: fixed; z-index: 90; box-sizing: content-box; margin: -6px 0 0 -6px; padding: 4px; pointer-events: none; border: 2px solid var(--gold); border-radius: 16px; box-shadow: 0 0 0 4px rgba(210, 180, 110, 0.22); transition: left 0.2s var(--ease), top 0.2s var(--ease), width 0.2s var(--ease), height 0.2s var(--ease); }
body.mms-picking #scene, body.mms-picking #labels .label { cursor: crosshair !important; }

/* ---- WS-52: what the lazy engine modules put on the map (js/lazy/): the client's pins and their card, the handles
   of the draw tool, the pins of the notes to the studio and the "you are here" marker. A page that loads none of
   those modules has none of these elements. #marks is the one layer for them, inside #labels: it is hidden with the
   labels and a drag that starts on a mark moves the map. Each mark is placed with a transform on its map point. */
#marks { position: absolute; inset: 0; z-index: 3; pointer-events: none; } /* over the labels, a hovered or selected one (z-index 2) included: a pin on a place stays pressable */
#marks [hidden] { display: none !important; }
#marks button { position: absolute; left: 0; top: 0; pointer-events: auto; will-change: transform; }
/* WS-91: the wayfinding marks' own layer (lazy/overlay.js `keep`): beside #labels, so looking up at the sky does not hide
   them; hidden in a ride view and inside a building, as the labels are. Never pressed. */
#marks-keep { position: fixed; inset: 0; z-index: 5; pointer-events: none; overflow: hidden; transition: opacity 0.6s var(--ease); }
#marks-keep > * { position: absolute; left: 0; top: 0; pointer-events: none; will-change: transform; }
body.ride-view #marks-keep, body.interior-diving #marks-keep { opacity: 0; }
#labels[inert] #marks button { pointer-events: none; }

/* a pin of the client: a disc in the layer's colour (--c) with the layer's icon, a short stem to its place, and its
   title beside it from close by (.near), under the pointer and while it is selected */
.cf-pin { display: inline-flex; align-items: center; height: 28px; margin: -35px 0 0 -14px; border-radius: 999px; color: var(--text); font-size: 12px; line-height: 1; white-space: nowrap; }
.cf-pin i { width: 28px; height: 28px; flex: none; display: grid; place-items: center; border-radius: 50%; background: var(--c); color: #fff;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.94), 0 6px 14px -4px rgba(3, 6, 14, 0.6); transition: scale 0.45s var(--spring), box-shadow 0.35s var(--ease); }
.cf-pin { transform-origin: 14px 35px; animation: pin-in 0.35s var(--ease); } /* scaled about its point (the stem's tip); shown again = faded in (a pin coming into view no longer pops up) */
@keyframes pin-in { from { opacity: 0; } }
.cf-pin.light i { color: var(--ink); }
.cf-pin i .ic { width: 15px; height: 15px; stroke-width: 1.6; }
.cf-pin::after { content: ''; position: absolute; left: 13px; top: 29px; width: 2px; height: 6px; border-radius: 1px; background: rgba(255, 255, 255, 0.94); box-shadow: 0 1px 3px rgba(3, 6, 14, 0.5); }
.cf-pin span { display: none; margin-left: 7px; padding: 6px 11px; border-radius: 999px; max-width: 200px; overflow: hidden; text-overflow: ellipsis;
  background: rgba(12, 16, 24, 0.8); border: 1px solid var(--hair); } /* no backdrop blur, as .label.place */
.near .cf-pin span, .cf-pin:hover span, .cf-pin:focus-visible span, .cf-pin.active span { display: block; }
@media (max-width: 760px) { .near .cf-pin:not(.active) span { display: none; } } /* a phone has no room for every title: the selected pin's only */
.cf-pin:hover, .cf-pin.active { z-index: 1; }
.cf-pin:hover i, .cf-pin.active i { scale: 1.12; }
.cf-pin.active i { box-shadow: 0 0 0 2px #fff, 0 0 0 5px color-mix(in srgb, var(--gold) 70%, transparent), 0 8px 18px -6px rgba(3, 6, 14, 0.6); }
.cf-pin:focus-visible { outline: none; }
.cf-pin:focus-visible i { outline: 2px solid var(--gold); outline-offset: 3px; }
/* WS-53: a line's or an area's keyboard button (lazy/layers.js) shows only while the keyboard is on it: for a pointer the line itself is the mark */
.cf-pin.cf-key { pointer-events: none; opacity: 0; }
.cf-pin.cf-key:focus-visible { opacity: 1; }
#scene.cf-over { cursor: pointer; }

/* the visitor's card of a pin, a line or an area: where the place card is, smaller */
#feature-card { position: fixed; top: 20px; right: 20px; width: 340px; z-index: 11; padding: 5px; opacity: 0; pointer-events: none; visibility: hidden;
  transform: translateX(28px) scale(0.98); transition: opacity 0.5s var(--ease), transform 0.7s var(--ease), visibility 0.5s; }
#feature-card.open { opacity: 1; transform: none; pointer-events: auto; visibility: visible; }
#feature-card > .core { position: relative; max-height: calc(100dvh - 134px); overflow-y: auto; scrollbar-width: none; }
#feature-card > .core::-webkit-scrollbar { display: none; }
#feature-card .close { position: absolute; top: 12px; right: 12px; z-index: 2; background: rgba(8, 11, 18, 0.5); }
#feature-card .fc-photo { position: relative; height: 176px; overflow: hidden; border-radius: calc(var(--r-xl) - 5px) calc(var(--r-xl) - 5px) 0 0; }
#feature-card .fc-photo > img { display: block; width: 100%; height: 100%; object-fit: cover; }
#feature-card .body { display: grid; gap: 12px; justify-items: start; padding: 18px 22px 22px; }
#feature-card .body > .eyebrow { max-width: calc(100% - 44px); }
#feature-card h2 { margin: 0; font: 400 28px/1.08 var(--font-display); letter-spacing: 0.005em; }
#feature-card h2:empty { display: none; }
#feature-card .blurb { margin: 0; color: var(--muted); font-size: 13.5px; line-height: 1.62; white-space: pre-line; overflow-wrap: anywhere; }
.fc-docs { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; width: 100%; }
.fc-docs a, .fc-link { display: flex; align-items: center; gap: 10px; width: 100%; min-height: 44px; padding: 8px 14px; border-radius: 14px; background: rgba(255, 255, 255, 0.04); border: 1px solid var(--hair);
  color: var(--text); text-decoration: none; font-size: 13px; transition: background 0.4s var(--ease), border-color 0.4s var(--ease); }
.fc-docs a:hover, .fc-link:hover { background: rgba(255, 255, 255, 0.08); border-color: var(--hair-strong); }
.fc-docs a:focus-visible, .fc-link:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.fc-docs .ic, .fc-link .ic { width: 16px; height: 16px; color: var(--gold); }
.fc-docs span { overflow: hidden; text-overflow: ellipsis; }
.fc-link span { font-weight: 500; flex: none; }
.fc-link small { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--faint); font-size: 11.5px; }
@media (max-width: 760px) {
  #feature-card { top: auto; left: 8px; right: 8px; bottom: 8px; width: auto; z-index: 16; transform: translateY(40px); }
  #feature-card > .core { max-height: 56dvh; }
  #feature-card .fc-photo { height: 140px; }
}
body.lobby-map #feature-card { display: none; }

/* the draw tool (editor only): a handle on every vertex, wide enough for a finger; a smaller one between two */
.dr-h, .dr-m { width: 44px; height: 44px; margin: -22px 0 0 -22px; display: grid; place-items: center; border-radius: 50%; cursor: grab; touch-action: none; }
.dr-h::before { content: ''; width: 16px; height: 16px; border-radius: 50%; background: #fff; border: 3px solid var(--c, var(--gold)); box-shadow: 0 2px 8px rgba(3, 6, 14, 0.6); transition: scale 0.3s var(--spring); }
.dr-m::before { content: ''; width: 10px; height: 10px; border-radius: 50%; background: var(--c, var(--gold)); border: 2px solid #fff; opacity: 0.9; box-shadow: 0 2px 6px rgba(3, 6, 14, 0.5); transition: scale 0.3s var(--spring); }
.dr-h:hover::before, .dr-h:focus-visible::before, .dr-m:hover::before, .dr-m:focus-visible::before { scale: 1.25; }
.dr-h:focus-visible, .dr-m:focus-visible { outline: none; }
.dr-h:focus-visible::before, .dr-m:focus-visible::before { box-shadow: 0 0 0 2px rgba(11, 15, 23, 0.7), 0 0 0 4px #fff; }
.dr-h:active, .dr-m:active { cursor: grabbing; }
.dr.one .dr-h::before { width: 22px; height: 22px; border-width: 4px; }
/* (WS-56) the first handle of a new line or area of 3 corners or more: pressed, it closes the loop or the area */
.dr-h.dr-close { cursor: pointer; }
.dr-h.dr-close::before { width: 22px; height: 22px; background: #dcebe2; border: 3px solid #2c6a52; box-shadow: 0 0 0 3px rgba(220, 235, 226, 0.55), 0 2px 8px rgba(3, 6, 14, 0.6); }
@media (pointer: coarse) { .dr-h::before { width: 22px; height: 22px; } .dr-m::before { width: 14px; height: 14px; } }
body.mms-drawing #scene, body.mms-drawing #labels .label, body.mms-drawing #labels .cf-pin, body.mms-placing #scene, body.mms-placing #labels .label { cursor: crosshair !important; }

/* the notes to the studio (editor only). A pin says its status with a mark as well as a colour (--s). */
.mk-note { display: inline-flex; align-items: center; gap: 3px; height: 26px; margin: -33px 0 0 -6px; padding: 0 9px 0 4px; border-radius: 13px 13px 13px 3px; background: var(--s); color: #fff;
  font: 600 12px/1 var(--font-ui); font-variant-numeric: tabular-nums; box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.94), 0 6px 14px -4px rgba(3, 6, 14, 0.6); }
.mk-note i { display: grid; place-items: center; width: 18px; height: 18px; }
.mk-note .ic { width: 16px; height: 16px; stroke-width: 2; }
.mk-note.s-open { --s: #b4532a; } .mk-note.s-in_progress { --s: #2f6fb0; } .mk-note.s-done { --s: #2f7d57; } .mk-note.s-declined { --s: #5d6470; }
/* a note that names a place and has no pin of its own (a Staff viewer's): a round tag with a dashed rim, at the place;
   several at one place stand side by side (--k: its position among them) */
.mk-note.at-place { margin-left: -13px; border-radius: 13px; box-shadow: 0 6px 14px -4px rgba(3, 6, 14, 0.6); outline: 1.5px dashed rgba(255, 255, 255, 0.94); outline-offset: 1px; translate: calc(var(--k, 0) * 34px) 0; }
/* (WS-56) the number of a note that marks a route or an area: a round badge on the route's first point or the area's centre */
.mk-note.on-shape { margin: -13px 0 0 -13px; border-radius: 13px; }
.mk-note:hover, .mk-note.active { z-index: 1; }
.mk-note.active { box-shadow: 0 0 0 2px #fff, 0 0 0 5px color-mix(in srgb, var(--gold) 75%, transparent), 0 8px 18px -6px rgba(3, 6, 14, 0.6); }
.mk-note:focus-visible { outline: 2px solid var(--gold); outline-offset: 4px; }
.mk-draft { width: 44px; height: 46px; margin: -46px 0 0 -22px; display: grid; place-items: end center; cursor: grab; touch-action: none; z-index: 2; }
.mk-draft::before { content: ''; width: 26px; height: 26px; margin-bottom: 6px; border-radius: 50% 50% 50% 3px; rotate: -45deg; background: var(--gold); box-shadow: 0 0 0 2px #fff, 0 8px 16px -4px rgba(3, 6, 14, 0.65); }
.mk-draft:active { cursor: grabbing; }
.mk-draft:focus-visible { outline: none; }
.mk-draft:focus-visible::before { box-shadow: 0 0 0 2px #fff, 0 0 0 5px rgba(11, 15, 23, 0.7); }

/* "you are here": a quiet dot with a slow ring, and the words above it */
#marks-keep .mk-here { width: 0; height: 0; z-index: 3; }
#marks-keep .mk-here.edit { pointer-events: auto; cursor: grab; } /* WS-91: its spot fine-tuned in the editor: dragged */
#marks-keep .mk-here.edit i { width: 30px; height: 30px; left: -15px; top: -15px; }
.mk-here i { position: absolute; left: -11px; top: -11px; width: 22px; height: 22px; border-radius: 50%; background: var(--gold); border: 3px solid #fff; box-shadow: 0 4px 14px rgba(3, 6, 14, 0.6); }
.mk-here i::after { content: ''; position: absolute; inset: -16px; border-radius: 50%; border: 2px solid #fff; opacity: 0; animation: mk-here 3.6s var(--ease-out) infinite; }
@keyframes mk-here { 0% { scale: 0.4; opacity: 0.85; } 70%, 100% { scale: 1.2; opacity: 0; } }
.mk-here span { position: absolute; left: 0; top: -20px; translate: -50% -100%; padding: 8px 14px; border-radius: 999px; background: #fff; color: var(--ink); font: 600 12px/1 var(--font-ui); letter-spacing: 0.03em; white-space: nowrap;
  box-shadow: 0 10px 24px -10px rgba(3, 6, 14, 0.75); }
@media (prefers-reduced-motion: reduce) { .mk-here i::after { animation: none; scale: 1; opacity: 0.45; } }
/* VIS-227: where guests arrive (Fine-tune Buildings): a flag in Fine-tune's fixed amber with a dark halo */
.mk-here.arrive i { display: grid; place-items: center; background: #ff9500; color: #2a1800; border-color: #fff; box-shadow: 0 0 0 1.5px rgba(11, 15, 23, 0.85), 0 4px 14px rgba(3, 6, 14, 0.6); }
.mk-here.arrive i::after { content: none; }
.mk-here.pin i::after { content: none; } /* a place's pin being moved in the editor: the gold dot, still */
.mk-here.arrive i svg { width: 62%; height: 62%; }
#marks-keep .mk-here.edit:active { cursor: grabbing; }

/* ---- WS-91 live location (web/js/lazy/locate.js): the guest's dot, its accuracy ring on the ground, the cone where
   the phone points; the line at the bottom (a note, or the route: where to, how far, minutes on foot); the button's
   states (looking, following, let go). One blue for the dot and its route, as map apps use: it reads as "you". */
:root { --loc: #2f8cff; }
#marks-keep .loc-dot { width: 0; height: 0; z-index: 4; }
.loc-dot i { position: absolute; left: -9px; top: -9px; width: 18px; height: 18px; border-radius: 50%; background: var(--loc); border: 3px solid #fff; box-shadow: 0 2px 10px rgba(3, 6, 14, 0.55); }
.loc-dot i::after { content: ''; position: absolute; inset: -3px; border-radius: 50%; background: var(--loc); opacity: 0; animation: loc-pulse 2.4s var(--ease-out) infinite; z-index: -1; }
@keyframes loc-pulse { 0% { scale: 1; opacity: 0.55; } 80%, 100% { scale: 3.2; opacity: 0; } }
.loc-cone { position: absolute; left: -30px; top: -54px; width: 60px; height: 54px; transform-origin: 30px 54px; pointer-events: none;
  background: radial-gradient(64px 64px at 50% 100%, rgba(47, 140, 255, 0.85), rgba(47, 140, 255, 0.25) 60%, rgba(47, 140, 255, 0) 100%); clip-path: polygon(50% 100%, 8% 0, 92% 0); }
#marks-keep .loc-acc { width: 320px; height: 320px; margin: -160px 0 0 -160px; border-radius: 50%; background: rgba(47, 140, 255, 0.16); box-shadow: inset 0 0 0 6.4px rgba(47, 140, 255, 0.6); z-index: 2; } /* radius 160 = locate.js RING: drawn large, scaled down */
.loc-bar { position: fixed; left: 50%; top: var(--wf-top, 20px); z-index: 14; /* WS-91 part 2: at the wayfinding spot (chrome/column.js fitSpot) */ display: flex; align-items: center; gap: 12px; max-width: min(560px, calc(100% - 32px)); width: max-content;
  padding: 10px 10px 10px 18px; border-radius: 999px; background: var(--glass-strong); border: 1px solid var(--hair); color: var(--text); translate: -50% 0;
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); box-shadow: 0 16px 40px -18px rgba(3, 6, 14, 0.85); animation: loc-in 0.5s var(--ease-out); }
.loc-bar[hidden] { display: none; }
@keyframes loc-in { from { opacity: 0; translate: -50% -10px; } }
.loc-bar p { margin: 0; font-size: 13px; line-height: 1.4; }
.loc-bar button { flex: none; height: 36px; padding: 0 16px; border-radius: 999px; font-size: 13px; font-weight: 600; }
.loc-bar .loc-act, .loc-bar .loc-end { background: var(--loc); color: #fff; }
.loc-bar .loc-x { width: 32px; height: 32px; padding: 0; position: relative; color: var(--muted); }
.loc-bar .loc-x::before, .loc-bar .loc-x::after { content: ''; position: absolute; left: 10px; top: 15.5px; width: 12px; height: 1.5px; background: currentColor; rotate: 45deg; }
.loc-bar .loc-x::after { rotate: -45deg; }
.loc-bar.route { gap: 16px; padding-left: 20px; }
.loc-to, .loc-meta { display: flex; flex-direction: column; min-width: 0; line-height: 1.2; }
.loc-to small, .loc-meta small { color: var(--muted); font-size: 11px; letter-spacing: 0.03em; }
.loc-to b { font: 400 18px/1.2 var(--font-display); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 260px; }
.loc-meta { padding-left: 16px; border-left: 1px solid var(--hair-strong); }
.loc-meta b { font-size: 15px; font-weight: 600; white-space: nowrap; }
#locate-btn.busy .ic { animation: loc-busy 1.2s ease-in-out infinite; }
@keyframes loc-busy { 50% { opacity: 0.35; } }
#locate-btn.on { background: var(--loc); color: #fff; }
#locate-btn.on .ic, #locate-btn.free .ic { fill: currentColor; }
#locate-btn.free { color: var(--loc); }
#card .card-route { display: inline-flex; align-items: center; gap: 8px; height: 48px; padding: 0 18px; border-radius: 999px; border: 1px solid var(--hair-strong); font-size: 13px; font-weight: 600; letter-spacing: 0.02em; transition: background 0.3s var(--ease); }
#card .card-route:hover { background: var(--shell); }
#card .card-route .ic { width: 18px; height: 18px; color: var(--loc); }
@media (max-width: 760px) { .loc-bar { top: var(--wf-top, calc(76px + env(safe-area-inset-top))); } .loc-to b { max-width: 150px; font-size: 16px; } } /* under the phone's top row */
@media (prefers-reduced-motion: reduce) { .loc-dot i::after, #locate-btn.busy .ic { animation: none; } .loc-bar { animation: none; } }
/* WS-91 part 2: "You" on the guest's dot while a sign's marker is on the map (that marker then says the sign's label) */
.loc-you { position: absolute; left: 15px; top: -10px; padding: 4px 9px; border-radius: 999px; background: var(--loc); color: #fff; font: 600 11px/1 var(--font-ui); letter-spacing: 0.03em; white-space: nowrap; box-shadow: 0 6px 16px -8px rgba(3, 6, 14, 0.8); }
.loc-you[hidden] { display: none; }

/* ---- WS-91 part 2 "Where to?" (chrome/column.js, web/js/lazy/whereto.js): one small button at the wayfinding spot,
   the top middle of the map under whatever bar is there (fitSpot writes --wf-top); pressed, one field there with its
   suggestions below. It gives way to the route bar (the same spot), and waits while a panel leaves it no room. */
.wf { position: fixed; left: 50%; top: var(--wf-top, 20px); translate: -50% 0; z-index: 12; transition: opacity 0.35s var(--ease), visibility 0.35s; }
@media (max-width: 760px) { .wf { top: var(--wf-top, calc(76px + env(safe-area-inset-top))); } }
body.loc-bar-on .wf, body.wf-open .wf, body.wf-full .wf { opacity: 0; visibility: hidden; pointer-events: none; }
.wf-pill { height: 40px; padding: 0 17px 0 13px; gap: 8px; color: var(--text); font-weight: 600; white-space: nowrap; box-shadow: 0 12px 30px -16px rgba(3, 6, 14, 0.85); }
.wf-pill .ic { width: 17px; height: 17px; color: var(--loc); stroke-width: 2; }
.wf-pill:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
.wf-box { position: fixed; left: 50%; top: var(--wf-top, 20px); translate: -50% 0; z-index: 17; width: min(380px, calc(100vw - 24px)); padding: 4px; border-radius: 24px;
  background: var(--glass-strong); border: 1px solid var(--hair); color: var(--text); backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px); box-shadow: 0 22px 50px -20px rgba(3, 6, 14, 0.9); animation: loc-in 0.35s var(--ease-out); }
@media (max-width: 760px) { .wf-box { top: var(--wf-top, calc(76px + env(safe-area-inset-top))); } }
.wf-box[hidden] { display: none; }
.wf-field { display: flex; align-items: center; gap: 10px; height: 46px; padding: 0 4px 0 14px; }
.wf-field > .ic { width: 18px; height: 18px; flex: none; color: var(--loc); stroke-width: 2; }
.wf-field input { flex: 1; min-width: 0; height: 100%; border: 0; background: none; color: inherit; font: 500 16px/1 var(--font-ui); outline: none; } /* 16px: a phone does not zoom into the field */
.wf-field input::placeholder { color: var(--muted); }
.wf-field input::-webkit-search-cancel-button { display: none; }
.wf-x { width: 38px; height: 38px; flex: none; display: grid; place-items: center; border-radius: 50%; color: var(--muted); }
.wf-x:hover, .wf-x:focus-visible { background: rgba(255, 255, 255, 0.08); color: var(--text); outline: none; }
.wf-x .ic { width: 16px; height: 16px; }
.wf-list { list-style: none; margin: 0; padding: 4px 0 0; max-height: min(46dvh, 340px); overflow-y: auto; border-top: 1px solid var(--hair); scrollbar-width: none; }
.wf-list:empty { display: none; }
.wf-opt { display: flex; align-items: center; gap: 10px; min-height: 50px; padding: 7px 14px; border-radius: 18px; cursor: pointer; }
.wf-opt.on, .wf-opt:hover { background: rgba(255, 255, 255, 0.07); }
.wf-title { display: none; } /* the words of "Where to?", for a style whose button is a circle without them (halo.css) */
/* each result's photo (the Explore list's, chrome/explore.js), a unit's number on it; a pin or a place without a photo: an icon */
.wf-thumb { position: relative; width: 40px; height: 40px; flex: none; display: grid; place-items: center; border-radius: 11px; overflow: hidden; background: linear-gradient(135deg, #24324c, #121827); box-shadow: inset 0 0 0 1px var(--hair); color: var(--muted); }
.wf-thumb img { width: 100%; height: 100%; object-fit: cover; }
.wf-thumb .ic { width: 18px; height: 18px; }
.wf-thumb .no { position: absolute; left: 3px; bottom: 3px; min-width: 16px; padding: 1px 4px; border-radius: 6px; background: var(--glass-strong); box-shadow: inset 0 0 0 1px var(--hair); font-size: 10.5px; font-weight: 700; line-height: 1.3; text-align: center; color: var(--text); }
.wf-txt { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; }
.wf-txt b { font-size: 14.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wf-txt small { color: var(--muted); font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wf-mine .wf-txt small { color: var(--loc); font-weight: 600; letter-spacing: 0.02em; }
.wf-forget { flex: none; height: 32px; padding: 0 12px; border-radius: 999px; border: 1px solid var(--hair-strong); color: var(--muted); font-size: 12px; font-weight: 600; }
.wf-forget:hover, .wf-forget:focus-visible { color: var(--text); background: rgba(255, 255, 255, 0.06); outline: none; }
.wf-none { padding: 12px 14px 10px; color: var(--muted); font-size: 13px; line-height: 1.4; }
@media (prefers-reduced-motion: reduce) { .wf-box { animation: none; } }

/* ---- VIS-82: a stop's short text while a tour plays (preset tours.show "text"; web/js/chrome/tourtext.js). Small,
   never over the middle of the picture, where the camera puts the stop. Three looks, the preset's tours.textLook:
   lower (a lower third, the default), subtitle (one line in a pill), top (a quiet line at the top). */
.tour-text { position: fixed; left: 50%; z-index: 9; display: flex; align-items: baseline; gap: 10px; max-width: min(680px, calc(100% - 48px)); pointer-events: none; color: var(--text);
  opacity: 0; transform: translate(-50%, 8px); transition: opacity 0.6s var(--ease), transform 0.8s var(--ease); }
.tour-text.show { opacity: 1; transform: translate(-50%, 0); }
.tour-text b { flex: none; font: 400 19px/1.1 var(--font-display); white-space: nowrap; }
.tour-text span { min-width: 0; font-size: 13px; line-height: 1.4; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tour-text b:empty, .tour-text span:empty { display: none; }
.tour-text.is-subtitle { bottom: 116px; padding: 9px 18px; border-radius: 999px; background: var(--glass-strong); border: 1px solid var(--hair); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); }
.tour-text.is-top { top: 84px; padding: 0 4px; text-shadow: 0 1px 12px rgba(3, 6, 14, 0.9), 0 0 2px rgba(3, 6, 14, 0.8); }
.tour-text.is-top span { color: var(--text); opacity: 0.82; }
.tour-text.is-lower { bottom: 116px; flex-direction: column; align-items: flex-start; gap: 3px; width: min(460px, calc(100% - 48px)); padding: 10px 16px 11px; border-radius: 4px 14px 14px 4px;
  background: var(--glass-strong); border-left: 2px solid var(--gold); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); }
.tour-text.is-lower b { font-size: 18px; }
.tour-text.is-lower span { max-width: 100%; }
@media (max-width: 760px) {
  .tour-text { max-width: calc(100% - 24px); }
  .tour-text.is-subtitle { flex-direction: column; align-items: center; gap: 2px; border-radius: 16px; text-align: center; }
  .tour-text.is-top { top: 64px; }
  .tour-text b { font-size: 17px; }
}
@media (prefers-reduced-motion: reduce) { .tour-text { transition: opacity 0.3s; transform: translate(-50%, 0); } }

/* ---- The tour screen (owner's picks Q5 A "Only the words", Q7 B, Q8 B, 2026-10-31; js/chrome/tourscreen.js). While a
   tour plays (body[data-tour]: text, card or none, what the tour shows) the map style's own pieces step aside, the same
   in every style and on phones: every child of the page and of #chrome but the map and its place names, the tour's
   words (the text look #tour-text, a style's own caption .tour-say, a phone's #ph-tour, the lobby panel), the place
   card while the tour shows the card, the toast, the attract prompt, Clear display's (i) and note, the editor's own
   marks (mms-*) and the tour screen itself. A piece with neither an id nor a class (the &perf readout) stays.
   Important: the entrance animation holds the controls' opacity. Nothing here names a style.
   The bottom is the tour's band (--tour-band): the progress line and, for 3 s after a touch, a click, a key or a mouse
   move, back, pause / play, next and Stop tour; every low word stands above it, so nothing moves when the buttons come.
   A tour that shows the card has both at the top (the cards of the styles sit at the bottom or below 12 px). */
body[data-tour] { --tour-band: 92px; }
body[data-tour] > :is([id], [class]):not(#scene, #labels, #chrome, #season-wait, .season-cover, .grain, #loader, .ld-close, #tour-text, .tour-say, #tour-screen, .clear-i, .clear-note, [id^="mms-"], [class^="mms-"]),
body[data-tour] #chrome > :not(#card, #lobby, #toast, #tooltip, .attract-cta, #ph), body[data-tour] #ph > :not(#ph-tour), body[data-tour]:not([data-tour="card"]) #card {
  opacity: 0 !important; visibility: hidden !important; pointer-events: none !important; transition: opacity var(--tour-fade, 0.4s) var(--ease), visibility 0s var(--tour-fade, 0.4s) !important; }
body[data-tour] .tour-text:not(.is-top) { bottom: var(--tour-band); }
#tour-screen { display: none; }
body[data-tour] #tour-screen { display: block; }
/* over the map and its place names, under every piece that stays: the press that asks for the buttons */
.tour-catch { position: fixed; inset: 0; z-index: 6; }
#tour-screen:is(.ui, .keep) .tour-catch, body:is(.attract, .mms-editing) .tour-catch { display: none; }
.tour-line { position: fixed; left: 24px; right: 24px; bottom: calc(16px + env(safe-area-inset-bottom, 0px)); z-index: 12; display: flex; gap: 4px; pointer-events: none; }
.tour-line i { flex: 1; height: 3px; border-radius: 2px; overflow: hidden; background: rgba(255, 255, 255, 0.26); box-shadow: 0 1px 4px rgba(3, 6, 14, 0.4); }
.tour-line i.done, .tour-line b { background: var(--text); }
.tour-line i.now { background: color-mix(in srgb, var(--text) 50%, rgba(255, 255, 255, 0.2)); }
.tour-line b { display: block; height: 100%; transform-origin: 0 50%; animation: tour-fill var(--secs, 8s) linear both; }
#tour-screen.no-steps .tour-line { display: none; } /* the tour's own `steps: false` */
body[data-tour-pins="off"] #labels { opacity: 0; visibility: hidden; transition: opacity var(--tour-fade, 0.4s) var(--ease), visibility 0s var(--tour-fade, 0.4s); } /* the tour's own `pins: false` */
#tour-screen.paused .tour-line b, body.clear-display .tour-line b { animation-play-state: paused; } /* (clear display: the tour waits too) */
@keyframes tour-fill { from { transform: scaleX(0); } }
.tour-ctl { position: fixed; left: 50%; bottom: calc(30px + env(safe-area-inset-bottom, 0px)); z-index: 13; translate: -50% 0; display: flex; align-items: center; gap: 2px; padding: 4px;
  border-radius: 999px; background: var(--glass-strong); border: 1px solid var(--hair); box-shadow: 0 16px 40px -18px rgba(3, 6, 14, 0.8); color: var(--text); font: 500 14px/1 var(--font-ui);
  opacity: 0; visibility: hidden; transition: opacity 0.3s var(--ease), visibility 0s 0.3s; }
#tour-screen.ui .tour-ctl { opacity: 1; visibility: visible; transition: opacity 0.2s var(--ease); }
.tour-ctl button { display: grid; place-items: center; width: 44px; height: 44px; border-radius: 999px; transition: background-color 0.18s ease; }
.tour-ctl button:hover { background: color-mix(in srgb, var(--text) 10%, transparent); }
.tour-ctl button:focus-visible { outline: 2px solid var(--gold); outline-offset: 1px; }
.tour-ctl button:disabled { opacity: 0.35; pointer-events: none; }
.tour-ctl .ic { width: 20px; height: 20px; }
.tour-ctl .tc-stop { width: auto; padding: 0 18px; white-space: nowrap; }
.tour-ctl .tc-play, #tour-screen.paused .tc-pause { display: none; }
#tour-screen.paused .tc-play { display: block; }
body[data-tour="card"] .tour-line { top: calc(6px + env(safe-area-inset-top, 0px)); bottom: auto; }
body[data-tour="card"] .tour-ctl { top: calc(18px + env(safe-area-inset-top, 0px)); bottom: auto; }
body.lobby-panel .tour-line { right: 440px; } /* beside the lobby panel (#lobby, 400 px on the right) */
body.lobby-panel .tour-ctl { left: calc(50% - 210px); }
@media (max-width: 760px) {
  body[data-tour] { --tour-band: calc(86px + env(safe-area-inset-bottom, 0px)); }
  .tour-line { left: 16px; right: 16px; bottom: calc(12px + env(safe-area-inset-bottom, 0px)); }
  .tour-ctl { bottom: calc(24px + env(safe-area-inset-bottom, 0px)); }
  body.lobby-panel .tour-line { right: 16px; top: calc(6px + env(safe-area-inset-top, 0px)); bottom: auto; } /* the panel takes the bottom */
  body.lobby-panel .tour-ctl { left: 50%; top: calc(18px + env(safe-area-inset-top, 0px)); bottom: auto; }
}
@media (prefers-reduced-motion: reduce) { .tour-line b { display: none; } .tour-ctl, #tour-screen.ui .tour-ctl { transition: none; } body[data-tour] { --tour-fade: 0s; } }
/* VIS-128: chrome/card.js fitTop (Night Glass only). An open card on a narrow window (a portrait tablet): where the
   top-right buttons, moved left of the card, would sit on the brand or the season switch, the tour button keeps its icon
   alone (data-top="icons"); still no room ("low"), the row takes a line of its own under the brand and the explore
   panel (and the tour list) move down by it */
body[data-top]:not(.mms-style) .top-actions #tour-btn span { display: none; }
body[data-top]:not(.mms-style) .top-actions #tour-btn { padding: 0 13px; }
body[data-top="low"]:not(.mms-style) .top-actions { top: 92px; }
body[data-top="low"]:not(.mms-style) #explore { top: 148px; }
body[data-top="low"]:not(.mms-style) .menu-pop { top: 146px; }
/* VIS-128: the booking button names the room type ("Check Glass Suite availability"): where it and the
   previous / next buttons do not fit on one line, the stepper takes the next line instead of squeezing both */
#card .actions { flex-wrap: wrap; }
/* VIS-128: a header without a logo (none set) keeps its text off the pill's edge */
.brand > .core > div:only-child { padding-left: 15px; }

/* ---- VIS-230 phones: ONE column (web/js/chrome/phone.js; layout B 2026-10-21, the column "1A Capsule" 2026-11-05).
   body.ph only on a phone (max-width 760 px) outside the lobby layouts and ?kiosk; desktop never matches. The top of
   the map stays empty (the brand pill alone) and nothing is docked at the bottom at rest: one slim capsule in the
   bottom-right corner holds Search (or the "Where to?" pin), a style's own buttons (.ph-lead), the settings rows,
   Settings, a hairline, the map tools and the map data (i). Labels are separate small pills left of the capsule.
   Flat fills, a hairline and one soft shadow: no backdrop filter anywhere on a phone (VIS-249). Motion is transform
   and opacity only. Where things stand (phone.js fit): --ph-b (what an open card, tour or route covers at the
   bottom), --ph-rb (the column's bottom), --ph-rest (the column without its rows), --ph-find-b / --ph-find-r (the
   bottom of Search, the column's left edge + 10 px), --ph-side-b (the bottom of the button a side row opened from).
   Hooks a map style re-skins (README "Phones"): .ph-rail .ph-find .ph-pin .ph-lead .ph-rows .ph-row .ph-ch .ph-lb
   .ph-ic .ph-back .ph-dot .ph-d .ph-pick .ph-date .ph-set .ph-dv .ph-tools .ph-side .ph-side-row
   .ph-sback .ph-pop .ph-time .ph-tc-* .ph-tour, and body.ph-rail-open, .ph-choose + .ph-choose-<row>, .ph-searching, .ph-side-open,
   .ph-touring, .ph-wayfind, .menu-open (= .ph-searching), .wf-open. */
body.ph { --ph-rb: max(calc(28px + env(safe-area-inset-bottom, 0px)), calc(var(--ph-b, 0px) + 14px)); --ph-glass: rgba(20, 26, 38, 0.88); --ph-dock: rgba(16, 21, 31, 0.94);
  --ph-edge: inset 0 0 0 1px var(--hair), 0 10px 28px -14px rgba(3, 6, 14, 0.8); --ph-ease: cubic-bezier(0.2, 0.9, 0.25, 1); }
body.ph [data-ph] { display: none !important; } /* what the column stands for (phone.js mark) */
body.ph .tour-text, body.ph .mobile-explore, body.ph .wf { display: none !important; } /* the tour's caption says the stop; "Where to?" is the column's pin */
/* the brand pill, under the phone's clock row */
body.ph .top-left { top: 56px; left: 12px; }
body.ph .brand { padding: 0; }
body.ph .brand > .core { height: 40px; gap: 8px; padding: 0 16px 0 4px; }
body.ph .brand img { width: 32px; height: 32px; padding: 2px; }
body.ph .brand.mark-only > .core { padding: 0 12px; }
body.ph .brand.mark-only img { width: auto; height: 30px; }
body.ph .brand h1 { font-size: 20px; font-weight: 600; line-height: 1; }
body.ph #toast { top: 104px; max-width: calc(100vw - 24px); }
/* the column: one capsule, 44 px buttons, 4 px padding and gaps */
.ph-rail { position: fixed; right: 12px; bottom: var(--ph-rb); z-index: 26; width: 52px; box-sizing: border-box; padding: 4px; display: flex; flex-direction: column; align-items: center; gap: 4px;
  border-radius: 26px; background: var(--ph-glass); box-shadow: var(--ph-edge); transition: bottom 0.4s var(--ease); }
.ph-rail[hidden], .ph-rail > [hidden], .ph-lead:empty, .ph-side[hidden] { display: none; }
body.ph-rail-open .ph-find { display: none; } /* Search steps aside while Settings is open */
body.ready .ph-rail { animation: chrome-in 1.1s var(--ease-out) 1.6s both; }
body.chrome-live .ph-rail { animation-delay: 0s; animation-duration: 0.45s; }
.ph-lead { display: flex; flex-direction: column; gap: 4px; }
.ph-find, .ph-set, .ph-ic, .ph-lead > *, body.ph .ph-tools > .round-btn { width: 44px; height: 44px; flex: none; display: grid; place-items: center; padding: 0; border: 0; border-radius: 22px;
  background: transparent; color: var(--text); box-shadow: none; transition: transform 0.14s var(--ease), background-color 0.2s ease, color 0.2s ease; }
:is(.ph-find, .ph-set, .ph-sback, .ph-lead > *, .ph-tools > *):active, :is(.ph-ch, .ph-back, [data-row]):active > :is(.ph-ic, .ph-lb) { transform: scale(0.93); }
.ph-rail .ic, .ph-side .ic { width: 20px; height: 20px; stroke-width: 1.6; }
body.ph .ph-tools .round-btn { color: var(--text); } /* the map data (i) as bright as the tools */
.ph-tools { display: flex; flex-direction: column; gap: 4px; }
.ph-dv { width: 24px; height: 1px; flex: none; margin: 1px auto; background: var(--hair-strong); }
/* Settings: the sliders turn into a cross (a cross-fade and a quarter turn) */
.ph-set > .ic { grid-area: 1 / 1; transition: opacity 0.28s ease, transform 0.28s var(--ph-ease); }
.ph-set .ph-x { opacity: 0; transform: rotate(-90deg); }
body.ph-rail-open .ph-set > .ic:not(.ph-x) { opacity: 0; transform: rotate(90deg); }
body.ph-rail-open .ph-set .ph-x { opacity: 1; transform: none; }
/* chosen: an Ivory disc with the icon in Ink (Settings open, Search open, a chosen choice, northern lights on, playing) */
body.ph-rail-open .ph-set, .ph-find[aria-expanded="true"], .ph-row.on > .ph-ic, .ph-ic.on, .ph-row[aria-expanded="true"] > .ph-ic { background: var(--text); color: var(--ink); }
.ph-dot.on > .ph-ic { background: transparent; }
.ph-find:focus-visible, .ph-set:focus-visible, .ph-row:focus-visible, .ph-ic:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
/* the column's own icons (Settings, Light, Language) are CSS masks in the thin-line set: no bytes in the engine (phone.js mask) */
.ph-i { display: block; background: currentColor; -webkit-mask: var(--i) center / contain no-repeat; mask: var(--i) center / contain no-repeat; }
.ph-i[data-i="sliders"] { --i: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 7h9M17 7h3M4 17h3M11 17h9'/%3E%3Ccircle cx='15' cy='7' r='2'/%3E%3Ccircle cx='9' cy='17' r='2'/%3E%3C/svg%3E"); }
.ph-i[data-i="globe"] { --i: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='8.5'/%3E%3Cpath d='M3.5 12h17M12 3.5c2.3 2.5 3.5 5.3 3.5 8.5s-1.2 6-3.5 8.5c-2.3-2.5-3.5-5.3-3.5-8.5s1.2-6 3.5-8.5Z'/%3E%3C/svg%3E"); }
.ph-i[data-i="clock"] { --i: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='8.5'/%3E%3Cpath d='M12 7.5V12l3 2'/%3E%3C/svg%3E"); }
body.ph:not(.mms-style) .ph-tools #compass i { transform: rotate(var(--rot, 0rad)) translateY(-12px); }
body.ph:not(.mms-style) .ph-tools #compass .needle { top: 9px; }
/* the rows (and a row's choices in their place): they grow upward from Settings, each label a pill to the left. The
   box reaches 280 px left of the capsule so the pills show while it scrolls; only the rows take a press */
.ph-rows { display: none; flex-direction: column; align-items: flex-end; gap: 4px; align-self: flex-end; box-sizing: content-box; width: 44px; padding-left: 280px;
  max-height: calc(100dvh - var(--ph-rb) - var(--ph-rest, 300px) - 64px - env(safe-area-inset-top, 0px)); overflow-y: auto; scrollbar-width: none; pointer-events: none; }
.ph-rows::-webkit-scrollbar { display: none; }
body.ph-rail-open .ph-rows { display: flex; }
.ph-row { position: relative; display: block; width: 44px; height: 44px; flex: none; padding: 0; border: 0; background: none; color: var(--text); pointer-events: auto; cursor: pointer; }
.ph-lb { position: absolute; right: calc(100% + 10px); top: 4px; display: flex; align-items: center; gap: 6px; height: 36px; padding: 0 14px; border-radius: 18px; white-space: nowrap;
  font: 600 14px/1 var(--font-ui); color: var(--text); background: var(--ph-glass); box-shadow: var(--ph-edge); transition: background-color 0.2s ease, color 0.2s ease; }
.ph-lb b { font-weight: 500; color: var(--muted); }
.ph-lb b:empty { display: none; }
.ph-lb .ic { width: 14px; height: 14px; margin: 0 -2px 0 -5px; color: var(--muted); } /* the back row's ‹ */
.ph-ch.on .ph-lb::after { content: ''; flex: none; width: 9px; height: 5px; margin: -3px 0 0 2px; border: solid var(--gold); border-width: 0 0 2px 2px; rotate: -45deg; } /* the chosen one's small check */
.ph-back .ph-lb { color: var(--muted); }
/* a named date: a dot in place of an icon, the chosen one bigger and in the accent */
.ph-d { width: 7px; height: 7px; border-radius: 50%; background: var(--muted); transition: transform 0.2s ease, background-color 0.2s ease; }
.ph-dot.on .ph-d { transform: scale(1.6); background: var(--gold); }
/* "Pick a date": the native picker, under its row (a press on the row opens it) */
.ph-date { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; pointer-events: none; }
/* a row's panel (phone.js POPS: the time card, the trees popover, the northern lights panel): left of the column, level
   with its row (--ph-pop-b; side mode: above the row of icons), flat: no frosting, one hairline, one shadow */
body.ph .ph-pop { position: fixed !important; inset: auto var(--ph-find-r, 74px) var(--ph-pop-b, 120px) auto !important; translate: none !important; margin: 0 !important; z-index: 27;
  width: min(300px, calc(100vw - var(--ph-find-r, 74px) - 12px)) !important; max-width: none !important; max-height: calc(100dvh - var(--ph-pop-b, 120px) - 20px - env(safe-area-inset-top, 0px)); overflow-y: auto; box-sizing: border-box;
  border: 0; border-radius: 22px; background: var(--ph-dock); box-shadow: var(--ph-edge); -webkit-backdrop-filter: none !important; backdrop-filter: none !important; animation: ph-slide 0.24s var(--ph-ease) both; }
/* the time card: the clock and the part of the day with play beside them, the hour's slider, one row for the day */
.ph-time { padding: 14px 14px 6px; color: var(--text); }
.ph-tc-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.ph-tc-now { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.ph-time .ph-clock { font: 600 32px/1 var(--font-ui); font-variant-numeric: tabular-nums; letter-spacing: 0.01em; }
.ph-phase { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: 500 13px/1.2 var(--font-ui); color: var(--muted); }
.ph-tc-play { flex: none; width: 44px; height: 44px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 22px; color: var(--text); background: var(--ph-glass);
  box-shadow: inset 0 0 0 1px var(--hair); transition: transform 0.14s var(--ph-ease), background-color 0.2s ease, color 0.2s ease; }
.ph-tc-play.on { background: var(--text); color: var(--ink); }
.ph-tc-play .ic { width: 18px; height: 18px; }
:is(.ph-tc-play, .ph-tc-day, .ph-tc-d):active { transform: scale(0.97); }
/* the hour: a plain track and a round handle only (the old slider's tall invisible handle showed as a dark box on iPhones) */
.ph-hr { -webkit-appearance: none; appearance: none; display: block; width: 100%; height: 28px; margin: 12px 0 4px; background: transparent; touch-action: none; cursor: pointer; }
.ph-hr::-webkit-slider-runnable-track { height: 4px; border-radius: 2px; background: color-mix(in srgb, var(--text) 22%, transparent); }
.ph-hr::-moz-range-track { height: 4px; border-radius: 2px; background: color-mix(in srgb, var(--text) 22%, transparent); }
.ph-hr::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 22px; height: 22px; margin-top: -9px; border: 0; border-radius: 50%; background: var(--text); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.45); }
.ph-hr::-moz-range-thumb { width: 22px; height: 22px; border: 0; border-radius: 50%; background: var(--text); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.45); }
/* the day ("21 Dec Polar night", Change day) and, opened, the season's named dates and Pick a date in the card */
.ph-tc-day, .ph-tc-d { position: relative; display: flex; align-items: center; width: 100%; box-sizing: border-box; border: 0; background: none; color: var(--text); font: 500 14px/1.2 var(--font-ui); text-align: left; cursor: pointer;
  transition: transform 0.14s var(--ph-ease); }
.ph-tc-day { gap: 10px; min-height: 48px; margin-top: 6px; padding: 0 2px; border-top: 1px solid var(--hair); }
.ph-tc-day > .ic, .ph-tc-d > .ic { flex: none; width: 18px; height: 18px; color: var(--muted); }
.ph-tc-txt { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
:is(.ph-tc-txt, .ph-tc-d) b { font-weight: 600; }
:is(.ph-tc-txt, .ph-tc-d) small { font-size: 13px; color: var(--muted); }
.ph-tc-go { flex: none; display: flex; align-items: center; gap: 2px; font-size: 13px; color: var(--muted); }
.ph-tc-go .ic { width: 14px; height: 14px; }
.ph-tc-days { display: flex; flex-direction: column; padding: 0 0 6px; }
.ph-tc-d { gap: 12px; min-height: 44px; padding: 0 2px 0 6px; border-radius: 12px; }
.ph-tc-d > .ph-d { flex: none; margin: 0 5px; }
.ph-tc-d.on .ph-d { transform: scale(1.6); background: var(--gold); }
.ph-tc-d.on b::after { content: ''; display: inline-block; width: 9px; height: 5px; margin: 0 0 3px 8px; border: solid var(--gold); border-width: 0 0 2px 2px; rotate: -45deg; }
.ph-tc-days > * { animation: ph-rise 0.22s var(--ph-ease) backwards; }
.ph-code { font: 700 13px/1 var(--font-ui); letter-spacing: 0.04em; }
/* a style's side mode (phone.js `side`): the choices in one row left of the column, level with the button that opened
   it; the close nearest the column */
.ph-side { position: fixed; right: var(--ph-find-r, 74px); bottom: calc(var(--ph-side-b, 120px) - 4px); z-index: 26; display: flex; flex-direction: column; align-items: flex-end; gap: 8px;
  max-width: calc(100vw - var(--ph-find-r, 74px) - 8px); pointer-events: none; }
.ph-side-row { display: flex; align-items: center; gap: 4px; max-width: 100%; box-sizing: border-box; padding: 4px; border-radius: 26px; overflow-x: auto; scrollbar-width: none;
  background: var(--ph-glass); box-shadow: var(--ph-edge); pointer-events: auto; }
.ph-side-row::-webkit-scrollbar { display: none; }
/* the same cells as the column's: icons only (the words stay for screen readers) */
.ph-side .ph-lb { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.ph-side .ph-ch.on .ph-lb::after { display: none; }
/* motion: what opens rises from its button one after another (side rows slide in from the column); drawn again in
   place (a language, a date picked: .ph-still) it stays */
.ph-rows > * { animation: ph-rise 0.26s var(--ph-ease) calc(var(--i, 0) * 26ms) backwards; }
.ph-side-row > * { animation: ph-slide 0.26s var(--ph-ease) calc(var(--i, 0) * 26ms) backwards; }
.ph-still > * { animation: none; }
@keyframes ph-rise { from { opacity: 0; transform: translateY(12px) scale(0.96); } }
@keyframes ph-slide { from { opacity: 0; transform: translateX(16px); } }
@keyframes ph-up { from { opacity: 0; translate: 0 24px; } }
/* "Show where I am" offered on a wayfinding page: a label beside My location (lazy/locate.js data-offer) */
body.ph .ph-tools [data-offer] { position: relative; box-shadow: 0 0 0 2px rgba(47, 140, 255, 0.6); }
body.ph .ph-tools [data-offer]::after { content: attr(data-offer); position: absolute; right: calc(100% + 16px); top: 6px; display: flex; align-items: center; height: 32px; padding: 0 13px;
  border-radius: 16px; white-space: nowrap; font: 700 14px/1 var(--font-ui); color: #fff; background: #1a6be0; box-shadow: 0 10px 24px -12px rgba(47, 140, 255, 0.9); }
/* the map data: its box opens bottom left, clear of the column; the start chip sits left of the (i) (column.js startChip) */
body.ph #credit-pop { top: auto; left: 12px; right: auto; bottom: var(--ph-rb); }
body.ph .credit-chip { left: auto; right: 74px; bottom: var(--ph-rb); max-width: calc(100vw - 92px); }
/* Search: the page's own list of places (#explore) as a panel left of the column, its field level with Search and the
   list above it (body.ph-searching; body.menu-open is the same) */
body.ph #explore { top: auto; left: 12px; right: var(--ph-find-r, 74px); bottom: calc(var(--ph-find-b, 300px) - 4px); width: auto; height: auto; z-index: 27; padding: 0; border: 0; border-radius: 22px;
  background: none; box-shadow: none; transform: none; transition: none; animation: ph-rise 0.26s var(--ph-ease) backwards; }
body.ph:not(.ph-searching) #explore, body.ph-wayfind #explore { display: none; }
body.ph #explore > .core { display: flex; flex-direction: column; gap: 6px; max-height: calc(100dvh - var(--ph-find-b, 300px) - 64px - env(safe-area-inset-top, 0px)); padding: 6px; border-radius: 22px;
  background: var(--ph-dock); box-shadow: var(--ph-edge); }
body.ph #explore .explore-head { order: 3; padding: 0; }
body.ph #explore .explore-top, body.ph #explore .legend { display: none; }
body.ph #explore .cats { order: 2; flex-wrap: nowrap; padding: 2px 2px; gap: 6px; overflow-x: auto; scrollbar-width: none; }
body.ph #explore #browse { order: 1; display: block; flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
body.ph #search input { height: 44px; padding-left: 42px; border-radius: 22px; border: 0; background: rgba(255, 255, 255, 0.08); font-size: 16px; } /* 16 px: a phone does not zoom into it */
body.ph #search .ic { left: 14px; width: 20px; height: 20px; color: var(--gold); }
body.ph .cat { height: 34px; padding: 0 13px; gap: 7px; font: 600 14px/1 var(--font-ui); color: var(--text); background: rgba(255, 255, 255, 0.04); border: 1px solid var(--hair-strong); border-radius: 17px; flex: none; }
body.ph .cat .ic { width: 16px; height: 16px; }
body.ph .cat.on { background: var(--text); color: var(--ink); border-color: transparent; }
/* "Where to?" (lazy/whereto.js): its box where Search's list stands, the field level with the pin, the places above */
body.ph .wf-box { top: auto; left: 12px; right: var(--ph-find-r, 74px); bottom: calc(var(--ph-find-b, 300px) - 4px); width: auto; translate: none; padding: 4px; border: 0; border-radius: 22px;
  background: var(--ph-dock); box-shadow: var(--ph-edge); animation: ph-rise 0.26s var(--ph-ease) backwards; }
body.ph .wf-box:not([hidden]) { display: flex; flex-direction: column-reverse; }
body.ph .wf-list { max-height: calc(100dvh - var(--ph-find-b, 300px) - 120px - env(safe-area-inset-top, 0px)); padding: 0 0 4px; border-top: 0; border-bottom: 1px solid var(--hair); }
/* one thing at a time: the card steps aside while Settings or Search is open and comes back; a tour hides it */
body.ph-touring #card, body.ph-touring #feature-card, body.ph:is(.ph-rail-open, .ph-searching) :is(#card, #feature-card) { display: none; }
/* the place card: a bottom sheet. It opens compact, about half the screen at most (the photo, the title, one line of
   figures, two lines of text, the actions; the details below the fold) and grows to the room under the column
   (--ph-room, phone.js) when the visitor asks: its handle pressed or dragged up, or a scroll inside (card.js) */
body.ph #card, body.ph.cards-compact #card, body.ph #feature-card { top: auto; left: 0; right: 0; bottom: 0; width: auto; padding: 0; border-width: 1px 0 0; border-radius: 28px 28px 0 0; z-index: 16; }
body.ph #card, body.ph #card > .core, body.ph #feature-card, body.ph #feature-card > .core { max-height: min(var(--ph-room, 52dvh), 52dvh, 440px); transition: max-height 0.4s var(--ease), opacity 0.6s var(--ease), transform 0.8s var(--ease), filter 0.6s var(--ease); }
body.ph.cards-compact:not(.mms-style) #card, body.ph.cards-compact:not(.mms-style) #card > .core { max-height: min(var(--ph-room, 40dvh), 40dvh, 340px); }
body.ph.ph-card-full #card, body.ph.ph-card-full #card > .core { max-height: var(--ph-room, 70dvh); }
body.ph #card > .core, body.ph #feature-card > .core { border-radius: 28px 28px 0 0; padding-bottom: env(safe-area-inset-bottom, 0px); }
body.ph #card .hero, body.ph #feature-card .fc-photo { height: 160px; border-radius: 28px 28px 0 0; }
body.ph.cards-compact:not(.mms-style) #card .hero { height: 104px; }
body.ph #card .close, body.ph #feature-card .close { width: 44px; height: 44px; top: 12px; right: 12px; }
body.ph #card .body { display: flex; flex-direction: column; align-items: flex-start; padding: 12px 20px 20px; gap: 10px; }
body.ph #card .body > * { order: 5; }
body.ph #card .body > h2 { order: 1; font-size: 26px; }
body.ph #card .body > .off-season { order: 2; }
body.ph #card .body > .stats { order: 2; }
body.ph #card .body > .blurb { order: 3; }
body.ph #card .body > .actions { order: 4; }
body.ph:not(.ph-card-full) #card .blurb { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
body.ph:not(.ph-card-full) #card .stats { display: flex; flex-wrap: wrap; gap: 0; }
body.ph:not(.ph-card-full) #card .stats div { padding: 0; border: 0; background: none; }
body.ph:not(.ph-card-full) #card .stats div:nth-child(n + 3), body.ph:not(.ph-card-full) #card .stats small { display: none; }
body.ph:not(.ph-card-full) #card .stats b { margin: 0; font-size: 14px; font-weight: 600; color: var(--gold); }
body.ph:not(.ph-card-full) #card .stats div + div b::before { content: '·'; margin: 0 7px; }
.ph-grip { position: sticky; top: 0; z-index: 3; display: grid; place-items: center; width: 88px; height: 28px; margin: 0 auto -28px; } /* inside the card's scroller (card.js grip): a drag up scrolls it */
.ph-grip::before { content: ''; width: 38px; height: 5px; border-radius: 3px; background: rgba(244, 239, 230, 0.75); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.45); }
.ph-grip:focus-visible { outline: 2px solid var(--gold); outline-offset: -4px; border-radius: 14px; }
/* the tour playing: its words in a caption card at the bottom (lazy/phtour.js), above the tour's band (the progress
   line and its buttons: "The tour screen") */
.ph-tour { position: fixed; left: 12px; right: 12px; bottom: var(--tour-band, calc(86px + env(safe-area-inset-bottom, 0px))); z-index: 15; max-height: 34dvh; overflow: hidden; display: grid; gap: 10px; padding: 14px 14px 14px 16px; border-radius: 24px;
  background: var(--ph-dock); box-shadow: var(--ph-edge); animation: ph-up 0.32s var(--ease-out); }
.ph-tour[hidden] { display: none; }
.ph-tour .ph-head { display: flex; align-items: flex-start; gap: 6px; }
.ph-tour .ph-head > div { flex: 1; min-width: 0; }
.ph-tour .ph-head h2 { margin: 4px 0 0; font: 700 17px/1.25 var(--font-ui); }
.ph-tstop { margin: 2px 0 0; font-size: 13px; color: var(--muted); }
.ph-ttext { margin: 0; font-size: 13px; line-height: 1.45; color: var(--muted); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.ph-ttext:empty { display: none; }
/* walking directions: a passing note left of the column; a route takes the bottom */
body.ph .loc-bar { top: auto; left: 12px; right: 76px; bottom: var(--ph-rb); width: auto; max-width: none; translate: none; border-radius: 20px; animation: ph-up 0.32s var(--ease-out); }
body.ph .loc-bar.route { left: 0; right: 0; bottom: 0; z-index: 15; max-height: 34dvh; justify-content: space-between; padding: 18px 20px calc(22px + env(safe-area-inset-bottom, 0px)); border-radius: 28px 28px 0 0; }
body.ph .loc-bar.route .loc-end { height: 44px; padding: 0 20px; }
/* a phone held sideways (short): the column keeps its corner, Search's list and "Where to?" stand in a left column */
@media (max-height: 500px) {
  body.ph .top-left { top: 10px; }
  body.ph #explore { top: 8px; bottom: 8px; left: 8px; right: auto; width: min(380px, calc(100vw - 96px)); }
  body.ph #explore > .core { height: 100%; max-height: none; box-sizing: border-box; }
  body.ph .wf-box { bottom: 8px; left: 8px; right: auto; width: min(380px, calc(100vw - 96px)); }
  body.ph .wf-list { max-height: calc(100dvh - 80px); }
  body.ph:is(.ph-searching, .wf-open) :is(.top-left, .brand) { visibility: hidden; } /* the name steps aside while the list takes the height */
  body.ph #card, body.ph #card > .core, body.ph.cards-compact #card, body.ph.cards-compact #card > .core { max-height: min(var(--ph-room, 62dvh), 62dvh); }
  body.ph #card .hero { height: 110px; }
  body.ph-rail-open .ph-rail { bottom: 8px !important; }
}
@media (prefers-reduced-motion: reduce) {
  .ph-rail, .ph-set > .ic, .ph-lb, .ph-d, :is(.ph-find, .ph-set, .ph-ic, .ph-lead > *) { transition: none; }
  .ph-rows > *, .ph-side-row > *, .ph-tc-days > *, body.ph .ph-pop, body.ph #explore, body.ph .wf-box, .ph-tour, body.ph .loc-bar { animation: none; }
}

/* ------------------------------------------------ VIS-249 phones and touch screens: solid glass, no frosting
   A backdrop blur over the map canvas is redrawn by the GPU every frame the map draws (15-30 a second, at 3x pixels on an
   iPhone): with ~50 glass pieces on screen that heats the phone. So on the device the map treats as a phone (main.js
   `mobile`: max-width 760 px or a coarse pointer) NO element anywhere blurs what is behind it, and every glass fill is
   raised to a near-solid of the same colour, so text reads at least as well as on frosted glass. The kill rule below
   covers every stylesheet (brand-dark and the map styles, gallery, the aurora panel, styles injected by script) and any
   rule written later; a new glass colour goes in a token here (or brand-dark's phone block), never a per-rule blur.
   Also off on phones: the film grain (a full-screen blend layer over the canvas) and the blur in entrance animations.
   Lobby screens keep the full look: touch lobby screens match (pointer: coarse) too, so every phone rule here and in the
   other stylesheets' VIS-249 blocks starts with :where(body:not(.kiosk, .lobby)) (main.js: body.kiosk = ?kiosk,
   body.lobby = ?kiosk or a lobby-* layout, as PHONE_ON skips them; :where adds no weight). Only the three entrance
   keyframes below cannot be scoped: a lobby touch screen's one-time entrance runs without its blur.
   Guarded by tests/unit/runtime/phone-css.test.mjs. */
@media (max-width: 760px), (pointer: coarse) {
  :where(body:not(.kiosk, .lobby)) *, :where(body:not(.kiosk, .lobby)) *::before, :where(body:not(.kiosk, .lobby)) *::after { -webkit-backdrop-filter: none !important; backdrop-filter: none !important; }
  :where(body:not(.kiosk, .lobby)) { --glass: rgba(14, 18, 27, 0.94); --glass-strong: rgba(12, 16, 24, 0.95); --shell: rgba(22, 27, 38, 0.94); }
  /* glass written as a colour rather than a token: the same colour, nearly solid */
  :where(body:not(.kiosk, .lobby)) :is(.round-btn:hover, .shell-btn:hover) { background: rgba(30, 36, 50, 0.95); }
  :where(body:not(.kiosk, .lobby)) :is(#loader .ld-play, #loader .ld-pill) { background: color-mix(in srgb, var(--cv-ink) 92%, transparent); }
  :where(body:not(.kiosk, .lobby)) .ld-close { background: color-mix(in srgb, var(--cv-ink, #16222e) 92%, transparent); }
  :where(body:not(.kiosk, .lobby)) .controls { background: var(--glass); }
  :where(body:not(.kiosk, .lobby)) :is(.label.place, .cf-pin span) { background: rgba(12, 16, 24, 0.94); }
  :where(body:not(.kiosk, .lobby)) #card .step-inside { background: rgba(8, 11, 18, 0.9); }
  :where(body:not(.kiosk, .lobby)) #card .step-inside:hover { background: rgba(14, 18, 27, 0.94); }
  :where(body:not(.kiosk, .lobby)) :is(.int-hot span, .int-hint) { background: rgba(8, 11, 18, 0.9); }
  :where(body:not(.kiosk, .lobby)) :is(.mms-render-ui.chip, .mms-render-tips, .mms-render-ui button:not([aria-pressed="true"])) { background: rgba(14, 16, 20, 0.94) !important; } /* js/lazy/renderstudio.js injects its rule after this file */
  /* other work over the canvas a phone pays for every frame */
  :where(body:not(.kiosk, .lobby)) .grain { display: none; }
  :where(body:not(.kiosk, .lobby)) :is(#card, #toast) { filter: none; } /* closed, they sat invisible but blurred */
  @keyframes rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
  @keyframes chrome-in { from { opacity: 0; translate: 0 16px; } to { opacity: 1; translate: 0 0; } }
  @keyframes int-rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
}
