/* ── Fonts ───────────────────────────────────────────────────────────────── */

@import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,500;1,300;1,400;1,500&family=Poppins:wght@400;500;600;700&display=swap');

/* Locally-cached Poppins fallback (Cormorant Garamond has no local fallback
   in this project — matches Thera/Kira precedent, which rely on the @import
   above alone; only Ellis needed a local safety net, because its CDN link
   happened to carry italic-only weights). */
@font-face { font-family: 'Poppins'; src: url('fonts/Poppins Regular.woff2') format('woff2'); font-weight: 400; font-style: normal; }
@font-face { font-family: 'Poppins'; src: url('fonts/Poppins SemiBold.woff2') format('woff2'); font-weight: 600; font-style: normal; }
@font-face { font-family: 'Poppins'; src: url('fonts/Poppins Bold.woff2') format('woff2'); font-weight: 700; font-style: normal; }

/* ── Il Greco Apartments Virtual Tour — Design System ───────────────────── */
/* Brand navy/light-blue extracted directly from the feature sheet's own
   logo lockup (exact pixel sample, 2026-08-06): navy #213661, light blue
   #A6D1ED. --ig-navy-deep is a derived darker navy (not from the sheet) used
   as the dark-glass base, same role --tw-navy-deep plays on every other
   MetaTours project — keeps the whole floating UI legible over any pano. */
:root {
  --ig-navy-deep: #111B31;  /* dark-glass base, derived by darkening the brand navy */
  --ig-navy:      #213661;  /* Il Greco's own brand navy (exact match, from the feature sheet) */
  --ig-blue:      #A6D1ED;  /* Il Greco's own brand light blue (exact match) — accent, CTAs, active states */
  --ig-white:     #F5F8FC;  /* soft cool white — primary text on dark ground */
  --tw-serif: 'Cormorant Garamond', serif;
  --tw-sans:  'Poppins', sans-serif;
  --tw-ease:  cubic-bezier(0.25, 0.46, 0.45, 0.94);
  /* Symmetric ease-in-out for the splash exit — see enterTour() in the JS,
     which now drives this fade directly via requestAnimationFrame rather
     than relying on this CSS transition (confirmed elsewhere in the product
     line that a CSS opacity transition here can simply never start
     interpolating under real-world conditions — see spencer-block.md round
     3/4). This value is kept only as a declared fallback. */
  --tw-ease-inout: cubic-bezier(0.65, 0, 0.35, 1);

  /* Onboarding hint — deliberately independent of every --ig-* token above.
     This teaches tour MECHANICS ("drag to look around"), not brand, so it's
     designed to look identical on any project regardless of that project's
     palette or fonts — same reasoning as the native 3DVista hotspot icons
     staying white/neutral across every client (see the metatours-3dvista
     skill). Portable as-is: copy this whole block into another project's
     CSS and it needs zero adjustment. System font stack on purpose, not
     --tw-sans — this component shouldn't depend on whatever custom webfont
     a given project happens to load. */
  --hint-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --hint-bg: rgba(255, 255, 255, 0.58);
  --hint-border: rgba(255, 255, 255, 0.5);
  --hint-ink: rgba(22, 22, 26, 0.9);
  --hint-ink-soft: rgba(22, 22, 26, 0.62);
  --hint-ink-faint: rgba(22, 22, 26, 0.48);
}

/* Paints the instant the CSS is parsed, before the splash <div> even exists
   in the DOM (only inserted once the 3DVista player is ready) — closes the
   "blank/white flash before anything splash-colored shows up" gap on a slow
   initial load. */
html, body { background: var(--ig-navy-deep); }

/* ── SPLASH ──────────────────────────────────────────────────────────────── */

#tw-splash {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Solid brand navy, now purely a fallback behind #tw-splash-video — it
     paints instantly, so it covers the beat before the video's first frame
     decodes and any case where the video fails to load. Deliberately NOT a
     static hero image: the video usually decodes fast enough that an
     image-then-crossfade sequence reads as a glitch rather than a reveal. */
  background: var(--ig-navy-deep);
  transition: opacity 1.6s var(--tw-ease-inout);
  overflow: hidden;
}

/* Static hero image support — inert until the JS sets HERO_PATH and this tag
   actually renders. Same warm-cache + fade-in treatment already proven on
   Spencer Block: starts invisible over the solid navy fallback, crossfades
   in once decoded (see the `tw-hero-loaded` toggle in init()) rather than
   popping in the instant the <img> resolves. */
/* Fades in from the solid navy fallback rather than popping in the instant a
   frame decodes (Danny 2026-08-10: "it just suddenly appears"). Originally
   built with no fade at all on the theory that video decodes fast enough for
   a pop to read as instant — wrong in practice, the navy-to-frame cut was
   visible. Same entrance mechanism already proven on #tw-splash-hero below:
   opacity 0 -> 1 via a CSS transition, toggled by a `tw-video-loaded` class
   in init() (see the `loadeddata` listener there). This is NOT the exit
   push-in, which stays rAF-driven — the CSS-transition-freeze bug that rule
   is dodging is specific to properties toggled mid-exit alongside several
   others in the same tick; a single one-shot entrance fade driven by a media
   event, off the critical path of any click handler, doesn't hit it (the
   hero image has used exactly this pattern since Spencer Block with no
   issue). The exit push-in (scale) still applies on top of this via inline
   styles from the rAF loop, untouched by this transition. */
#tw-splash-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
  transform: scale(1);
  opacity: 0;
  transition: opacity 1.4s var(--tw-ease-inout);
  user-select: none;
  pointer-events: none;
}

#tw-splash-video.tw-video-loaded { opacity: 1; }

#tw-splash-hero {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
  transform: scale(1);
  opacity: 0;
  transition: opacity 1s var(--tw-ease-inout), transform 1.6s var(--tw-ease-inout);
  user-select: none;
  pointer-events: none;
}

#tw-splash-hero.tw-hero-loaded { opacity: 1; }

/* Veil over the splash video. The previous version bottomed out at 0.05 alpha
   at 42% height — precisely where the lockup sits — and carried a *lightening*
   light-blue radial on top of that, so the white wordmark had almost nothing
   to hold against bright drone footage (sunlit water, pale rooftops).
   Now it's darkest exactly behind the lockup and eases out toward the edges,
   so the logo keeps its contrast on every frame of the clip without the whole
   splash reading as a flat grey slab. Keeping the WHITE logo and darkening the
   backdrop, rather than switching to the navy mark — navy on aerial footage
   this busy would disappear into the shadows instead. */
.tw-splash-overlay {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 78% 62% at 50% 42%, rgba(6, 10, 20, 0.62) 0%, rgba(6, 10, 20, 0.42) 55%, rgba(6, 10, 20, 0.30) 100%),
    linear-gradient(180deg, rgba(6, 10, 20, 0.52) 0%, rgba(6, 10, 20, 0.22) 45%, rgba(6, 10, 20, 0.60) 100%);
  z-index: 1;
}

#tw-splash.tw-hiding {
  pointer-events: none;
}

#tw-splash.tw-gone {
  display: none;
}

.tw-splash-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 48px 36px;
  width: 100%;
  max-width: 720px;
  position: relative;
  z-index: 2;
}

.tw-splash-icon-img {
  width: clamp(76px, 7.2vw, 116px);
  height: auto;
  margin-bottom: clamp(14px, 1.4vw, 20px);
  opacity: 0;
  transform: translateY(20px);
  animation: tw-rise 1.3s 0.3s var(--tw-ease) forwards;
  user-select: none;
  pointer-events: none;
}

.tw-splash-wordmark-img {
  width: clamp(280px, 28vw, 430px);
  height: auto;
  opacity: 0;
  transform: translateY(24px);
  animation: tw-rise 1.5s 0.45s var(--tw-ease) forwards;
  user-select: none;
  pointer-events: none;
}

.tw-splash-rule {
  width: clamp(72px, 7vw, 108px);
  height: 1.5px;
  background: linear-gradient(90deg, transparent, var(--ig-blue), transparent);
  margin: clamp(18px, 1.8vw, 28px) auto;
  opacity: 0;
  animation: tw-fade 1.1s 0.9s var(--tw-ease) forwards;
}

.tw-splash-location {
  font-family: var(--tw-sans);
  font-size: clamp(15px, 1.4vw, 21px);
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(245, 248, 252, 0.78);
  margin-top: 14px;
  opacity: 0;
  animation: tw-fade 1.0s 1.15s var(--tw-ease) forwards;
}

.tw-splash-enter {
  margin-top: clamp(24px, 2.4vw, 42px);
  font-family: var(--tw-sans);
  font-size: clamp(15px, 1.2vw, 18px);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  /* Navy text on the light-blue fill — mirrors the feature sheet's own
     navy-on-light-blue treatment rather than the generic light-text-on-
     filled-accent pattern used on the gold-accented sibling projects. */
  color: var(--ig-navy-deep);
  background: var(--ig-blue);
  border: none;
  border-radius: 150px;
  padding: clamp(18px, 1.8vw, 24px) clamp(42px, 4vw, 66px);
  min-height: 72px;
  min-width: 66px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 18px;
  touch-action: manipulation;
  box-shadow: 0 4px 24px rgba(166, 209, 237, 0.30);
  transition: background 0.22s, box-shadow 0.22s, transform 0.18s var(--tw-ease);
  opacity: 0;
  animation: tw-rise 1.1s 1.4s var(--tw-ease) forwards;
}

.tw-splash-enter:hover {
  background: #c3e0f5;
  box-shadow: 0 6px 32px rgba(166, 209, 237, 0.45);
  transform: translateY(-1.5px);
}

.tw-splash-enter:focus-visible {
  outline: 2px solid var(--ig-blue);
  outline-offset: 4px;
}

.tw-splash-arrow {
  width: 21px;
  height: 21px;
  transition: transform 0.18s var(--tw-ease);
}

.tw-splash-enter:hover .tw-splash-arrow {
  transform: translateX(4.5px);
}

/* Devon Properties — pinned to bottom of splash, with label */
.tw-splash-devon-wrap {
  position: absolute;
  bottom: 40px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 11px;
  opacity: 0;
  animation: tw-fade 1.0s 1.65s var(--tw-ease) forwards;
  white-space: nowrap;
}

.tw-splash-devon-label {
  font-family: var(--tw-sans);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: rgba(245, 248, 252, 0.42);
}

.tw-splash-devon-img {
  width: clamp(100px, 8vw, 138px);
  height: auto;
  filter: drop-shadow(0 1px 10px rgba(0,0,0,0.45));
  user-select: none;
  pointer-events: none;
}

/* ── ANIMATIONS ──────────────────────────────────────────────────────────── */

@keyframes tw-rise {
  from { opacity: 0; transform: translateY(21px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes tw-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* ── VIGNETTES ───────────────────────────────────────────────────────────── */
/* Raised-cosine ease (alpha(t) = peak * 0.5 * (1 + cos(pi*t))), not hand-
   picked linear steps — a linear ramp ending in a flat 0 still has a slope
   discontinuity right at that last stop, visible as a Mach band over a
   large flat bright surface (a ceiling). Cosine has zero slope at both
   ends. Cornered radials use `farthest-side`, not the `farthest-corner`
   default — farthest-corner over-sizes the ellipse ~41% along the box's
   straight edges, leaving a visible rectangular edge at the box boundary
   before alpha reaches true 0. Both fixes applied from day one here (see
   CLAUDE.md's Ellis writeup for the two bugs this avoids). */
#tw-vignette-top {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: 195px;
  background: linear-gradient(to bottom,
    rgba(6, 9, 18, 0.45) 0%, rgba(6, 9, 18, 0.44) 15%, rgba(6, 9, 18, 0.36) 30%,
    rgba(6, 9, 18, 0.26) 45%, rgba(6, 9, 18, 0.16) 60%, rgba(6, 9, 18, 0.07) 75%,
    rgba(6, 9, 18, 0.01) 90%, rgba(6, 9, 18, 0) 100%
  );
  z-index: 98;
  pointer-events: none;
}

#tw-vignette-bottom {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  height: 270px;
  background: linear-gradient(to top,
    rgba(6, 9, 18, 0.40) 0%, rgba(6, 9, 18, 0.38) 15%, rgba(6, 9, 18, 0.32) 30%,
    rgba(6, 9, 18, 0.23) 45%, rgba(6, 9, 18, 0.14) 60%, rgba(6, 9, 18, 0.06) 75%,
    rgba(6, 9, 18, 0.01) 90%, rgba(6, 9, 18, 0) 100%
  );
  z-index: 98;
  pointer-events: none;
}

#tw-vignette-tl {
  position: fixed;
  top: 0; left: 0;
  width: 480px;
  height: 280px;
  background: radial-gradient(ellipse farthest-side at 0% 0%,
    rgba(6, 9, 18, 0.18) 0%, rgba(6, 9, 18, 0.17) 15%, rgba(6, 9, 18, 0.14) 30%,
    rgba(6, 9, 18, 0.10) 45%, rgba(6, 9, 18, 0.06) 60%, rgba(6, 9, 18, 0.03) 75%,
    rgba(6, 9, 18, 0.005) 90%, rgba(6, 9, 18, 0) 100%
  );
  z-index: 98;
  pointer-events: none;
}

#tw-vignette-toast {
  position: fixed;
  bottom: 0; left: 0;
  width: 850px;
  height: 680px;
  background: radial-gradient(ellipse farthest-side at 0% 100%,
    rgba(6, 9, 18, 0.95) 0%, rgba(6, 9, 18, 0.90) 15%, rgba(6, 9, 18, 0.75) 30%,
    rgba(6, 9, 18, 0.55) 45%, rgba(6, 9, 18, 0.33) 60%, rgba(6, 9, 18, 0.14) 75%,
    rgba(6, 9, 18, 0.02) 90%, rgba(6, 9, 18, 0) 100%
  );
  z-index: 98;
  pointer-events: none;
}

/* ── UI FLOAT VISIBILITY ─────────────────────────────────────────────────── */

.tw-ui-el {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.55s var(--tw-ease);
}

.tw-ui-el.tw-show {
  opacity: 1;
  pointer-events: all;
}

#tw-devon-logo-float { transition-delay: 0.04s; }
#tw-logo-float        { transition-delay: 0.08s; }
#tw-cta-btn           { transition-delay: 0.12s; }
#tw-menu-bar          { transition-delay: 0.22s; }

/* ── FLOATING LOGOS ──────────────────────────────────────────────────────── */

/* Devon Properties — top left (property manager mark) */
#tw-devon-logo-float {
  position: fixed;
  top: 30px;
  left: 36px;
  z-index: 100;
}

.tw-devon-logo-img {
  display: block;
  height: 52px;
  width: auto;
  filter: drop-shadow(0 2px 14px rgba(0,0,0,0.55));
}

/* Il Greco — horizontally centred at top. Icon + wordmark side by side,
   matching the feature sheet's own real lockup composition (icon left of
   wordmark) — these are two separately-extracted assets (no single
   pre-composed horizontal file exists), composed here via flex. */
#tw-logo-float {
  position: fixed;
  top: 30px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 100;
  display: flex;
  align-items: center;
  gap: 14px;
}

.tw-logo-icon-img {
  display: block;
  height: 46px;
  width: auto;
  filter: drop-shadow(0 2px 14px rgba(0,0,0,0.55));
}

.tw-logo-wordmark-img {
  display: block;
  height: 39px;
  width: auto;
  filter: drop-shadow(0 2px 14px rgba(0,0,0,0.55));
}

/* ── FLOATING CTA ─────────────────────────────────────────────────────────── */

#tw-cta-btn {
  position: fixed;
  top: 27px;
  right: 30px;
  z-index: 100;
  font-family: var(--tw-sans);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  text-decoration: none;
  /* Navy text on light-blue fill — same rationale as .tw-splash-enter. */
  color: var(--ig-navy-deep);
  background: var(--ig-blue);
  border-radius: 150px;
  padding: 0 33px;
  height: 66px;
  min-width: 66px;
  display: flex;
  align-items: center;
  white-space: nowrap;
  transition: opacity 0.55s var(--tw-ease), filter 0.2s;
  transition-delay: 0.12s, 0s;
}

#tw-cta-btn:hover  { filter: brightness(1.06); }
#tw-cta-btn:focus-visible { outline: 2px solid var(--ig-white); outline-offset: 3px; }

/* ── BOTTOM MENU BAR ─────────────────────────────────────────────────────── */

#tw-menu-bar {
  position: fixed;
  bottom: 42px;
  left: 50%;
  transform: translateX(-50%);
  /* Higher than #tw-map-card's z-index:100 — NOT a redundant belt-and-
     suspenders alongside .tw-dropdown's own z-index:200. A fixed-position
     descendant's z-index only competes within its NEAREST ancestor stacking
     context: #tw-menu-bar (position:fixed + z-index:100) already establishes
     one, so .tw-dropdown's z-index:200 only wins against OTHER children of
     #tw-menu-bar — it never escapes to compete against #tw-map-card (a
     separate top-level stacking context, also z-index:100, later in DOM
     order so it wins the tie and paints over the entire #tw-menu-bar
     subtree, dropdown included). Confirmed live on Ellis's deployed tour,
     2026-08-06: bumping the child alone did nothing; bumping this container
     past #tw-map-card's 100 fixed it immediately. */
  z-index: 150;
}

.tw-menu-pill {
  display: flex;
  align-items: center;
  background: rgba(17, 27, 49, 0.84);
  backdrop-filter: blur(24px) saturate(170%);
  -webkit-backdrop-filter: blur(24px) saturate(170%);
  border: 1px solid rgba(166, 209, 237, 0.18);
  border-radius: 150px;
  padding: 0 9px;
  height: 78px;
  gap: 0;
  box-shadow: 0 12px 54px rgba(0, 0, 0, 0.4), 0 1.5px 0 rgba(166, 209, 237, 0.06) inset;
}

/* ── MENU TRIGGER BUTTONS ─────────────────────────────────────────────────── */

.tw-menu-group { position: relative; }

.tw-menu-btn {
  display: flex;
  align-items: center;
  gap: 10.5px;
  font-family: var(--tw-sans);
  font-size: 16px;
  font-weight: 500;
  letter-spacing: 0.06em;
  color: rgba(245, 248, 252, 0.52);
  background: transparent;
  border: none;
  padding: 0 25.5px;
  height: 60px;
  border-radius: 150px;
  cursor: pointer;
  white-space: nowrap;
  touch-action: manipulation;
  transition: color 0.18s, background 0.18s;
}

.tw-menu-btn:hover {
  color: rgba(245, 248, 252, 0.88);
  background: rgba(255, 255, 255, 0.05);
}

.tw-menu-btn[aria-expanded="true"] {
  color: var(--ig-white);
  background: rgba(255, 255, 255, 0.07);
}

.tw-menu-btn.tw-active { color: var(--ig-blue); }

.tw-menu-btn:focus-visible {
  outline: 2px solid var(--ig-blue);
  outline-offset: -2px;
  border-radius: 150px;
}

.tw-menu-chevron {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  opacity: 0.4;
  transition: transform 0.22s var(--tw-ease), opacity 0.18s;
}

.tw-menu-btn:hover .tw-menu-chevron { opacity: 0.65; }
.tw-menu-btn.tw-active .tw-menu-chevron { opacity: 0.65; }
.tw-menu-btn[aria-expanded="true"] .tw-menu-chevron {
  transform: rotate(180deg);
  opacity: 0.9;
}

.tw-menu-sep {
  width: 1.5px;
  height: 27px;
  background: rgba(245, 248, 252, 0.1);
  flex-shrink: 0;
  margin: 0 3px;
}

/* ── DRONE / AERIAL BUTTON ───────────────────────────────────────────────── */

#tw-aerial {
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  width: 66px;
  height: 60px;
  border-radius: 150px;
  cursor: pointer;
  color: rgba(245, 248, 252, 0.52);
  touch-action: manipulation;
  transition: color 0.18s, background 0.18s;
  margin: 0 3px;
}

#tw-aerial:hover {
  color: rgba(245, 248, 252, 0.88);
  background: rgba(255, 255, 255, 0.05);
}

#tw-aerial.tw-active { color: var(--ig-blue); }
#tw-aerial svg { width: 24px; height: 24px; }
#tw-aerial:focus-visible {
  outline: 2px solid var(--ig-blue);
  outline-offset: -2px;
  border-radius: 150px;
}

/* ── DROPDOWN CARDS ──────────────────────────────────────────────────────── */

.tw-dropdown {
  position: absolute;
  bottom: calc(100% + 24px);
  left: 50%;
  transform: translateX(-50%) translateY(12px);
  min-width: 277.5px;
  background: rgba(14, 22, 40, 0.96);
  backdrop-filter: blur(28px) saturate(160%);
  -webkit-backdrop-filter: blur(28px) saturate(160%);
  border: 1px solid rgba(166, 209, 237, 0.2);
  border-radius: 24px;
  padding: 9px;
  box-shadow: 0 30px 84px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(166, 209, 237, 0.06);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s var(--tw-ease), transform 0.2s var(--tw-ease);
  max-height: 62vh;
  overflow-y: auto;
  scroll-behavior: smooth;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: rgba(166, 209, 237, 0.32) transparent;
}

#tw-suites-dd { min-width: 290px; }

/* Wider than the base 277.5px — rows pair a label with a "Coming Soon" tag,
   which clips at the narrower width. */
#tw-amenities-dd { min-width: 320px; }

.tw-dropdown.tw-open {
  opacity: 1;
  pointer-events: all;
  transform: translateX(-50%) translateY(0);
}

.tw-dropdown::-webkit-scrollbar { width: 10px; }
.tw-dropdown::-webkit-scrollbar-track { background: transparent; }
.tw-dropdown::-webkit-scrollbar-thumb {
  background: rgba(166, 209, 237, 0.3);
  border-radius: 99px;
  border: 3px solid transparent;
  background-clip: padding-box;
}
.tw-dropdown::-webkit-scrollbar-thumb:hover {
  background: rgba(166, 209, 237, 0.55);
  background-clip: padding-box;
}

.tw-dropdown-label {
  font-family: var(--tw-sans);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(245, 248, 252, 0.25);
  padding: 9px 21px 12px;
  display: block;
  border-bottom: 1px solid rgba(166, 209, 237, 0.1);
  margin-bottom: 6px;
}

.tw-dropdown-empty {
  display: block;
  font-family: var(--tw-sans);
  font-size: 13.5px;
  font-weight: 400;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: rgba(245, 248, 252, 0.28);
  padding: 14px 21px 18px;
  text-align: center;
}

/* Per-item "Coming Soon" row — every suite until the shoot lands, plus every
   practical building feature without an explorable pano. */
.tw-dropdown-item-soon {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  font-family: var(--tw-sans);
  font-size: 15px;
  font-weight: 400;
  letter-spacing: 0.02em;
  color: rgba(245, 248, 252, 0.32);
  padding: 11px 21px;
  border-radius: 15px;
  cursor: default;
  user-select: none;
}

.tw-dropdown-soon-tag {
  flex-shrink: 0;
  font-family: var(--tw-sans);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(166, 209, 237, 0.85);
  border: 1px solid rgba(166, 209, 237, 0.35);
  border-radius: 999px;
  padding: 3px 9px;
  white-space: nowrap;
}

.tw-dropdown-item {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 5px;
  width: 100%;
  font-family: var(--tw-sans);
  font-size: 17px;
  font-weight: 400;
  letter-spacing: 0.02em;
  color: rgba(245, 248, 252, 0.55);
  background: transparent;
  border: none;
  padding: 11px 21px 11px 39px;
  border-radius: 15px;
  cursor: pointer;
  text-align: left;
  touch-action: manipulation;
  transition: color 0.15s, background 0.15s;
  position: relative;
}

.tw-dd-unit-name {
  font-size: 17px;
  font-weight: 400;
  color: inherit;
  letter-spacing: 0.02em;
}

.tw-dd-meta {
  display: flex;
  align-items: center;
  gap: 13px;
  opacity: 0.6;
  transition: opacity 0.15s;
}

.tw-dropdown-item:hover     .tw-dd-meta { opacity: 0.85; }
.tw-dropdown-item.tw-active .tw-dd-meta { opacity: 0.75; }

/* The unit number, e.g. "Unit 309". Every other MetaTours property puts this
   in the row's title; Il Greco's titles are floor plan types, so it rides in
   the meta row as a filled chip — distinct enough from the icon+value pairs
   beside it to read as an identifier rather than another spec. */
.tw-dd-unit-tag {
  padding: 2px 7px;
  border-radius: 5px;
  background: rgba(166, 209, 237, 0.16);
  color: var(--ig-blue);
  font-weight: 600;
}

.tw-dd-meta-item {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: var(--tw-sans);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(245, 248, 252, 0.75);
  /* Without this, two-word meta ("2 Bed") breaks mid-item onto a second line
     the instant the row runs out of width — reads as a layout bug, not a
     wrap. Paired with flex-wrap on the row itself at the mobile breakpoint
     (see .tw-toast-meta below for the same fix on the toast). */
  white-space: nowrap;
}

.tw-dropdown-item::before {
  content: '';
  position: absolute;
  left: 15px;
  top: 50%;
  transform: translateY(-50%);
  width: 4.5px;
  height: 4.5px;
  border-radius: 50%;
  background: var(--ig-blue);
  opacity: 0;
  transition: opacity 0.15s;
}

.tw-dropdown-item:hover {
  color: var(--ig-white);
  background: rgba(255, 255, 255, 0.05);
}

.tw-dropdown-item.tw-active {
  color: var(--ig-white);
  font-weight: 500;
}

.tw-dropdown-item.tw-active::before { opacity: 1; }

.tw-dropdown-item:focus-visible {
  outline: 2px solid var(--ig-blue);
  outline-offset: -2px;
  border-radius: 15px;
}

/* ── ROOM NAME TOAST ─────────────────────────────────────────────────────── */

/* Bottom-left is the toast's alone again — #tw-hint-trigger moved to the
   bottom-right corner (Danny 2026-08-07), which is what let this drop back to
   its natural height instead of being pushed up to clear that button. */
#tw-toast {
  position: fixed;
  bottom: 52px;
  left: 48px;
  z-index: 99;
  pointer-events: none;
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.7s var(--tw-ease), transform 0.7s var(--tw-ease);
  max-width: 500px;
}

#tw-toast.tw-show {
  opacity: 1;
  transform: translateY(0);
}

.tw-toast-label {
  display: block;
  font-family: var(--tw-sans);
  font-size: clamp(22px, 1.6vw, 28px);
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ig-blue);
  /* Spacing below now belongs to .tw-toast-eyebrow, the flex row that wraps
     this label and the unit chip — a bottom margin on a flex ITEM would offset
     it against the chip beside it instead of spacing the group. */
  margin-bottom: 0;
  text-shadow: 0 1.5px 15px rgba(0,0,0,0.6);
}

.tw-toast-room {
  display: block;
  font-family: var(--tw-serif);
  font-size: clamp(54px, 4.2vw, 86px);
  font-weight: 300;
  color: var(--ig-white);
  line-height: 1.05;
  text-shadow: 0 3px 30px rgba(0,0,0,0.55);
  letter-spacing: 0.01em;
}

.tw-toast-meta {
  display: flex;
  align-items: center;
  gap: 24px;
  margin-top: 18px;
  font-family: var(--tw-sans);
  font-size: clamp(17px, 1.3vw, 22px);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(245, 248, 252, 0.78);
  text-shadow: 0 1.5px 12px rgba(0,0,0,0.6);
}

.tw-toast-meta-item {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  /* Same backstop as .tw-dd-meta-item above — without this, "2 Bed" breaks
     mid-item on a narrow screen. Paired with flex-wrap on the row itself at
     the mobile breakpoint below (nowrap alone just trades a mid-item break
     for a silent horizontal overflow — both halves are required together). */
  white-space: nowrap;
}

/* Eyebrow row: "NOW VIEWING" plus the unit number chip. The chip sits here
   rather than in the meta row below because a 4th meta chip pushed the toast
   wide enough to hit the centred nav pill at desktop widths (measured). */
.tw-toast-eyebrow {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}

.tw-toast-unit {
  padding: 3px 9px;
  border-radius: 6px;
  background: rgba(166, 209, 237, 0.16);
  color: var(--ig-blue);
  font-family: var(--tw-sans);
  font-size: 0.66em;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
}

.tw-toast-meta-icon {
  color: var(--ig-blue);
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
}

.tw-toast-meta-icon svg { width: 30px; height: 30px; }

/* ── ONBOARDING HINT ─────────────────────────────────────────────────────── */
/* Shown once per device after Explore Now (see maybeShowHintAutomatically()
   in the JS), teaching first-time visitors the pano is draggable. Both the
   overlay and card are pointer-events:none throughout — this is a pure
   visual layer that never intercepts a drag gesture aimed at the pano
   underneath (see showHint()'s dismiss listener for why). Only
   .tw-hint-link (the embedded-only "open in a new tab" line) re-enables
   pointer-events on itself, since it's the one genuinely clickable thing
   here.

   DELIBERATELY brand-neutral (Danny 2026-08-06: "I want this to feel like
   it works on any tour, no matter the colours, fonts, etc... like the
   animated hotspot designs we made") — every color/font here comes from
   the --hint-* tokens in :root, never from --ig-*. White frosted glass
   (0.58 alpha + heavy blur) rather than the dark navy glass the rest of
   the UI uses, specifically so this reads as universal tour CHROME (how
   the interface works) rather than this property's BRAND (which the rest
   of the floating UI already carries). Same reasoning the native 3DVista
   hotspot icons stay white/neutral regardless of client palette. */
#tw-hint-overlay {
  position: fixed;
  inset: 0;
  z-index: 250;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.45s var(--tw-ease);
}

#tw-hint-overlay.tw-show { opacity: 1; }

.tw-hint-card {
  pointer-events: none;
  position: relative; /* anchors .tw-hint-close */
  max-width: 320px;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 26px 24px 18px;
  border-radius: 22px;
  background: var(--hint-bg);
  backdrop-filter: blur(32px) saturate(180%);
  -webkit-backdrop-filter: blur(32px) saturate(180%);
  border: 1px solid var(--hint-border);
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.28), 0 1px 0 rgba(255, 255, 255, 0.6) inset;
  transform: scale(0.96) translateY(6px);
  transition: transform 0.45s var(--tw-ease);
}

#tw-hint-overlay.tw-show .tw-hint-card {
  transform: scale(1) translateY(0);
}

/* Explicit dismiss. `pointer-events: auto` is required — the overlay and card
   are both pointer-events:none so a drag aimed at the pano passes straight
   through, and each genuinely clickable child has to opt back in (same as
   .tw-hint-link). Deliberately quiet: it should read as a way out, not compete
   with the instruction the card is there to deliver. */
.tw-hint-close {
  pointer-events: auto;
  position: absolute;
  top: 10px;
  right: 10px;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--hint-ink);
  opacity: 0.4;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition: opacity 0.18s, background 0.18s;
}

.tw-hint-close:hover { opacity: 0.85; background: rgba(0, 0, 0, 0.06); }
.tw-hint-close:focus-visible { opacity: 0.85; outline: 2px solid var(--hint-ink); outline-offset: 2px; }

.tw-hint-icon-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  height: 34px;
  margin-bottom: 12px;
  color: var(--hint-ink);
}

.tw-hint-chevron {
  display: flex;
  opacity: 0.3;
}

.tw-hint-pointer {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  animation: tw-hint-drag 2.4s ease-in-out infinite;
}

/* Touch variant — HINT_HTML leaves this span genuinely empty (no cursor
   SVG) when IS_TOUCH, so a plain filled dot stands in for a fingertip. */
.tw-hint-pointer:empty {
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 0 6px rgba(22, 22, 26, 0.08);
}

@keyframes tw-hint-drag {
  0%   { transform: translateX(-16px); opacity: 0.5; }
  50%  { transform: translateX(16px);  opacity: 1; }
  100% { transform: translateX(-16px); opacity: 0.5; }
}

.tw-hint-title {
  font-family: var(--hint-sans);
  font-size: 16px;
  font-weight: 600;
  color: var(--hint-ink);
  letter-spacing: 0.002em;
}

.tw-hint-sub {
  font-family: var(--hint-sans);
  font-size: 12.5px;
  font-weight: 400;
  line-height: 1.4;
  color: var(--hint-ink-soft);
  margin-top: 8px;
  max-width: 26ch;
}

.tw-hint-sub b { font-weight: 600; color: var(--hint-ink); }

.tw-hint-footer {
  margin-top: 16px;
  padding-top: 13px;
  width: 100%;
  border-top: 1px solid rgba(22, 22, 26, 0.12);
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.tw-hint-disclaimer {
  font-family: var(--hint-sans);
  font-size: 10.5px;
  font-weight: 400;
  line-height: 1.4;
  color: var(--hint-ink-faint);
}

.tw-hint-link {
  pointer-events: auto;
  width: 100%;
  background: none;
  border: none;
  padding: 0;
  font-family: var(--hint-sans);
  font-size: 10.5px;
  font-weight: 400;
  color: var(--hint-ink-faint);
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.tw-hint-link span {
  color: var(--hint-ink);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.tw-hint-link:hover span,
.tw-hint-link:focus-visible span { color: var(--hint-ink); opacity: 0.7; }
.tw-hint-link:focus-visible { outline: 2px solid var(--hint-ink); outline-offset: 2px; border-radius: 4px; }

@media (max-width: 768px) {
  .tw-hint-card { padding: 22px 20px 16px; border-radius: 18px; }
  .tw-hint-title { font-size: 15px; }
  .tw-hint-sub { font-size: 12px; }
  .tw-hint-footer { margin-top: 14px; padding-top: 11px; }
  .tw-hint-disclaimer,
  .tw-hint-link { font-size: 10px; }
}

/* ── FLOATING MAP PILL ───────────────────────────────────────────────────── */
/* Bottom-right glass pill — a single button styled like the other floating
   pills, opening the fullscreen map modal directly. */

/* Back to sitting in the same row as the nav pill (Danny 2026-08-10): stacking
   it above #tw-hint-trigger read as "Location belongs to the help button",
   the opposite of the intent — Location IS one of the branded controls, help
   is the thing that should read as separate from it. `bottom: 42px` matches
   #tw-menu-bar's own bottom exactly, so the two sit on a shared baseline. */
#tw-map-card {
  position: fixed;
  bottom: 42px;
  right: 36px;
  z-index: 100;
  border-radius: 999px;
  overflow: hidden;
  border: 1px solid rgba(166, 209, 237, 0.18);
  box-shadow: 0 12px 60px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(166, 209, 237, 0.06) inset;
  background: rgba(17, 27, 49, 0.84);
  backdrop-filter: blur(24px) saturate(170%);
  -webkit-backdrop-filter: blur(24px) saturate(170%);
  transition-delay: 0.3s;
}

/* `width: 100%` is load-bearing, not cosmetic: #tw-map-card carries all the
   pill styling (background, border, radius) while this button is the only
   clickable thing inside it. If the card is ever given a width larger than
   this button's content width, the difference becomes a dead zone that still
   looks clickable. Stretching the button to the card guarantees the hit area
   and the visible pill are always the same rectangle. */
.tw-map-header {
  display: flex;
  width: 100%;
  align-items: center;
  gap: 12px;
  padding: 16.5px 24px;
  background: transparent;
  border: none;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.18s;
}

.tw-map-header:hover { background: rgba(255, 255, 255, 0.04); }
.tw-map-header:focus-visible { outline: 2px solid var(--ig-blue); outline-offset: -2px; }

/* ── RE-OPEN ONBOARDING HINT ─────────────────────────────────────────────── */
/* Bottom-RIGHT corner, with the Location pill sitting inboard of it (Danny
   2026-08-07). Two reasons it moved off bottom-left: it was crowding the
   "Now Viewing" toast into an unnaturally high position, and sharing that
   corner made it read as part of the property's branded UI. It isn't — it
   explains how the TOUR works, the same category as 3DVista's own neutral
   hotspot icons.
   Styled from the --hint-* tokens (white frosted glass), NOT --ig-*, so it
   matches the card it opens and stays portable to any other property
   unchanged. Standalone, never in the nav pill — that slot is the
   aerial/drone button's (Danny 2026-08-06). */
#tw-hint-trigger {
  position: fixed;
  /* Genuinely alone in the corner, not stacked with Location anymore (Danny
     2026-08-10: stacking it under Location made IT read as the branded thing
     — pulling it right against the edge, independent of every other floating
     control, is what makes it read as tour chrome instead). Small and close
     to the edge on purpose: the least important, most native-feeling control
     on screen sits where a viewer's OWN UI would put a minor affordance. */
  bottom: 14px;
  right: 16px;
  left: auto;
  z-index: 100;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--hint-bg);
  backdrop-filter: blur(32px) saturate(180%);
  -webkit-backdrop-filter: blur(32px) saturate(180%);
  border: 1px solid var(--hint-border);
  box-shadow: 0 10px 34px rgba(0, 0, 0, 0.3), 0 1px 0 rgba(255, 255, 255, 0.6) inset;
  color: var(--hint-ink);
  opacity: 0.82;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition: opacity 0.55s var(--tw-ease), background 0.18s, transform 0.15s var(--tw-ease);
  transition-delay: 0.3s, 0s, 0s;
}

#tw-hint-trigger svg { width: 13px; height: 13px; }

#tw-hint-trigger:hover { opacity: 1; transform: scale(1.06); }
#tw-hint-trigger:focus-visible { opacity: 1; outline: 2px solid var(--hint-ink); outline-offset: 2px; }

/* Hover label sits to the LEFT of the button, which now leaves it sitting
   neatly underneath the Location pill rather than colliding with it — the
   collision was only a problem back when the two shared a row. Vertically
   centred on the button. Pointer-events off so it can never swallow a click
   meant for the button. */
#tw-hint-trigger::after {
  content: 'How to use';
  position: absolute;
  right: calc(100% + 9px);
  top: 50%;
  transform: translateY(-50%) translateX(4px);
  padding: 7px 12px;
  border-radius: 999px;
  background: var(--hint-bg);
  backdrop-filter: blur(32px) saturate(180%);
  -webkit-backdrop-filter: blur(32px) saturate(180%);
  border: 1px solid var(--hint-border);
  box-shadow: 0 8px 26px rgba(0, 0, 0, 0.26);
  color: var(--hint-ink);
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s var(--tw-ease), transform 0.18s var(--tw-ease);
}

#tw-hint-trigger:hover::after,
#tw-hint-trigger:focus-visible::after {
  opacity: 1;
  transform: translateY(-50%) translateX(0);
}

/* Touch devices have no hover state, so the label would either never appear
   or stick after a tap. The icon alone carries it there. */
@media (hover: none) {
  #tw-hint-trigger::after { display: none; }
}

/* ── RESPONSIVE ──────────────────────────────────────────────────────────── */

@media (max-width: 1199px) and (min-width: 769px) {
  #tw-devon-logo-float { top: 22px; left: 26px; }
  .tw-devon-logo-img { height: 42px; }
  #tw-logo-float { top: 24px; gap: 11px; }
  .tw-logo-icon-img { height: 36px; }
  .tw-logo-wordmark-img { height: 30px; }
  #tw-cta-btn    { top: 22px; right: 22px; height: 56px; padding: 0 24px; font-size: 13.5px; }

  #tw-menu-bar   { bottom: calc(22px + env(safe-area-inset-bottom)); }
  .tw-menu-pill  { height: 64px; padding: 0 6px; }
  .tw-menu-btn   { padding: 0 18px; height: 50px; font-size: 14px; gap: 8px; }
  .tw-menu-sep   { height: 24px; margin: 0 2px; }
  #tw-aerial     { width: 56px; height: 50px; margin: 0 2px; }

  /* Clears the centred nav pill, which occupies 22..88px from the bottom on
     this breakpoint. Unlike desktop — where the toast stays narrow enough to
     sit beside the pill — the room name and its beds/baths/sq.ft. row get wide
     enough here to reach the pill's left edge, so they have to stack instead. */
  #tw-toast      { bottom: calc(104px + env(safe-area-inset-bottom)); left: 24px; max-width: min(42vw, 420px); }
  .tw-toast-label { font-size: clamp(16px, 2vw, 20px); letter-spacing: 0.16em; }
  .tw-toast-eyebrow { margin-bottom: 9px; gap: 9px; }
  .tw-toast-room  { font-size: clamp(36px, 5vw, 54px); }
  .tw-toast-meta  { gap: 16px; margin-top: 12px; font-size: clamp(13px, 1.4vw, 17px); }

  /* No fixed width. A hardcoded `width: 280px` here made the card render far
     wider than the button inside it (which is content-sized), so ~100px of the
     pill was visually part of the control but dead to clicks — and the live
     button was the size the pill should have been all along. Let it hug its
     content exactly like the desktop rule does. */
  /* Matches #tw-menu-bar's own bottom on this breakpoint — same reasoning as
     the desktop rule, same shared baseline. */
  #tw-map-card   { bottom: calc(22px + env(safe-area-inset-bottom)); right: 22px; }
  /* Beside Location rather than stacked below it — Location's own bottom
     offset here (22px) leaves too little room to fit anything beneath it and
     still clear its ~59px height (the desktop/mobile "stack below" approach
     needs the anchor sitting higher than that to have somewhere to stack
     into). Tucked into the narrow strip between Location's right edge and the
     true screen edge instead: still separate from it, still corner-anchored,
     just arranged left-right here rather than top-bottom. Vertically centred
     on Location (22 + 59/2 - 16/2 ≈ 44px). */
  #tw-hint-trigger { bottom: calc(44px + env(safe-area-inset-bottom)); right: 2px; left: auto; width: 16px; height: 16px; }
  #tw-hint-trigger svg { width: 10px; height: 10px; }
  /* Base rule already points the tooltip LEFT (toward Location/the canvas) —
     correct here too and left alone on purpose: the button sits only 2px
     from the true edge, so a right-pointing tooltip would run off-screen. */
}

/* Mobile — all phones (portrait & landscape) and small tablets ≤768px. */
@media (max-width: 768px) {
  #tw-devon-logo-float { display: none; }

  /* Il Greco lockup — icon alone on mobile (the full horizontal lockup is
     too wide next to the CTA at this width — same reasoning as Spencer
     Block's full/icon swap). */
  #tw-logo-float { top: 16px; left: 20px; transform: none; }
  .tw-logo-wordmark-img { display: none; }
  .tw-logo-icon-img { height: 48px; }

  #tw-cta-btn {
    top: 18px;
    right: 20px;
    height: 54px;
    min-width: 0;
    padding: 0 26px;
    font-size: 15px;
    letter-spacing: 0.12em;
  }

  #tw-menu-bar   { bottom: calc(18px + env(safe-area-inset-bottom)); width: calc(100vw - 40px); display: flex; justify-content: center; left: 20px; right: 20px; transform: none; }
  /* backdrop-filter (like transform/filter/perspective/will-change) makes an
     element the containing block for its position:fixed descendants — and
     .tw-dropdown switches to position:fixed at this breakpoint specifically
     to span the full viewport instead of just this pill. With the blur left
     on, the dropdown's left/right below would resolve against the PILL's
     narrower, centered box instead of the viewport. Solid fill instead of
     blur here fixes it; desktop/tablet dropdowns use position:absolute
     anchored via .tw-menu-group's own position:relative, which resolves
     first and never reaches this rule, so their glass look is untouched. */
  .tw-menu-pill  { height: 70px; padding: 0 6px; max-width: 100%; backdrop-filter: none; -webkit-backdrop-filter: none; background: rgba(9, 14, 26, 0.94); }
  .tw-menu-btn   { padding: 0 20px; height: 58px; font-size: 16px; gap: 8px; letter-spacing: 0.04em; }
  .tw-menu-sep   { height: 26px; margin: 0 2px; }
  #tw-aerial     { width: 58px; height: 58px; margin: 0 2px; }
  .tw-menu-chevron { width: 13px; height: 13px; }
  .tw-menu-pill::-webkit-scrollbar { display: none; }

  #tw-toast       { bottom: auto; top: calc(104px + env(safe-area-inset-top)); left: 20px; right: 20px; max-width: none; transform: translateY(-10px); }
  #tw-toast.tw-show { transform: translateY(0); }
  .tw-toast-label { font-size: 16px; letter-spacing: 0.16em; }
  .tw-toast-eyebrow { margin-bottom: 10px; gap: 8px; }
  .tw-toast-room  { font-size: clamp(38px, 10vw, 56px); line-height: 1.0; }
  /* At 375px the row has ~335px, but the widest suite label ("2 Bedroom +
     Den") needs more than that alongside its meta. nowrap alone (on
     .tw-toast-meta-item above) prevents a mid-item break but trades it for a
     silent horizontal overflow — wrapping the ROW instead lets an item that
     doesn't fit drop to a clean second line as a whole unit. */
  .tw-toast-meta  { flex-direction: row; flex-wrap: wrap; align-items: center; column-gap: 14px; row-gap: 6px; margin-top: 12px; font-size: 15px; letter-spacing: 0.08em; }
  .tw-toast-meta-item { gap: 7px; align-items: center; }
  .tw-toast-meta-icon svg { width: 24px !important; height: 24px !important; }

  /* Floats above the nav pill on this breakpoint out of necessity — the pill
     goes full-width here, so there's no shared row to align Location into
     the way the wider breakpoints do. Back to the original 100px gap now
     that #tw-hint-trigger (below) no longer stacks underneath it. */
  #tw-map-card {
    bottom: calc(100px + env(safe-area-inset-bottom));
    right: 20px;
    left: auto;
    width: 68px;
    height: 68px;
    border-radius: 50%;
  }
  .tw-map-header { width: 100%; height: 100%; padding: 0; gap: 0; border-radius: 50%; display: flex; align-items: center; justify-content: center; }
  .tw-map-header-text { display: none; }
  .tw-map-header-icon { display: flex; align-items: center; justify-content: center; }
  .tw-map-header-icon svg { width: 26px !important; height: 26px !important; stroke-width: 2.2 !important; }

  /* Genuinely in the true bottom-right corner (Danny 2026-08-10, repeated
     ask — the previous "stacked between the pill and Location" placement
     still read as inset, part of the branded cluster rather than the tour
     itself). The nav pill's rendered shape (checked against `.tw-menu-pill`
     itself, not `#tw-menu-bar`'s full-width wrapper) spans nearly edge to
     edge at this width, so there's no empty margin to tuck into — this
     deliberately sits low enough that their bounding boxes overlap, and
     relies on z-index (170, above #tw-menu-bar's 150) plus the pill's own
     rounded end-cap curving away from the true corner to keep it visually
     clear and on top rather than fighting for genuinely empty space that
     doesn't exist here. Verify this on a real phone, not just devtools —
     confirm it doesn't sit under the pill's rounded cap at whatever width
     actually ships. */
  #tw-hint-trigger {
    bottom: calc(10px + env(safe-area-inset-bottom));
    right: 10px;
    left: auto;
    width: 32px;
    height: 32px;
    z-index: 170;
  }
  #tw-hint-trigger svg { width: 15px; height: 15px; }

  .tw-splash-inner { padding: 36px 30px; }
  .tw-splash-icon-img { width: clamp(60px, 15vw, 84px); margin-bottom: 12px; }
  .tw-splash-wordmark-img { width: clamp(240px, 62vw, 360px); }
  .tw-splash-location { font-size: 16px; letter-spacing: 0.12em; margin-top: 12px; }
  .tw-splash-enter {
    margin-top: 32px;
    font-size: 17px;
    padding: 20px 40px;
    min-height: 64px;
    /* Tighter than the desktop 18px gap — reads as oddly separated between
       icon and text at mobile button scale. */
    gap: 10px;
  }
  .tw-splash-arrow { width: 22px; height: 22px; }
  .tw-splash-rule { margin: 16px auto; }
  /* Sized down and pushed up slightly so the "Leasing By" lockup clears the
     bottom safe area on real phones instead of crowding it. */
  .tw-splash-devon-wrap { bottom: 34px; gap: 9px; }
  .tw-splash-devon-img { width: clamp(85px, 24vw, 119px); }

  #tw-vignette-top {
    height: 240px;
    background: linear-gradient(to bottom,
      rgba(6, 9, 18, 0.82) 0%, rgba(6, 9, 18, 0.78) 15%, rgba(6, 9, 18, 0.65) 30%,
      rgba(6, 9, 18, 0.47) 45%, rgba(6, 9, 18, 0.28) 60%, rgba(6, 9, 18, 0.12) 75%,
      rgba(6, 9, 18, 0.02) 90%, rgba(6, 9, 18, 0) 100%
    );
  }
  #tw-vignette-bottom {
    height: 200px;
    background: linear-gradient(to top,
      rgba(6, 9, 18, 0.40) 0%, rgba(6, 9, 18, 0.38) 15%, rgba(6, 9, 18, 0.32) 30%,
      rgba(6, 9, 18, 0.23) 45%, rgba(6, 9, 18, 0.14) 60%, rgba(6, 9, 18, 0.06) 75%,
      rgba(6, 9, 18, 0.01) 90%, rgba(6, 9, 18, 0) 100%
    );
  }
  #tw-vignette-toast { display: none; }

  .tw-dropdown {
    position: fixed !important;
    left: 20px !important;
    right: 20px !important;
    bottom: calc(104px + env(safe-area-inset-bottom)) !important;
    top: auto !important;
    max-width: none !important;
    min-width: 0 !important;
    width: auto !important;
    z-index: 200 !important;
    transform: translateY(12px) !important;
    max-height: 46vh;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    border-radius: 20px;
  }
  .tw-dropdown.tw-open { transform: translateY(0) !important; }
  .tw-dropdown-item { padding: 16px 20px 16px 32px; font-size: 16px; }
  .tw-dropdown-item::before { left: 12px; }
  .tw-dropdown-item-soon { padding: 16px 20px; }
}

@media (max-height: 680px) {
  .tw-splash-icon-img { width: clamp(50px, 10vw, 70px); margin-bottom: 10px; }
  .tw-splash-wordmark-img { width: clamp(190px, 26vw, 260px); }
  .tw-splash-rule  { margin: 18px auto; }
  .tw-splash-enter { margin-top: 24px; font-size: 15px; min-height: 54px; padding: 16px 36px; }
  #tw-menu-bar     { bottom: calc(10px + env(safe-area-inset-bottom)); }
  .tw-menu-pill    { height: 58px; }
  .tw-menu-btn     { height: 46px; font-size: 14px; }
  #tw-vignette-top { height: 180px; }
}

/* Danny 2026-08-10: "the unit selector pill can block the text here for some
   units/screen sizes." Real gap, not just a longer-unit-name issue — the
   query above drops the nav pill to bottom:10px/height:58px (a 10..68px
   band), but nothing had ever adjusted #tw-toast for short viewports, so it
   was still sitting at the desktop base bottom:52px, landing squarely inside
   that band. Horizontal separation (toast left-anchored vs. pill centered)
   hides this on wide desktop windows, which is why it only showed up "for
   some screen sizes" — a short-but-still-desktop-width browser window (a
   smaller laptop, or Chrome just not maximized vertically) is exactly where
   width alone doesn't give enough of a horizontal gap to save it.
   Scoped to desktop width on purpose: the ≤1199px tablet breakpoint already
   bumps #tw-toast to bottom:104px with its own comment explaining exactly
   this clearance math, and the ≤768px mobile breakpoint moves the toast to
   the TOP of the screen entirely (bottom:auto) — folding this into the
   shared max-height query above would win the cascade on any viewport
   matching both max-width and max-height (any phone in landscape, for one)
   and silently reinstate a bottom value on a toast meant to stay top-anchored. */
@media (max-height: 680px) and (min-width: 1200px) {
  #tw-toast { bottom: 92px; }
}

/* ── HIDE NATIVE 3DVISTA LOAD BAR & PRELOADER ───────────────────────────── */
#viewer div[style*="height: 3px"][style*="z-index: 2"] { visibility: hidden !important; }
#preloadContainer { display: none !important; }

/* ── BRANDED LOAD INDICATOR ─────────────────────────────────────────────── */

#tw-loader {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: 2px;
  z-index: 200;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.25s var(--tw-ease);
}

#tw-loader.tw-loader-active { opacity: 1; }
#tw-loader.tw-loader-done   { opacity: 0; transition: opacity 0.3s var(--tw-ease) 0.15s; }

.tw-loader-fill {
  width: 100%;
  height: 100%;
  transform-origin: left center;
  transform: scaleX(0);
  background: linear-gradient(90deg, rgba(166,209,237,0), var(--ig-blue) 30%, var(--ig-white) 70%, rgba(245,248,252,0));
  box-shadow: 0 0 12px rgba(166, 209, 237, 0.5);
}

/* ── FULLSCREEN MAP MODAL ────────────────────────────────────────────────── */

#tw-map-modal {
  position: fixed;
  inset: 0;
  z-index: 400;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 1;
  transition: opacity 0.2s var(--tw-ease);
}

#tw-map-modal.tw-map-modal-hidden {
  opacity: 0;
  pointer-events: none;
}

.tw-map-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(9, 14, 26, 0.72);
  backdrop-filter: blur(10px) saturate(140%);
  -webkit-backdrop-filter: blur(10px) saturate(140%);
  cursor: pointer;
}

.tw-map-modal-card {
  position: relative;
  width: 92vw;
  height: 88vh;
  max-width: 2100px;
  background: rgba(14, 22, 40, 0.95);
  border: 1px solid rgba(166, 209, 237, 0.2);
  border-radius: 24px;
  box-shadow: 0 30px 120px rgba(0, 0, 0, 0.7), 0 0 0 1px rgba(166, 209, 237, 0.06) inset;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transform: scale(1);
  transition: transform 0.2s var(--tw-ease);
}

#tw-map-modal.tw-map-modal-hidden .tw-map-modal-card { transform: scale(0.96); }

.tw-map-modal-topbar {
  display: flex;
  align-items: center;
  gap: 24px;
  padding: 21px 27px;
  border-bottom: 1px solid rgba(166, 209, 237, 0.12);
  background: rgba(17, 27, 49, 0.4);
}

.tw-map-modal-title {
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: var(--tw-sans);
  font-size: 13.5px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(245, 248, 252, 0.55);
  flex-shrink: 0;
}

.tw-map-modal-title .tw-map-header-icon { color: var(--ig-blue); }
.tw-map-header-icon { color: var(--ig-blue); flex-shrink: 0; display: flex; align-items: center; }
.tw-map-header-text {
  font-family: var(--tw-sans);
  font-size: 16px;
  font-weight: 500;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: rgba(245, 248, 252, 0.72);
  text-align: left;
  white-space: nowrap;
}

.tw-map-filter {
  display: flex;
  gap: 3px;
  padding: 4.5px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(166, 209, 237, 0.1);
  border-radius: 15px;
  flex: 1;
  max-width: 630px;
  overflow-x: auto;
  /* Branded scroller. Left unstyled, this renders as the OS default bar — a
     thick light-grey slab spanning the pill, which is what Danny caught on
     mobile. Matches the .tw-dropdown scrollbar treatment: transparent track,
     translucent light-blue thumb. */
  scrollbar-width: thin;
  scrollbar-color: rgba(166, 209, 237, 0.34) transparent;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
}

.tw-map-filter::-webkit-scrollbar { height: 5px; }
.tw-map-filter::-webkit-scrollbar-track { background: transparent; }
.tw-map-filter::-webkit-scrollbar-thumb {
  background: rgba(166, 209, 237, 0.34);
  border-radius: 99px;
}
.tw-map-filter::-webkit-scrollbar-thumb:hover { background: rgba(166, 209, 237, 0.6); }

.tw-map-filter-btn {
  flex: 1;
  padding: 9px 21px;
  background: transparent;
  border: none;
  border-radius: 10.5px;
  font-family: var(--tw-sans);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(245, 248, 252, 0.5);
  cursor: pointer;
  touch-action: manipulation;
  transition: background 0.18s, color 0.18s;
  white-space: nowrap;
}

.tw-map-filter-btn:hover { color: rgba(245, 248, 252, 0.85); }
.tw-map-filter-btn.tw-active {
  background: rgba(166, 209, 237, 0.16);
  color: var(--ig-blue);
}

.tw-map-modal-close {
  width: 54px;
  height: 54px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid rgba(166, 209, 237, 0.30);
  border-radius: 15px;
  cursor: pointer;
  color: var(--ig-blue);
  transition: background 0.18s, color 0.18s, border-color 0.18s;
  flex-shrink: 0;
  margin-left: auto;
  -webkit-tap-highlight-color: transparent;
}

.tw-map-modal-close:hover {
  color: var(--ig-white);
  background: rgba(166, 209, 237, 0.12);
  border-color: rgba(166, 209, 237, 0.55);
}

.tw-map-modal-body { position: relative; flex: 1; min-height: 0; }

#tw-map-modal-canvas { position: absolute; inset: 0; background: #111B31; }

#tw-map-modal-canvas .mapboxgl-ctrl-logo { opacity: 0.35; }
#tw-map-modal-canvas .mapboxgl-ctrl-attrib { font-size: 13.5px; opacity: 0.35; }

#tw-map-modal-canvas .mapboxgl-ctrl-top-right > .mapboxgl-ctrl { margin: 8px 8px 0 0 !important; }
#tw-map-modal-canvas .mapboxgl-ctrl-group {
  background: rgba(17, 27, 49, 0.88) !important;
  border: 1px solid rgba(166, 209, 237, 0.28) !important;
  border-radius: 10px !important;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.45) !important;
  overflow: hidden;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
#tw-map-modal-canvas .mapboxgl-ctrl-group button {
  width: 34px !important;
  height: 34px !important;
  background: transparent !important;
  border: none !important;
  border-bottom: 1px solid rgba(166, 209, 237, 0.18) !important;
}
#tw-map-modal-canvas .mapboxgl-ctrl-group button:last-child { border-bottom: none !important; }
#tw-map-modal-canvas .mapboxgl-ctrl-group button:hover { background: rgba(166, 209, 237, 0.14) !important; }
#tw-map-modal-canvas .mapboxgl-ctrl-zoom-in .mapboxgl-ctrl-icon {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 18 18'%3E%3Cpath d='M9 3v12M3 9h12' stroke='%23F5F8FC' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E") !important;
}
#tw-map-modal-canvas .mapboxgl-ctrl-zoom-out .mapboxgl-ctrl-icon {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 18 18'%3E%3Cpath d='M3 9h12' stroke='%23F5F8FC' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E") !important;
}

.tw-map-layer-toggle {
  position: absolute;
  bottom: 27px;
  left: 27px;
  z-index: 5;
  display: flex;
  gap: 3px;
  padding: 4.5px;
  background: rgba(17, 27, 49, 0.88);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  border: 1px solid rgba(166, 209, 237, 0.18);
  border-radius: 15px;
  box-shadow: 0 9px 36px rgba(0, 0, 0, 0.55);
}

.tw-map-layer-btn {
  padding: 9px 18px;
  background: transparent;
  border: none;
  border-radius: 10.5px;
  font-family: var(--tw-sans);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(245, 248, 252, 0.55);
  cursor: pointer;
  touch-action: manipulation;
  transition: background 0.18s, color 0.18s;
}

.tw-map-layer-btn:hover     { color: rgba(245, 248, 252, 0.85); }
.tw-map-layer-btn.tw-active { background: rgba(166, 209, 237, 0.16); color: var(--ig-blue); }

/* ── POI MARKERS + POPUP ─────────────────────────────────────────────────── */

.tw-map-poi-chip {
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  background: rgba(17, 27, 49, 0.92);
  border: 1.5px solid rgba(166, 209, 237, 0.5);
  border-radius: 50%;
  color: var(--ig-white);
  cursor: pointer;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.45), 0 0 0 1.5px rgba(255, 255, 255, 0.10);
  transition: transform 0.15s var(--tw-ease), border-color 0.18s, color 0.18s, background 0.18s;
}

.tw-map-poi-chip:hover {
  transform: scale(1.18);
  border-color: var(--ig-blue);
  background: rgba(17, 27, 49, 0.98);
  color: var(--ig-blue);
}

.tw-map-pin-large {
  width: 22px !important;
  height: 22px !important;
  border-radius: 50%;
  background: var(--ig-blue);
  border: 3px solid white !important;
  box-shadow: 0 0 0 6px rgba(166, 209, 237, 0.5), 0 0 0 12px rgba(166, 209, 237, 0.18), 0 4px 18px rgba(0, 0, 0, 0.45);
  animation: tw-pin-pulse 2.2s ease-in-out infinite;
  cursor: default;
}

.tw-map-aerial-pin {
  position: relative;
  width: 48px;
  height: 48px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  background: var(--ig-blue);
  border: 1.5px solid rgba(17, 27, 49, 0.9);
  border-radius: 12px;
  color: var(--ig-navy-deep);
  cursor: pointer;
  box-shadow: 0 6px 21px rgba(0, 0, 0, 0.7), 0 0 0 4.5px rgba(166, 209, 237, 0.18);
  transition: transform 0.18s var(--tw-ease), box-shadow 0.18s;
}

.tw-map-aerial-pin:hover {
  transform: scale(1.12);
  box-shadow: 0 9px 27px rgba(0, 0, 0, 0.75), 0 0 0 7.5px rgba(166, 209, 237, 0.32);
}

.tw-map-aerial-num {
  position: absolute;
  top: -9px;
  right: -9px;
  min-width: 24px;
  height: 24px;
  padding: 0 6px;
  font: 700 15px/24px var(--tw-sans);
  color: var(--ig-blue);
  background: rgba(17, 27, 49, 0.96);
  border: 1px solid var(--ig-blue);
  border-radius: 15px;
  text-align: center;
  box-sizing: border-box;
}

@keyframes tw-pin-pulse {
  0%, 100% { box-shadow: 0 0 0 9px rgba(166, 209, 237, 0.28), 0 6px 24px rgba(0, 0, 0, 0.65); }
  50%      { box-shadow: 0 0 0 21px rgba(166, 209, 237, 0.05), 0 6px 24px rgba(0, 0, 0, 0.65); }
}

.tw-map-popup-wrap .mapboxgl-popup-content {
  background: rgba(14, 22, 40, 0.96);
  backdrop-filter: blur(12px) saturate(140%);
  -webkit-backdrop-filter: blur(12px) saturate(140%);
  border: 1px solid rgba(166, 209, 237, 0.25);
  border-radius: 15px;
  padding: 15px 21px;
  box-shadow: 0 15px 60px rgba(0, 0, 0, 0.6);
  color: var(--ig-white);
}

.tw-map-popup-wrap .mapboxgl-popup-tip { display: none; }

.tw-map-poi-popup .tw-map-poi-cat {
  font-family: var(--tw-sans);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ig-blue);
}

.tw-map-poi-popup .tw-map-poi-name {
  font-family: var(--tw-serif);
  font-size: 24px;
  font-weight: 400;
  color: var(--ig-white);
  margin-top: 3px;
  line-height: 1.25;
  max-width: 330px;
}

.tw-map-poi-popup .tw-map-poi-dist {
  font-family: var(--tw-sans);
  font-size: 15px;
  color: rgba(245, 248, 252, 0.55);
  margin-top: 6px;
}

body.tw-modal-open { overflow: hidden; }

/* ── RESPONSIVE — MODAL ──────────────────────────────────────────────────── */

@media (max-width: 768px) {
  .tw-map-modal-card { width: 100vw; height: 100dvh; max-width: none; border-radius: 0; }
  .tw-map-modal-topbar { flex-wrap: wrap; gap: 12px; padding: calc(12px + env(safe-area-inset-top)) 16px 12px; }
  .tw-map-modal-title { order: 1; flex: 1; font-size: 12px; gap: 8px; min-width: 0; }
  .tw-map-modal-title span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .tw-map-modal-close { order: 2; width: 44px; height: 44px; }
  /* The five filter labels don't fit at phone width, so this row scrolls. Two
     things make that read as intentional rather than broken: the buttons stop
     stretching (`flex: 0 0 auto`) so each keeps its natural width instead of
     being squeezed, and the trailing edge fades out — a half-cut chip under a
     fade says "there's more" far better than a scrollbar does. Extra
     padding-bottom leaves room for the slim scroller without it sitting on
     top of the buttons. */
  .tw-map-filter {
    order: 3;
    flex-basis: 100%;
    max-width: none;
    padding-bottom: 7px;
    -webkit-mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 22px), transparent 100%);
    mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 22px), transparent 100%);
  }
  .tw-map-filter-btn { flex: 0 0 auto; padding: 9px 14px; font-size: 12.5px; }
  .tw-map-layer-toggle { bottom: calc(18px + env(safe-area-inset-bottom)); left: 18px; padding: 4px; }
  .tw-map-layer-btn { padding: 8px 14px; font-size: 12.5px; }
  .tw-map-popup-wrap .mapboxgl-popup-content { max-width: calc(100vw - 60px); }
  .tw-map-poi-popup .tw-map-poi-name { font-size: 19px; max-width: 240px; }
}

/* ── REDUCED MOTION ──────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  .tw-splash-icon-img,
  .tw-splash-wordmark-img,
  .tw-splash-rule,
  .tw-splash-location,
  .tw-splash-enter {
    animation: none;
    opacity: 1;
    transform: none;
  }
  .tw-ui-el,
  #tw-toast,
  .tw-dropdown,
  .tw-splash-enter,
  .tw-menu-chevron,
  #tw-loader,
  .tw-loader-fill,
  #tw-map-modal,
  .tw-map-modal-card,
  .tw-map-poi-chip,
  .tw-map-pin-large,
  .tw-map-aerial-pin,
  #tw-hint-overlay,
  .tw-hint-card,
  .tw-hint-pointer { transition: none; animation: none; }
  .tw-loader-fill { transform: scaleX(1); }
}
