/* ==========================================================================
   SWK Properties — Section Layouts (hero, arc gallery, page-specific blocks)
   ========================================================================== */

/* ---- Hero (ink-reveal) ---- */

.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  overflow: hidden;
  background: var(--navy-950);
  color: var(--cream-50);
  /* pan-y (not none): a vertical finger drag still scrolls the page
     natively — important since the hero is now taller than one screen on
     mobile (the gap that reveals the search bar on scroll), so blocking
     all touch gestures here would fight scrolling through a large chunk
     of the page, not just a single screen's worth. A horizontal-ish drag
     (or a tap/short hold) still reaches the ink-reveal canvas, same
     technique already used for this site's other swipeable carousels. */
  touch-action: pan-y;
}

.hero__bg {
  position: absolute;
  left: 0;
  right: 0;
  /* Taller than .hero itself (clipped by its overflow:hidden) so
     parallax.js has room to translate this up/down without ever
     uncovering empty space at the top or bottom edge. */
  top: -30%;
  height: 160%;
  z-index: 0;
  will-change: transform;
}

/* .hero__bg picture must also be block + 100% width/height: it's the img's
   direct containing block now, and a percentage height on the img only
   resolves against a parent with a DEFINITE height. <picture> defaults to
   inline with no sizing of its own, so without this the img silently fell
   back to auto-sizing at its own natural aspect ratio instead of filling
   .hero__bg — showing only a thin strip of photo instead of a full cover. */
.hero__bg picture {
  display: block;
  width: 100%;
  height: 100%;
}

.hero__bg img {
  width: 100%; height: 100%;
  object-fit: cover;
}

@media (prefers-reduced-motion: reduce) {
  .hero__bg { top: 0; height: 100%; }
}

/* Canvas ink-reveal mask sits above the bg image; erasing it reveals the photo beneath */
.hero__mask {
  position: absolute;
  inset: 0;
  z-index: 1;
  /* Mobile Chrome's compositor decides whether a touch-scroll can run on the
     fast path (without waiting on the main thread) by checking touch-action
     on the exact element the finger lands on — inheriting it from an
     ancestor (.hero) isn't always enough for a <canvas>, which is the one
     element in the hero that actually has pointer listeners attached. */
  touch-action: pan-y;
}

.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: linear-gradient(to top, rgba(7, 9, 13, 0.92) 0%, rgba(7, 9, 13, 0.55) 42%, rgba(7, 9, 13, 0.25) 68%, rgba(7, 9, 13, 0.35) 100%);
  pointer-events: none;
}

.hero__content {
  position: relative;
  z-index: 3;
  padding-block: var(--space-9) var(--space-8);
}

/* Clears the mobile brand mark (see .site-brand .brand-logo, 70px tall,
   starting at the 24px top offset) plus a bit of breathing room. */
@media (max-width: 767px) {
  .hero__content {
    padding-top: 120px;
  }
}

.hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ember-400);
  margin-bottom: var(--space-4);
}

.hero__title {
  max-width: 20ch;
  color: var(--white);
}

.hero__title em {
  font-style: normal;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--color-accent);
  display: inline-block;
  padding: 0.1em 0.5em 0.16em;
  border-radius: var(--radius-md);
  background: var(--glass-bg-light);
  border: 1px solid var(--glass-border-light);
  backdrop-filter: blur(var(--glass-blur));
  -webkit-backdrop-filter: blur(var(--glass-blur));
  box-shadow: var(--shadow-md);
}

/* ---- Typewriter reveal (hero headline) ---- */

.tw-word {
  display: inline-block;
}

.tw-char {
  display: inline-block;
  opacity: 0;
  transition: opacity 0.05s linear;
}

.is-typing .tw-char {
  opacity: 1;
}

/* ---- Colourful text (hero "Dubai") ---- */

@keyframes cv-pulse {
  0%, 100% { transform: translateY(0) scale(1); filter: blur(0px); opacity: 1; }
  50% { transform: translateY(-3px) scale(1.01); filter: blur(5px); opacity: 0.8; }
}

.cv-pulse {
  animation: cv-pulse 0.5s ease;
}

@media (prefers-reduced-motion: reduce) {
  .cv-pulse { animation: none; }
}

/* ---- Cascade text (hover letter-reveal) ---- */

.cascade-text {
  display: inline-block;
  color: var(--cascade-color, inherit);
  cursor: pointer;
  transition: color 0.35s ease;
}

.cascade-text__word {
  display: inline-flex;
  overflow: hidden;
  height: 1em;
  vertical-align: top;
}

.cascade-text__char {
  display: inline-block;
  position: relative;
  will-change: transform;
  text-shadow: 0 var(--cascade-shadow-y, 1em) currentColor;
  transition: transform var(--cascade-duration, 250ms) ease-in-out;
}

.cascade-text:hover {
  color: var(--cascade-hover-color, var(--color-accent));
}

.cascade-text:hover .cascade-text__char {
  transform: translateY(calc(-1 * var(--cascade-shadow-y, 1em)));
}

@media (prefers-reduced-motion: reduce) {
  .cascade-text,
  .cascade-text__char {
    transition: none;
  }
}

.hero__subtitle {
  max-width: 52ch;
  margin-top: var(--space-4);
  font-size: var(--fs-md);
  color: var(--slate-100);
}

.hero__ctas {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-top: var(--space-6);
}

.hero__search-wrap {
  margin-top: var(--space-8);
}

/* Mobile only. The search form stays right where it was in the markup
   (inside .hero__content, after the CTA) — what changes is just spacing:
   a large gap under the headline pushes the button down far enough that
   the hero's height naturally grows past one screen instead of being
   clipped to it. The first screenful shows just the headline/CTA over the
   background; the search bar comes into view once the visitor scrolls,
   without needing a separate section. Desktop keeps the original tighter
   spacing where everything fits in one view. */
@media (max-width: 640px) {
  /* svh (not vh) to match .hero's own min-height:100svh — plain vh can
     resolve against the browser's *expanded*-toolbar viewport on real
     mobile Safari, taller than what's actually visible with the toolbar
     showing, which would otherwise push the button below the fold. */
  /* calc(), not a flat svh percentage: the content sitting above this button
     (logo/dock row, eyebrow, heading) is a FIXED px height, not a percentage
     of viewport height, so a flat Nsvh value only lines up with the
     WhatsApp float (position:fixed; bottom:24px) on whatever one device it
     was tuned against. Solving the actual equation — button center should
     land at (100svh - 47px, matching the float's own center) — makes it
     hold on any device height. 506px = the fixed content height above the
     button (~440px) + half the button's own height (19px) + the float's
     47px offset from the bottom, measured empirically. */
  .hero__ctas { margin-top: calc(100svh - 506px); }
  .hero__search-wrap { margin-top: 22svh; }

  /* The base .hero__bg rule sizes the photo to the full height of .hero
     itself, which is fine on desktop (one screen tall) but on mobile
     .hero runs 1.5-2 screens tall (see above), so object-fit:cover was
     blowing the photo up to a huge scale to cover that whole span —
     only a thin sliver of the skyline ended up visible ("zoomed in").
     Capping it to one screen + the parallax buffer keeps a normal,
     un-cropped-looking photo behind the headline/CTA; the scrim
     gradient below already fades to near-solid navy toward the bottom
     of the hero, so the photo running out before the search form is
     invisible. Buffer is top-only (not top+bottom) since parallax.js's
     offset is always >= 0 — it only ever pushes the image down. */
  .hero__bg {
    top: -25svh;
    height: 125svh;
  }

  /* h1's base clamp() floors out at 2.5rem on phone-width viewports (its
     preferred value, tied to vw, is smaller than that floor well before
     desktop widths) — bump the floor specifically for the hero headline. */
  .hero__title {
    font-size: 3.25rem;
  }

  .hero__eyebrow {
    font-size: var(--fs-sm);
  }
}

.hero__scroll-cue {
  position: absolute;
  bottom: var(--space-5);
  left: 50%;
  transform: translateX(-50%);
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-xs);
  color: var(--slate-300);
}

.hero__scroll-cue .line {
  width: 1px; height: 32px;
  background: linear-gradient(to bottom, var(--color-accent), transparent);
}

/* ---- Featured listings / general grid sections ---- */

.listings-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
}

@media (min-width: 640px) { .listings-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .listings-grid { grid-template-columns: repeat(3, 1fr); } }

.section-head-row {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-6);
  margin-bottom: var(--space-7);
}

/* ---- Dark section wrapper (developer showcase, benefits, calculator band) ---- */

.section--dark {
  background: var(--navy-950);
  color: var(--cream-50);
}

.section--dark p { color: var(--slate-300); }
.section--dark h2, .section--dark h3 { color: var(--white); }

/* A gradient, not a flat fill: blends in from the surrounding (transparent,
   body-navy) sections at the top and bottom edges instead of snapping to a
   visibly different shade right at the section boundary. */
.section--alt {
  background: linear-gradient(
    to bottom,
    var(--color-bg) 0,
    var(--color-surface-alt) 80px,
    var(--color-surface-alt) calc(100% - 80px),
    var(--color-bg) 100%
  );
}

/* ---- Photo gallery (wrapping section) ---- */

.arc-gallery {
  position: relative;
}

.arc-gallery__viewall {
  margin-top: var(--space-5);
  text-align: center;
}

/* ---- Fan carousel ---- */

.fan-carousel-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.fan-layout {
  position: relative;
  width: 100%;
  max-width: 80rem;
  height: 26rem;
  margin-top: var(--space-7);
  /* The fan's spread math is keyed off viewport width breakpoints, which
     don't account for aspect ratio — a phone in landscape crosses into
     tablet-width sizing while still being exactly as narrow as portrait,
     so outer cards can compute a position past this container's edge.
     Clipping here keeps that from becoming a page-level horizontal
     scrollbar without having to fight the imported spread math itself. */
  overflow: hidden;
  touch-action: pan-y;
}

@media (min-width: 480px) { .fan-layout { height: 29rem; } }
@media (min-width: 640px) { .fan-layout { height: 31rem; } }
@media (min-width: 768px) { .fan-layout { height: 34rem; } }
@media (min-width: 1024px) { .fan-layout { height: 38rem; } }
@media (min-width: 1280px) { .fan-layout { height: 42rem; } }

.fan-card {
  position: absolute;
  top: 0;
  left: 50%;
  width: 9rem;
  height: 14rem;
  margin-left: -4.5rem;
  border-radius: var(--radius-md);
  overflow: hidden;
  border: 3px solid var(--color-surface);
  background: var(--navy-800);
  box-shadow: var(--shadow-md);
  cursor: pointer;
  will-change: transform;
}

@media (min-width: 480px) { .fan-card { width: 10.5rem; height: 16.5rem; margin-left: -5.25rem; } }
@media (min-width: 768px) { .fan-card { width: 13rem; height: 20.5rem; margin-left: -6.5rem; } }
@media (min-width: 1024px) { .fan-card { width: 15rem; height: 23.5rem; margin-left: -7.5rem; } }
@media (min-width: 1280px) { .fan-card { width: 17rem; height: 26.5rem; margin-left: -8.5rem; } }

.fan-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
}

.fan-pagination {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-top: var(--space-6);
}

.fan-arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  border-radius: var(--radius-full);
  border: 1.5px solid var(--color-border);
  background: var(--navy-800);
  color: var(--slate-300);
  transition: color var(--duration-fast) var(--ease-luxury), border-color var(--duration-fast) var(--ease-luxury);
}

.fan-arrow:hover { color: var(--color-accent); border-color: var(--color-accent); }
.fan-arrow svg { width: 18px; height: 18px; }

.fan-dots {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  max-width: 18rem;
}

.fan-dot {
  width: 6px;
  height: 6px;
  border-radius: var(--radius-full);
  background: var(--navy-700);
  transition: background var(--duration-base) var(--ease-luxury), transform var(--duration-base) var(--ease-luxury);
}

.fan-dot.is-active {
  background: var(--color-accent);
  transform: scale(1.5);
}

/* ---- Lightbox ---- */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(7, 9, 13, 0.94);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--duration-base) var(--ease-luxury);
}

.lightbox.is-open { opacity: 1; visibility: visible; }

.lightbox__frame {
  position: relative;
  max-width: 900px;
  width: 100%;
  /* Let vertical page-scroll gestures pass through untouched; a horizontal
     drag is claimed by swipe.js instead of the browser's default handling. */
  touch-action: pan-y;
}

.lightbox__frame img {
  width: 100%;
  max-height: 78vh;
  object-fit: contain;
  border-radius: var(--radius-md);
}

.lightbox__close,
.lightbox__prev,
.lightbox__next {
  position: absolute;
  width: 48px; height: 48px;
  border-radius: var(--radius-full);
  background: rgba(255, 255, 255, 0.12);
  color: var(--white);
  display: flex; align-items: center; justify-content: center;
  transition: background var(--duration-fast) var(--ease-luxury);
}

.lightbox__close:hover,
.lightbox__prev:hover,
.lightbox__next:hover { background: rgba(255, 255, 255, 0.25); }

.lightbox__close { top: -60px; right: 0; }
.lightbox__prev { left: -60px; top: 50%; transform: translateY(-50%); }
.lightbox__next { right: -60px; top: 50%; transform: translateY(-50%); }

.lightbox__counter {
  text-align: center;
  color: var(--slate-300);
  font-size: var(--fs-xs);
  margin-top: var(--space-3);
}

@media (max-width: 720px) {
  .lightbox__prev { left: var(--space-2); }
  .lightbox__next { right: var(--space-2); }
  .lightbox__close { top: -48px; right: 0; }
}

/* ---- Featured listings slider ---- */

.feature-slider__viewport {
  overflow: hidden;
}

.feature-slider__track {
  --slides-per-view: 1;
  display: flex;
  gap: var(--space-6);
  transition: transform var(--duration-slow) var(--ease-luxury);
  will-change: transform;
  touch-action: pan-y;
}

@media (min-width: 700px) { .feature-slider__track { --slides-per-view: 2; } }
@media (min-width: 1100px) { .feature-slider__track { --slides-per-view: 4; } }

.feature-slider__track > .property-card--feature {
  flex: 0 0 calc((100% - (var(--slides-per-view) - 1) * var(--space-6)) / var(--slides-per-view));
}

.feature-slider__nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  margin-top: var(--space-7);
}

.feature-slider__arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  border-radius: var(--radius-full);
  border: 1.5px solid var(--color-border);
  background: var(--navy-800);
  color: var(--slate-300);
  transition: color var(--duration-fast) var(--ease-luxury), border-color var(--duration-fast) var(--ease-luxury), opacity var(--duration-fast) var(--ease-luxury);
}

.feature-slider__arrow:hover:not(:disabled) { color: var(--color-accent); border-color: var(--color-accent); }
.feature-slider__arrow svg { width: 18px; height: 18px; }
.feature-slider__arrow:disabled { opacity: 0.35; cursor: default; }

.feature-slider__dots {
  display: flex;
  gap: 6px;
}

/* The dot itself stays visually small; the button's hit area is enlarged
   via a centered pseudo-element so it's still comfortably tappable on
   touch devices. */
.feature-slider__dot {
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.feature-slider__dot::after {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: var(--radius-full);
  background: var(--navy-700);
  transition: background var(--duration-base) var(--ease-luxury), transform var(--duration-base) var(--ease-luxury);
}

.feature-slider__dot.is-active::after {
  background: var(--color-accent);
  transform: scale(1.4);
}

@media (prefers-reduced-motion: reduce) {
  .feature-slider__track { transition: none; }
}

/* ---- Featured section custom display font ---- */

.featured-section .section-header h2,
.featured-section .property-card__feature-title {
  font-family: var(--font-feature);
}

/* ---- Clash Display headings (selected homepage section titles) ----
   !important is deliberate: this is a utility class meant to force the
   font on a heading regardless of which section-scoped font rule (e.g.
   .featured-section's Bodoni Moda override) would otherwise win by
   specificity. */

.font-clash {
  font-family: 'Clash Display', var(--font-display) !important;
}

/* ---- Investment benefits band ---- */

.benefits-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-5);
}

@media (min-width: 700px) { .benefits-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .benefits-grid { grid-template-columns: repeat(4, 1fr); } }

/* ---- Community grid ---- */

.communities-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-5);
}

@media (min-width: 768px) { .communities-grid { grid-template-columns: repeat(4, 1fr); } }

/* ---- Testimonials / blog rows ---- */

.testimonials-grid, .blog-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
}

@media (min-width: 700px) { .testimonials-grid, .blog-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .testimonials-grid, .blog-grid { grid-template-columns: repeat(3, 1fr); } }

/* ---- Page hero (interior pages, non full-screen) ---- */

.page-hero {
  background: var(--navy-950);
  color: var(--cream-50);
  padding-top: calc(var(--header-h) + var(--space-8));
  padding-bottom: var(--space-8);
  position: relative;
  overflow: hidden;
}

.page-hero::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 85% 20%, rgba(232, 69, 44, 0.16), transparent 55%);
  pointer-events: none;
}

.page-hero__title { position: relative; }
.page-hero p { position: relative; max-width: 60ch; }

/* ---- Two-column content block (About page etc.) ---- */

.split-block {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-8);
  align-items: center;
}

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

.split-block img {
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}

/* ---- Values / process step list ---- */

.step-list {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: 1fr;
}

@media (min-width: 700px) { .step-list { grid-template-columns: repeat(2, 1fr); } }

.step-item {
  display: flex;
  gap: var(--space-4);
}

.step-item .num {
  flex-shrink: 0;
  width: 44px; height: 44px;
  border-radius: var(--radius-full);
  border: 1.5px solid var(--color-accent);
  color: var(--color-accent-hover);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display);
  font-weight: 700;
}
