/* ==========================================================================
   DHULEVA ONE50 — Base Stylesheet
   1. Reset / Normalize
   2. Root variables (breakpoints, spacing)
   3. Responsive container (320px -> TV / 4K)
   ========================================================================== */

/* ---------- 1. Reset / Normalize ---------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* base font scales gently from small phones up to large TV displays */
  font-size: clamp(14px, 0.75vw + 11px, 20px);
}

body,
h1, h2, h3, h4, h5, h6,
p, figure, blockquote, dl, dd {
  margin: 0;
}

body {
  min-height: 100svh;
  line-height: 1.5;
  font-family: var(--font-body);
  color: var(--color-text);
  background-color: var(--color-bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading);
  line-height: 1.15;
  overflow-wrap: break-word;
}

img, picture, svg, video, canvas {
  display: block;
  max-width: 100%;
  height: auto;
}

video {
  width: 100%;
}

ul, ol {
  list-style: none;
  margin: 0;
  padding: 0;
}

a {
  color: inherit;
  text-decoration: none;
}

button, input, textarea, select {
  font: inherit;
  color: inherit;
}

button {
  cursor: pointer;
  background: none;
  border: none;
}

table {
  border-collapse: collapse;
  border-spacing: 0;
}

/* Respect users who prefer less motion */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* ---------- 2. Root variables ---------- */
:root {
  /* breakpoints (reference only — used via media queries below) */
  --bp-xs: 320px;   /* small phones */
  --bp-sm: 480px;   /* large phones */
  --bp-md: 768px;   /* tablets */
  --bp-lg: 1024px;  /* small laptops */
  --bp-xl: 1280px;  /* desktops */
  --bp-xxl: 1440px; /* large desktops */
  --bp-uhd: 1920px; /* full HD monitors */
  --bp-tv: 2560px;  /* 2K/4K TVs and ultrawide */

  --container-padding: 1rem;
  --container-max: 100%;

  /* Fonts — change once here, every element updates (see fonts.css) */
  --font-heading: "Black Mango", "General Sans", Arial, sans-serif;
  --font-body: "Futura Lt BT", Arial, Helvetica, sans-serif;

  /* Brand colors (from Brand Playbook) — reuse these, never hardcode hex */
  --color-maroon: #390007;      /* Imperial Signet */
  --color-argent: #d6d7db;      /* Liquid Argent */
  --color-steel: #a8acb3;       /* Molten Steel */
  --color-obsidian: #5b616c;    /* Obsidian Chrome */
  --color-stone: #e7e3da;       /* Ground Bombay Limestone */
  --color-mist: #c9c6c0;        /* Harbour Mist */
  --color-midnight: #0e1624;    /* Midnight Facade */

  --color-text: #1a1a1a;
  --color-bg: #ffffff;
}

/* ---------- 3. Responsive container ---------- */
.container {
  width: 100%;
  margin-inline: auto;
  padding-inline: var(--container-padding);
  max-width: var(--container-max);
}

/* Large phones */
@media (min-width: 480px) {
  :root { --container-padding: 1.25rem; }
}

/* Tablets */
@media (min-width: 768px) {
  :root {
    --container-padding: 2rem;
    --container-max: 720px;
  }
}

/* Small laptops */
@media (min-width: 1024px) {
  :root { --container-max: 960px; }
}

/* Desktops */
@media (min-width: 1280px) {
  :root {
    --container-padding: 2.5rem;
    --container-max: 1200px;
  }
}

/* Large desktops */
@media (min-width: 1440px) {
  :root { --container-max: 1320px; }
}

/* Full HD monitors */
@media (min-width: 1920px) {
  :root { --container-max: 1600px; }
}

/* 2K / 4K TVs & ultrawide */
@media (min-width: 2560px) {
  :root {
    --container-padding: 3rem;
    --container-max: 2000px;
  }
}

/* Full-bleed sections (hero videos etc.) ignore the container max-width */
.full-bleed {
  width: 100%;
  max-width: none;
  padding-inline: 0;
}

/* ---------- 4. Shared text utilities — reused by hero, every video
   section and the footer, so none of this is ever redeclared ---------- */
.eyebrow {
  display: block;
  font-size: clamp(0.7rem, 0.6vw + 0.5rem, 0.9rem);
  letter-spacing: 0.35em;
  text-transform: uppercase;
  color: var(--color-mist);
  margin-bottom: 1rem;
}

.title-mask {
  overflow: hidden;
}

.reveal-title {
  display: block;
  font-family: var(--font-heading);
  font-weight: 400;
  color: var(--color-stone);
  transform: translateY(110%);
}

.lede {
  margin-top: 1.25rem;
  font-size: clamp(1rem, 0.5vw + 0.85rem, 1.25rem);
  color: var(--color-mist);
  max-width: 38ch;
}

/* Two title scales, shared everywhere instead of each component
   declaring its own font-size */
.title-lg {
  font-size: clamp(2.75rem, 6vw + 1.5rem, 8.5rem);
  line-height: 0.95;
  letter-spacing: -0.01em;
}

.title-md {
  font-size: clamp(1.75rem, 2.5vw + 1.2rem, 3.5rem);
}

/* Corner frame accent — the "architectural frame" motif from the brand
   playbook, drawn in on scroll (see main.js) instead of just a flat tint */
.corner-frame {
  position: absolute;
  z-index: 1;
  width: clamp(36px, 4vw, 58px);
  height: clamp(36px, 4vw, 58px);
  fill: none;
  stroke: var(--color-stone);
  stroke-width: 1;
  opacity: 0.7;
  pointer-events: none;
}

.corner-frame--tl {
  top: clamp(1.25rem, 3vw, 2.25rem);
  left: clamp(1.25rem, 3vw, 2.25rem);
}

.corner-frame--br {
  bottom: clamp(1.25rem, 3vw, 2.25rem);
  right: clamp(1.25rem, 3vw, 2.25rem);
}

/* Fixed scroll HUD — a vertical fill line that tracks progress through
   the entire page, plus the section index (echoing ONE50's numeric
   identity). One fixed cluster, never duplicated per-section. */
.scroll-hud {
  position: fixed;
  left: clamp(1.5rem, 4vw, 2.5rem);
  bottom: clamp(1.5rem, 4vw, 2.5rem);
  z-index: 15;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  color: var(--color-stone);
  opacity: 0;
}

.scroll-hud__label {
  font-size: 0.6rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  writing-mode: vertical-rl;
  color: var(--color-mist);
}

.scroll-hud__track {
  position: relative;
  width: 1px;
  height: clamp(40px, 8vw, 70px);
  background-color: rgba(231, 227, 218, 0.2);
  overflow: hidden;
}

.scroll-hud__fill {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: var(--color-stone);
  transform: scaleY(0);
  transform-origin: top;
}

.scroll-hud__counter {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.7rem;
  letter-spacing: 0.2em;
}

.section-counter__divider {
  width: 16px;
  height: 1px;
  background-color: rgba(231, 227, 218, 0.4);
}

/* Keeps a section's title from landing under the fixed header when jumped
   to directly (menu links, browser back/forward with a hash, etc.) */
main > section[id],
.site-footer[id] {
  scroll-margin-top: clamp(64px, 9vw, 96px);
}

/* ---------- 5. Brand header ---------- */
.site-header {
  position: fixed;
  inset-inline: 0;
  top: 0;
  z-index: 30;
  padding-block: 1rem;
  background: linear-gradient(180deg, rgba(14, 22, 36, 0.55), transparent);
  transition: background-color 0.4s ease, padding-block 0.4s ease;
}

.site-header.is-scrolled {
  background-color: var(--color-maroon);
  padding-block: 0.5rem;
}

.site-header.is-scrolled .logo {
  width: clamp(100px, 12vw, 170px);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.logo {
  display: block;
  width: clamp(140px, 18vw, 260px);
  height: auto;
  transition: width 0.4s ease;
}

/* shared "wait for the intro before showing" state — one rule, reused */
.is-hidden-until-ready {
  opacity: 0;
}

/* Hamburger — three lines that morph into an X, pulls toward the cursor */
.menu-toggle {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: clamp(26px, 2.4vw, 34px);
  padding: 0;
}

.menu-toggle__line {
  display: block;
  height: 1.5px;
  width: 100%;
  background-color: var(--color-stone);
  transition: transform 0.35s ease, opacity 0.35s ease;
}

.menu-toggle.is-open .menu-toggle__line:nth-child(1) {
  transform: translateY(7.5px) rotate(45deg);
}

.menu-toggle.is-open .menu-toggle__line:nth-child(2) {
  opacity: 0;
}

.menu-toggle.is-open .menu-toggle__line:nth-child(3) {
  transform: translateY(-7.5px) rotate(-45deg);
}

/* ---------- 6. Preloader — panels part like doors as the logo departs ---------- */
.preloader {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.preloader__panel {
  position: absolute;
  inset-inline: 0;
  height: 50%;
  background-color: var(--color-maroon);
}

.preloader__panel--top {
  top: 0;
}

.preloader__panel--bottom {
  bottom: 0;
}

.preloader__logo {
  position: relative;
  z-index: 1;
  width: clamp(160px, 30vw, 340px);
  height: auto;
  opacity: 0;
  transform: scale(0.92);
  transform-origin: center;
}

.is-loading,
.is-loading body {
  overflow: hidden;
  height: 100%;
}

/* ---------- 7. Menu overlay — a slim glass panel from the right, not a
   full-screen takeover. The backdrop only dims (barely blurs) so whatever
   section video is playing stays visible behind it; the panel itself is a
   tinted, translucent sheet of glass rather than a solid wall, so motion
   from the video still reads through it. Width is capped everywhere, so
   most of the screen — and the video — stays uncovered at any size. */
.menu-overlay {
  position: fixed;
  inset: 0;
  z-index: 25;
  pointer-events: none;
}

.menu-overlay.is-open {
  pointer-events: auto;
}

.menu-overlay__backdrop {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background-color: rgba(14, 22, 36, 0.22);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  opacity: 0;
  cursor: pointer;
  /* driven by the .is-open class below — a plain CSS transition, so the
     drawer always shows/hides correctly even if the JS animation layer
     (GSAP) fails to load for any reason */
  transition: opacity 0.4s ease;
}

.menu-overlay__panel {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  /* starts from the top (not vertically centered) — with 9 links the list
     is taller than most viewports, and centering it made the list scroll
     to a mid-point by default, burying item 01 and colliding with the
     close button. Starting at the top plus enough clearance below the
     close button fixes both. */
  justify-content: flex-start;
  gap: clamp(1.5rem, 5vh, 2.5rem);
  /* narrow on purpose — leaves the video visible at every breakpoint;
     scales gently on small phones, then holds steady above ~490px.
     Width itself is unchanged — only the text sizing below was the bug. */
  width: clamp(272px, 84vw, 400px);
  padding-top: clamp(4.5rem, 13vh, 6rem);
  padding-bottom: clamp(2rem, 6vh, 3rem);
  overflow-y: auto;
  background: linear-gradient(165deg, rgba(57, 0, 7, 0.5), rgba(14, 22, 36, 0.58));
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  border-left: 1px solid rgba(214, 215, 219, 0.16);
  box-shadow: -24px 0 60px rgba(0, 0, 0, 0.3);
  transform: translateX(100%);
  /* same reasoning as the backdrop above — plain CSS drives the slide */
  transition: transform 0.55s cubic-bezier(0.16, 1, 0.3, 1);
}

/* Close button — lives inside the panel itself so it's always visible
   and unambiguous, independent of the header's hamburger/X state */
.menu-overlay__close {
  position: absolute;
  top: clamp(1.25rem, 3.5vh, 1.75rem);
  right: clamp(1.25rem, 5vw, 2rem);
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 0.55em;
  color: var(--color-stone);
  opacity: 0.8;
  transition: opacity 0.25s ease;
}

.menu-overlay__close:hover,
.menu-overlay__close:focus-visible {
  opacity: 1;
}

.menu-overlay__close-label {
  font-family: var(--font-body);
  font-size: 0.7rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}

.menu-overlay__close-icon {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
}

/* the guaranteed baseline: toggling this one class shows/hides the whole
   drawer correctly on its own. GSAP (in main.js) only ever layers the
   extra staggered link entrance on top of this — it never owns the
   open/close state itself, so there's no scenario where the toggle works
   but the panel stays invisible. */
.menu-overlay.is-open .menu-overlay__backdrop {
  opacity: 1;
}

.menu-overlay.is-open .menu-overlay__panel {
  transform: translateX(0);
}

.menu-overlay__nav {
  display: flex;
  flex-direction: column;
  gap: clamp(0.3rem, 1vh, 0.6rem);
  padding-inline: clamp(1.25rem, 5vw, 2rem);
}

.menu-overlay__nav a {
  position: relative;
  display: flex;
  align-items: baseline;
  gap: 0.55em;
  padding-block: 0.2em;
  font-family: var(--font-heading);
  /* fixed-ish on purpose, no vw term: the panel's own width plateaus at
     400px well before the viewport does, so sizing this off vw (like the
     panel width does) made the text keep growing on wide screens long
     after the panel had stopped — that's what forced every label onto
     two lines. The page root font-size (14–20px, see the html rule up
     top) already gives this just enough responsiveness on its own. */
  font-size: 1.05rem;
  line-height: 1.15;
  color: var(--color-stone);
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.45);
}

.menu-overlay__label {
  white-space: nowrap;
}

.menu-overlay__index {
  font-family: var(--font-body);
  font-size: 0.5em;
  letter-spacing: 0.18em;
  color: var(--color-mist);
  opacity: 0.65;
  flex-shrink: 0;
}

.menu-overlay__nav a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  height: 1px;
  width: 0;
  background-color: var(--color-stone);
  transition: width 0.35s ease;
}

.menu-overlay__nav a:hover,
.menu-overlay__nav a:focus-visible {
  color: var(--color-mist);
}

.menu-overlay__nav a:hover::after,
.menu-overlay__nav a:focus-visible::after {
  width: 100%;
}

.menu-overlay__foot {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding-inline: clamp(1.25rem, 5vw, 2rem);
}

.menu-overlay__tagline {
  font-family: var(--font-heading);
  font-size: 0.85rem;
  letter-spacing: 0.08em;
  color: var(--color-mist);
  opacity: 0.75;
}

/* keeps the drawer usable when the viewport is short (landscape phones,
   small laptops with the browser chrome eating vertical space) */
@media (max-height: 480px) {
  .menu-overlay__panel {
    padding-top: 3.5rem;
    padding-bottom: 1rem;
    gap: 0.75rem;
  }
  .menu-overlay__foot {
    display: none;
  }
}

/* background scroll is locked while the drawer is open (see main.js) */
.menu-is-locked {
  overflow: hidden;
}

/* ---------- 8. Hero ---------- */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  color: var(--color-stone);
  background-color: var(--color-midnight);
}

.hero__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  will-change: transform;
}

.hero__overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(14, 22, 36, 0.25) 0%, rgba(14, 22, 36, 0.35) 55%, rgba(14, 22, 36, 0.8) 100%);
  pointer-events: none;
}

.hero__content {
  position: relative;
  z-index: 1;
  text-align: center;
}

.hero__line {
  font-size: clamp(1.5rem, 2.2vw + 1rem, 3.25rem);
  letter-spacing: 0.04em;
}

/* ---------- 9. Scroll cue — a slow-turning ring, not the cliché line ---------- */
.scroll-cue {
  position: absolute;
  left: 50%;
  bottom: clamp(1.5rem, 4vw, 2.75rem);
  transform: translateX(-50%);
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  opacity: 0;
}

.scroll-cue__ring {
  position: absolute;
  inset: 0;
  fill: none;
  stroke: rgba(201, 198, 192, 0.4);
  stroke-width: 1;
  stroke-dasharray: 4 10;
  animation: scroll-ring-spin 6s linear infinite;
}

.scroll-cue__arrow {
  width: 8px;
  height: 8px;
  border-right: 1px solid var(--color-stone);
  border-bottom: 1px solid var(--color-stone);
  transform: rotate(45deg);
  animation: scroll-arrow-bob 1.6s ease-in-out infinite;
}

@keyframes scroll-ring-spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

@keyframes scroll-arrow-bob {
  0%, 100% { transform: rotate(45deg) translate(0, 0); opacity: 0.6; }
  50% { transform: rotate(45deg) translate(4px, 4px); opacity: 1; }
}

/* ---------- 11. Video sections — one component, reused for every video
   (Rare by Design / Amenities / The Life / The Brand). A data-reveal
   attribute + modifier class controls which side the content sits on and
   which direction it enters from — see main.js. ---------- */
.section-media {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: center;
  overflow: hidden;
  color: var(--color-stone);
  background-color: var(--color-midnight);
}

.section-media__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  will-change: transform;
  transform: scale(1.15);
}

.section-media__overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgba(14, 22, 36, 0.88) 0%, rgba(14, 22, 36, 0.55) 42%, rgba(14, 22, 36, 0.15) 100%);
  pointer-events: none;
}

/* a soft brand-maroon wash on every video — the "creative overlay",
   instead of a flat neutral tint */
.section-media__overlay::after {
  content: "";
  position: absolute;
  inset: 0;
  background-color: var(--color-maroon);
  mix-blend-mode: multiply;
  opacity: 0.16;
}

.section-media__content {
  position: relative;
  z-index: 1;
  max-width: 42rem;
  padding-block: clamp(2rem, 6vw, 5rem);
}

/* Direction modifiers */
.section-media--right {
  justify-content: flex-end;
}

.section-media--right .section-media__overlay {
  background: linear-gradient(270deg, rgba(14, 22, 36, 0.88) 0%, rgba(14, 22, 36, 0.5) 42%, rgba(14, 22, 36, 0.12) 100%);
}

.section-media--top {
  align-items: flex-start;
}

.section-media--top .section-media__content {
  padding-top: clamp(7rem, 16vw, 11rem);
}

.section-media--top .section-media__overlay {
  background: linear-gradient(180deg, rgba(14, 22, 36, 0.85) 0%, rgba(14, 22, 36, 0.4) 45%, rgba(14, 22, 36, 0.15) 100%);
}

.section-media--center {
  justify-content: center;
  text-align: center;
}

.section-media--center .section-media__content {
  max-width: 46rem;
}

.section-media--center .section-media__overlay {
  background: radial-gradient(circle at 50% 45%, rgba(14, 22, 36, 0.25) 0%, rgba(14, 22, 36, 0.8) 72%);
}

/* ---------- 12. Address — pinned circular reveal. Starts as a small
   circle of video against brand stone; scroll scrubs it open to full
   screen, then the title/lede fade in on top. ---------- */
.reveal-circle {
  position: relative;
  height: 100svh;
  overflow: hidden;
  background-color: var(--color-stone);
  display: flex;
  align-items: center;
  justify-content: center;
}

.reveal-circle__mask {
  position: absolute;
  inset: 0;
  clip-path: circle(8% at 50% 50%);
  will-change: clip-path;
}

.reveal-circle__video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.08);
}

.reveal-circle__overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(14, 22, 36, 0.05) 0%, rgba(14, 22, 36, 0.5) 100%);
}

/* curved wordmark + flanking location tags, visible only while the
   circle is still small — fades out as the video takes over */
.reveal-circle__arc {
  position: absolute;
  top: 9%;
  left: 50%;
  transform: translateX(-50%);
  width: min(70vw, 620px);
  z-index: 3;
  pointer-events: none;
}

.reveal-circle__arc-text {
  font-family: var(--font-heading);
  /* fluid, and locked to the arc's own path length via textLength on the
     <text> element in index.html — together these keep the wordmark from
     ever overrunning the curve, on any screen size */
  font-size: clamp(0.8rem, 1.3vw + 0.35rem, 1.15rem);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  fill: var(--color-maroon);
}

.reveal-circle__tag {
  position: absolute;
  top: 14%;
  z-index: 3;
  font-size: 0.7rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--color-maroon);
}

.reveal-circle__tag--left {
  left: clamp(1rem, 5vw, 3rem);
}

.reveal-circle__tag--right {
  right: clamp(1rem, 5vw, 3rem);
}

.reveal-circle__content {
  position: relative;
  z-index: 2;
  max-width: 42rem;
  text-align: center;
  opacity: 0;
}

/* ---------- 13. Location — pinned horizontal scroll. Vertical scroll
   drives a horizontal track across three panels (Heritage / Seaface map /
   Connected convenience) before releasing to the next section. ---------- */
.location-scroll {
  position: relative;
  height: 100svh;
  overflow: hidden;
  background-color: var(--color-stone);
  color: var(--color-midnight);
}

.location-scroll__track {
  position: absolute;
  inset: 0;
  display: flex;
  height: 100%;
  width: 300%;
  will-change: transform;
}

.location-scroll__panel {
  position: relative;
  width: 100vw;
  height: 100%;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  padding-inline: clamp(1.5rem, 6vw, 4rem);
}

.location-scroll__ambient,
.location-scroll__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.location-scroll__ambient {
  opacity: 0.16;
  filter: blur(6px) saturate(0.8);
  transform: scale(1.1);
}

.location-scroll__video {
  opacity: 0.85;
}

.location-scroll__tint {
  position: absolute;
  inset: 0;
  background-color: var(--color-midnight);
  opacity: 0.6;
}

.location-scroll__panel:not(.location-scroll__panel--map) {
  color: var(--color-stone);
}

.location-scroll__panel:not(.location-scroll__panel--map) .eyebrow,
.location-scroll__panel:not(.location-scroll__panel--map) .lede {
  color: var(--color-mist);
}

.location-scroll__text {
  position: relative;
  z-index: 1;
  max-width: 42rem;
  text-align: center;
}

.location-scroll__panel--map .location-scroll__text {
  margin-bottom: clamp(1rem, 3vw, 1.75rem);
}

/* The map panel sits on the light stone background — the shared
   eyebrow/reveal-title/lede rules are tuned for the dark video panels,
   so this one panel needs its own dark-appropriate colors or the text
   is nearly invisible (light-on-light). */
.location-scroll__panel--map .eyebrow {
  color: var(--color-obsidian);
}

.location-scroll__panel--map .reveal-title {
  color: var(--color-midnight);
}

.location-scroll__panel--map .lede {
  color: var(--color-obsidian);
}

.location-scroll__graphic {
  position: relative;
  z-index: 1;
  width: min(94%, 1280px);
}

.location-scroll__svg {
  width: 100%;
  height: auto;
  max-height: min(58vh, 480px);
  overflow: visible;
}

.location-scroll__route {
  fill: none;
  stroke: var(--color-maroon);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-dasharray: 2 10;
}

/* A small marker that travels the length of the route in sync with the
   scrub itself (see main.js), so the map reads as a journey rather than
   a static drawn line */
.location-scroll__traveler {
  fill: var(--color-maroon);
  opacity: 0;
}

.location-scroll__traveler-ring {
  fill: none;
  stroke: var(--color-maroon);
  stroke-width: 1.5;
  opacity: 0;
  animation: traveler-pulse 1.8s ease-out infinite;
}

@keyframes traveler-pulse {
  0% { r: 5; opacity: 0.55; }
  100% { r: 15; opacity: 0; }
}

/* Stops — a dot on the route with a short stem rising to a two-line
   label (name + category), so every label reads as tied to its point
   rather than floating unattached above the line */
.location-scroll__stop-stem {
  stroke: var(--color-maroon);
  stroke-width: 1.5;
  opacity: 0.55;
}

.location-scroll__dot {
  fill: var(--color-maroon);
  stroke: var(--color-stone);
  stroke-width: 2;
}

.location-scroll__stop-name {
  font-family: var(--font-heading);
  font-size: 19px;
  font-weight: 600;
  fill: var(--color-midnight);
  text-anchor: middle;
}

.location-scroll__stop-tag {
  font-family: var(--font-body);
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  fill: var(--color-obsidian);
  text-anchor: middle;
  opacity: 0.75;
}

.location-scroll__stop--end .location-scroll__stop-name {
  font-size: 21px;
}

/* Below 900px the horizontal scroll-jacking track (see main.js) is
   switched off entirely — dragging a single scroll axis sideways is
   unreliable on touch and was the source of the map feeling broken on
   phones/tablets. The three panels simply stack and reveal normally,
   like every other section on the page. */
@media (max-width: 899.98px) {
  .location-scroll {
    height: auto;
  }

  .location-scroll__track {
    position: relative;
    inset: auto;
    flex-direction: column;
    width: 100%;
    height: auto;
  }

  .location-scroll__panel {
    width: 100%;
    height: 100svh;
    padding-block: clamp(3rem, 10vw, 5rem);
  }

  .location-scroll__graphic {
    width: 100%;
  }

  .location-scroll__svg {
    max-height: none;
  }
}

/* ---------- 14. Footer — form and info are deliberately two distinct
   zones: a plain info column, and the enquiry form as its own bordered,
   floating-label card, with a huge faint "50" as a numeric watermark ---------- */
.site-footer {
  position: relative;
  overflow: hidden;
  background-color: var(--color-maroon);
  color: var(--color-stone);
  padding-block: clamp(3rem, 8vw, 7rem);
}

.site-footer__inner {
  position: relative;
  z-index: 1;
  display: grid;
  gap: clamp(2.5rem, 6vw, 4rem);
  grid-template-columns: 1fr;
}

@media (min-width: 768px) {
  .site-footer__inner {
    grid-template-columns: 1fr 1fr;
    align-items: start;
  }
}

.site-footer__info {
  display: grid;
  gap: clamp(1.5rem, 4vw, 2.5rem);
  align-content: start;
  margin-top: clamp(2rem, 5vw, 3rem);
}

/* the form card — bordered, set apart from the plain info column */
.site-footer__form {
  display: grid;
  gap: 0.75rem;
  padding: clamp(1.75rem, 4vw, 2.75rem);
  border: 1px solid rgba(231, 227, 218, 0.25);
}

.form-field {
  position: relative;
  padding-top: 1.35rem;
}

.form-field input,
.form-field textarea {
  width: 100%;
  background: transparent;
  border: none;
  border-bottom: 1px solid rgba(231, 227, 218, 0.35);
  padding-block: 0.5rem;
  color: var(--color-stone);
  font-family: var(--font-body);
  font-size: 1rem;
  resize: none;
  transition: border-color 0.3s ease;
}

.form-field label {
  position: absolute;
  left: 0;
  top: 1.85rem;
  font-size: 1rem;
  color: var(--color-mist);
  pointer-events: none;
  transform-origin: left top;
  transition: transform 0.25s ease, color 0.25s ease;
}

.form-field input:focus + label,
.form-field input:not(:placeholder-shown) + label,
.form-field textarea:focus + label,
.form-field textarea:not(:placeholder-shown) + label {
  transform: translateY(-1.6rem) scale(0.72);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-stone);
}

.form-field input:focus,
.form-field textarea:focus {
  outline: none;
  border-color: var(--color-stone);
}

.btn-submit {
  justify-self: start;
  margin-top: 0.5rem;
  padding: 0.85rem 2.25rem;
  border: 1px solid var(--color-stone);
  color: var(--color-stone);
  font-size: 0.75rem;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  background: transparent;
  transition: background-color 0.35s ease, color 0.35s ease;
}

.btn-submit:hover {
  background-color: var(--color-stone);
  color: var(--color-maroon);
}

.site-footer__success {
  font-size: 0.9rem;
  color: var(--color-stone);
  opacity: 0;
}

.site-footer__bottom {
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: clamp(2.5rem, 6vw, 4rem);
  padding-top: clamp(1.5rem, 3vw, 2rem);
  border-top: 1px solid rgba(231, 227, 218, 0.2);
}

.site-footer__bottom .logo {
  width: clamp(100px, 12vw, 150px);
}

.site-footer__copyright {
  font-size: 0.75rem;
  color: var(--color-mist);
}

.site-footer__social {
  display: flex;
  gap: 0.85rem;
}

.site-footer__social a {
  width: 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(231, 227, 218, 0.3);
  border-radius: 50%;
  transition: background-color 0.3s ease, color 0.3s ease;
}

.site-footer__social a:hover {
  background-color: var(--color-stone);
  color: var(--color-maroon);
}

.site-footer__social svg {
  width: 15px;
  height: 15px;
  fill: currentColor;
}

.site-footer__legal {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1rem;
  font-size: 0.75rem;
  color: var(--color-mist);
}

.site-footer__legal a:hover {
  color: var(--color-stone);
}

/* ---------- 15. Flat-color interludes — one base + two color modifiers,
   reused by "Why ONE50", "Residences" and "Trust & Credibility" instead of
   three separate background rules ---------- */
.flat-section {
  padding-block: clamp(4rem, 10vw, 8rem);
}

/* lets a full-bleed element (e.g. the philosophy split-panel) sit flush
   against the top edge instead of inheriting the section's padding */
.flat-section--flush-top {
  padding-top: 0;
}

.flat-section--stone {
  background-color: var(--color-stone);
  color: var(--color-midnight);
}

.flat-section--stone .eyebrow,
.flat-section--stone .lede {
  color: var(--color-obsidian);
}

.flat-section--stone .reveal-title {
  color: var(--color-midnight);
}

.flat-section--maroon {
  background-color: var(--color-maroon);
}

/* Why ONE50 — three positioning pillars */
.pillars__grid {
  display: grid;
  gap: clamp(2rem, 5vw, 3rem);
  grid-template-columns: 1fr;
  margin-top: clamp(2.5rem, 6vw, 4rem);
}

@media (min-width: 900px) {
  .pillars__grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

.pillar {
  position: relative;
}

@media (min-width: 900px) {
  .pillar + .pillar {
    border-left: 1px solid rgba(57, 0, 7, 0.15);
    padding-left: clamp(1.5rem, 3vw, 2.5rem);
  }
}

.pillar__title {
  position: relative;
  font-size: clamp(1.25rem, 2vw, 1.75rem);
  margin-bottom: 0.5rem;
}

.pillar__text {
  color: var(--color-obsidian);
  font-size: clamp(0.95rem, 0.5vw + 0.8rem, 1.05rem);
}

/* Reveal media — one shared "real photo with a scroll clip-reveal and
   a gentle hover zoom" recipe, reused by the Why ONE50 gallery and the
   Residence cards instead of two near-identical blocks */
.reveal-media {
  position: relative;
  overflow: hidden;
}

.reveal-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.08);
  transition: transform 0.6s ease;
}

.reveal-media:hover img {
  transform: scale(1);
}

.reveal-media--portrait {
  aspect-ratio: 4 / 5;
}

/* Why ONE50 — a two-photo gallery, adapted from the real-photo +
   quote compositions studied on era-residence.com */
.philosophy__gallery {
  display: grid;
  grid-template-columns: 1fr;
}

@media (min-width: 700px) {
  .philosophy__gallery {
    grid-template-columns: 1fr 1fr;
  }
}

.philosophy__gallery-item {
  min-height: clamp(280px, 46vw, 480px);
}

.philosophy__gallery-tint {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(14, 22, 36, 0) 45%, rgba(14, 22, 36, 0.78) 100%);
}

.philosophy__gallery-quote {
  position: absolute;
  left: clamp(1.25rem, 4vw, 2.5rem);
  bottom: clamp(1.5rem, 4vw, 2.5rem);
  z-index: 1;
  max-width: 20rem;
}

.philosophy__gallery-quote .accent-quote {
  margin-top: 0.75rem;
  color: var(--color-stone);
}

.philosophy__body {
  padding-top: clamp(3rem, 7vw, 5rem);
}

.philosophy__cta {
  display: flex;
  justify-content: center;
  margin-top: clamp(2.5rem, 6vw, 3.5rem);
}

/* a non-video variant of the magnetic CTA — sits in normal document
   flow (centered) instead of pinned to a corner of a full-bleed video */
.magnetic-cta--static {
  position: static;
  opacity: 1;
}

/* Amenities index — a browsable list of tags, not another video */
.amenities-index {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 0.75rem;
  margin-top: 1.75rem;
}

.amenities-index li {
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-stone);
  padding: 0.5rem 1rem;
  border: 1px solid rgba(231, 227, 218, 0.3);
  background-color: rgba(14, 22, 36, 0.55);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}

/* Residences highlight */
.residences__grid {
  display: grid;
  gap: clamp(1.5rem, 4vw, 2.5rem);
  grid-template-columns: 1fr;
  margin-top: clamp(2rem, 5vw, 3rem);
}

@media (min-width: 768px) {
  .residences__grid {
    grid-template-columns: 1fr 1fr;
  }
}

/* Residence cards — a real interior still, with its title and copy
   sitting below it (not overlaid on top of the photo) */
.residence-card {
  display: flex;
  flex-direction: column;
}

.residence-card__body {
  padding: clamp(1.25rem, 3vw, 1.75rem) 0 0;
}

.residence-card__title {
  font-size: clamp(1.25rem, 2vw, 1.75rem);
  margin-bottom: 0.5rem;
  color: var(--color-stone);
}

.residence-card__text {
  color: var(--color-mist);
  font-size: 0.95rem;
  max-width: 34ch;
}

/* Trust & Credibility */
.trust__credit {
  margin-top: clamp(2rem, 5vw, 3rem);
  font-size: 0.8rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-obsidian);
}

/* ---------- 20. Split panel — a two-tone maroon/stone layout, adapted
   from the dark/light lifestyle-statement panels studied on
   era-residence.com, used once for the Developer/Trust section. ---------- */
.split-panel {
  display: grid;
  grid-template-columns: 1fr;
}

@media (min-width: 900px) {
  .split-panel {
    grid-template-columns: 1.3fr 1fr;
  }
}

.split-panel__side {
  padding: clamp(2.5rem, 7vw, 5.5rem) clamp(1.5rem, 5vw, 3rem);
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.split-panel__side--stone {
  background-color: var(--color-stone);
  color: var(--color-midnight);
}

.split-panel__side--stone .eyebrow {
  color: var(--color-obsidian);
}

.split-panel__side--stone .reveal-title {
  color: var(--color-midnight);
}

.split-panel__side--maroon {
  background-color: var(--color-maroon);
}

.split-panel__side--maroon .accent-quote {
  margin-top: 0;
  color: var(--color-stone);
  font-size: clamp(1.75rem, 3.5vw, 2.75rem);
  max-width: 16ch;
}

/* ---------- 16. Arc dividers — a curved seam between color changes,
   adapted from the dome motif studied on era-residence.com. One base
   shape + two small modifier sets (the color it reveals, the color it
   sits on) instead of a bespoke shape per seam. ---------- */
.arc-divider {
  position: relative;
  z-index: 2;
  width: 100%;
  height: clamp(48px, 9vw, 110px);
  line-height: 0;
  overflow: hidden;
}

.arc-divider svg {
  display: block;
  width: 100%;
  height: 100%;
}

.arc-divider--from-midnight { background-color: var(--color-midnight); }

.arc-divider--maroon path { fill: var(--color-maroon); }

/* ---------- 17. Background watermark — one shared recipe for the
   footer's giant "50" and a section's faint editorial word, so the two
   never redeclare the same font-size/opacity logic twice. ---------- */
.bg-watermark {
  position: absolute;
  z-index: 0;
  font-family: var(--font-heading);
  line-height: 1;
  color: rgba(231, 227, 218, 0.07);
  pointer-events: none;
  user-select: none;
}

.bg-watermark--footer {
  top: 50%;
  right: clamp(-3rem, 4vw, 1rem);
  transform: translateY(-50%);
  font-size: clamp(9rem, 26vw, 24rem);
}

.bg-watermark--section {
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: clamp(5rem, 20vw, 16rem);
  letter-spacing: 0.02em;
  white-space: nowrap;
  text-align: center;
}

/* ---------- 18. Magnetic CTA — a circular button that leans toward the
   cursor, adapted from era-residence.com's floating "Book a Call" button.
   Used sparingly, once, as a direct call to enquire. ---------- */
.magnetic-cta {
  position: absolute;
  z-index: 4;
  right: clamp(1.5rem, 5vw, 4rem);
  bottom: clamp(2rem, 6vw, 4rem);
  width: clamp(88px, 9vw, 120px);
  height: clamp(88px, 9vw, 120px);
  border-radius: 50%;
  border: 1px solid rgba(231, 227, 218, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-size: 0.7rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--color-stone);
  opacity: 0;
  transition: background-color 0.35s ease, color 0.35s ease;
}

.magnetic-cta:hover {
  background-color: var(--color-stone);
  color: var(--color-maroon);
}

/* ---------- 19b. Word-mask — splits a video-section headline into
   individual words at runtime (see main.js), so it arrives word by
   word instead of as one flat block. Paired with a small horizontal
   tick mark under the eyebrow — the quiet counterpart to the fixed
   scroll-hud's vertical line. ---------- */
.word-mask {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
}

.word-inner {
  display: inline-block;
  transform: translateY(110%);
}

.rule-line {
  display: block;
  width: clamp(28px, 4vw, 46px);
  height: 1px;
  background-color: rgba(231, 227, 218, 0.35);
  margin-block: 0.9rem 1.1rem;
}

/* dark modifier — same tick mark, for use on the stone/light backgrounds
   where the default stone-tinted line would be invisible */
.rule-line--dark {
  background-color: rgba(57, 0, 7, 0.25);
}

/* ---------- 19. Accent quote — a single line of authentic brochure
   copy set apart in italic heading type, echoing the script-accent
   emphasis studied on era-residence.com. ---------- */
.accent-quote {
  margin-top: 1.5rem;
  font-family: var(--font-heading);
  font-style: italic;
  font-size: clamp(1.5rem, 3vw, 2.25rem);
  color: var(--color-maroon);
  max-width: 30ch;
}

/* Accent script — a single italic word inline within a heading, the
   same mixed serif/script emphasis as the accent quote but sized to
   sit inside a title rather than stand alone */
.accent-script {
  font-style: italic;
  font-weight: 400;
  color: var(--color-maroon);
}
