/* ============================================================================
   KAMO Property Group — Landing Page Styles
   ----------------------------------------------------------------------------
   Editorial-luxury aesthetic: midnight ground, off-white type,
   muted gold accent, generous spacing, fine hairlines.
============================================================================ */

:root {
  /* Never let the OS swap a typographic glyph for a colour emoji. iOS/Android
     render ↗ ↔ ♡ ☀ from the emoji font by default, which reads as a chat
     sticker inside this type system. The U+FE0E selector in the markup is the
     load-bearing fix (universal); this is the modern declarative backstop. */
  font-variant-emoji: text;

  /* Layout bands — keep in sync with src/breakpoints.ts */
  --kamo-bp-mobile: 720px;
  --kamo-bp-tablet: 960px;
  --kamo-bp-narrow: 380px;
  --kamo-bp-short-mobile-h: 640px;
  --kamo-bp-short-desktop-h: 740px;

  /* Rendered height of the fixed mobile tab bar (.kamo-app-shell__mobile-nav):
     4px top pad + a 40px min-height row + 4px bottom pad + 1px border-top = 49px.
     The nav owns the home-indicator inset, so anything that sits flush ON TOP of
     the nav (sticky enquire bar, home CTA, offset consent banner) offsets by
     exactly this — one source of truth keeps them seam-free. */
  --mobile-nav-h: calc(49px + env(safe-area-inset-bottom, 0px));

  /* Site header's `min-height` (.kamo-app-shell__header) — the CSS-only
     baseline sticky-rail offset for the Stage/Dossier layouts (native
     `position: sticky` on Stage; useBothWaysSticky.ts on Dossier, which
     measures the header's REAL rendered height at runtime for its own
     `top` writes), so this constant only has to be a good-enough fallback
     for the plain CSS `position: sticky` value both layouts share. Ignores
     `env(safe-area-inset-top)` (usually 0 on the desktop viewports where a
     sticky rail matters). */
  --header-h: 64px;

  --kamo-bg:      #0a0c10;
  --kamo-bg-deep: #07090d;
  --kamo-fg:      #e8e4dc;
  --kamo-fg-dim:  rgba(232, 228, 220, 0.55);
  --kamo-fg-mute: rgba(232, 228, 220, 0.54); /* tertiary/labels — raised 0.45→0.54 to clear WCAG AA on midnight, kept just below fg-dim */
  --kamo-rule:    rgba(232, 228, 220, 0.14);
  --kamo-gold:    #c9a574;
  /* Gold for SMALL TEXT — same hue family, guaranteed AA on each theme ground */
  --kamo-gold-text: #c9a574;
  --kamo-gold-soft: rgba(201, 165, 116, 0.45);

  --kamo-panel-bg: rgba(7, 9, 13, 0.38);
  --kamo-panel-bg-strong: rgba(7, 9, 13, 0.86);
  /* Email CTA panel — more opaque than generic panels */
  --kamo-panel-bg-cta: rgba(7, 9, 13, 0.72);
  --kamo-panel-border-cta: rgba(232, 228, 220, 0.14);
  --kamo-panel-shadow-cta: 0 16px 42px rgba(0, 0, 0, 0.38);
  --kamo-panel-border: rgba(232, 228, 220, 0.1);
  --kamo-panel-blur: 12px;
  --kamo-panel-shadow: 0 14px 36px rgba(0, 0, 0, 0.22);

  /* Prata ships a single weight (400) with no italics: declared lighter
     weights resolve to it without synthesis, and italics render faux-oblique. */
  --font-serif: 'Prata', 'Prata Fallback', Georgia, serif;
  --font-sans:  'Lora', Georgia, serif;
  --font-mono:  'Lora', Georgia, serif;

  /* Header logo reserve — keep in sync with .brand-header-anchor */
  --kamo-logo-clear-w: min(360px, 62vw);
  --kamo-logo-clear-h: clamp(48px, 6vw, 68px);

  /* Additional tokens from design system */
  --kamo-gold-faint: rgba(201, 165, 116, 0.10);
  --kamo-error: #e88a8a;
  --kamo-shadow-panel: 0 14px 36px rgba(0, 0, 0, 0.22);
  --kamo-shadow-cta:   0 16px 42px rgba(0, 0, 0, 0.38);
  --kamo-shadow-modal: 0 20px 56px rgba(0, 0, 0, 0.42);
  --kamo-r-hair: 2px;
  --kamo-r-pad:  3px;
  --font-ar: 'Noto Naskh Arabic', 'Lora', serif;

  /* Letter-spacing scale */
  --track-tight:  0.01em;
  --track-body:   0.02em;
  --track-wide:   0.12em;
  --track-label:  0.2em;
  --track-wider:  var(--track-label); /* deprecated alias of --track-label */
  --track-widest: var(--track-label); /* deprecated alias of --track-label */
  /* Interior display register (owner decision 2026-07-24, "Variant A"):
     sentence case in the homepage hero's voice — 0.07em was uppercase
     tracking; sentence case wants near-neutral. */
  --track-display: 0.015em;
  --display-transform: none;
  --display-size-mult: 0.92;
  --body-size: 16px;
  --kamo-line: rgba(201,165,116,0.25);

  /* Top-of-page rhythm — the page-hero's top padding, one source of truth so
     interior pages open at a consistent depth below the fixed header. */
  --hero-pad-top: clamp(40px, 5.5vw, 72px);

  /* Spacing scale */
  --space-1: 4px;   --space-2: 6px;   --space-3: 8px;
  --space-4: 12px;  --space-5: 14px;  --space-6: 18px;
  --space-7: 22px;  --space-8: 28px;  --space-9: 40px;
  --space-10: 56px;

  /* Motion */
  --ease-emphasised: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-standard:   cubic-bezier(0.65, 0, 0.35, 1);
  --ease-flight:     cubic-bezier(0.4, 0, 0.2, 1);
  --dur-fast:   180ms;
  --dur-base:   280ms;
  --dur-mid:    420ms;
  --dur-slow:   600ms;
  --dur-flight: 1200ms;
}

/* ============================================================================
   Metric-matched serif fallback — kills the hero-headline font-swap reflow.
   ----------------------------------------------------------------------------
   The homepage LCP (the hero <h1>) first paints in Georgia, then swaps to
   Prata once Google Fonts loads (print->all swap in index.html). Without
   matched metrics that swap reflows the headline -> CLS + a visible jump.

   This face renders local Georgia (the boot-hero already falls back to it)
   but forces it to Prata's box, so the fallback paint and the Prata
   paint occupy the SAME width and line height -> zero layout shift on swap.

   Values were measured from the actual font files (fontTools), NOT guessed:
   - size-adjust 108.2% — Prata's advance over the real headline string
     ("Prime addresses in Egypt and the UAE.") is 0.5068 em/char vs Georgia
     0.4685; the ratio is 1.082, so Prata is ~8% WIDER than macOS Georgia
     (x-height ratio 1.076 agrees). 108.2% lines the two up.
   - ascent/descent overrides reproject Prata's vertical box (hhea/typo
     ascent 0.993, descent 0.362 em — USE_TYPO_METRICS is set, so browsers
     use these, not the 1.201 winAscent) onto the size-adjusted fallback em
     (metric / 1.082), so the line box height matches too — no vertical jump.
   - line-gap 0% — both faces ship a zero hhea/typo line gap.
============================================================================ */
@font-face {
  font-family: 'Prata Fallback';
  src: local('Georgia'), local('Times New Roman');
  size-adjust: 108.2%;
  ascent-override: 91.8%;
  descent-override: 33.5%;
  line-gap-override: 0%;
}

/* ============================================================================
   CLASSIC theme — lighter, higher-contrast skin for the 50–70 demographic.
   Cream/warm-white surfaces, warm-charcoal type, a deeper gold that passes AA
   on light, softer radii and larger reading type. MODERN (the :root dark skin)
   stays the default; both share one component tree via these tokens.
   ============================================================================ */
[data-theme="light"] {
  /* Linen light variant — pulled from the KÂMO design-system handoff bundle:
     warm linen ground, deep warm ink type, deeper bronze gold. */
  --kamo-bg:               #f1ede3;  /* warm linen ground                 */
  --kamo-bg-deep:          #e8e1d2;  /* deeper linen — panels / map edges  */
  --kamo-panel-bg:         rgba(250, 247, 241, 0.82);
  --kamo-panel-bg-strong:  rgba(250, 247, 241, 0.96);
  --kamo-panel-bg-cta:     rgba(250, 247, 241, 0.90);
  --kamo-panel-border:     rgba(26, 22, 18, 0.12);
  --kamo-panel-border-cta: rgba(26, 22, 18, 0.16);
  --kamo-fg:        #1a1612;                    /* deep warm ink           */
  --kamo-fg-dim:    rgba(26, 22, 18, 0.64);     /* secondary               */
  --kamo-fg-mute:   rgba(26, 22, 18, 0.62);     /* tertiary / labels — raised 0.44→0.62 for AA on parchment, kept just below fg-dim */
  --kamo-rule:      rgba(26, 22, 18, 0.14);
  --kamo-gold:      #8a6a3a;                     /* deeper bronze           */
  --kamo-gold-text: #6f5527;                     /* small-text bronze (AA+) */
  --kamo-gold-soft: rgba(138, 106, 58, 0.42);
  --kamo-gold-faint:rgba(138, 106, 58, 0.12);
  --kamo-shadow-panel: 0 6px 24px rgba(40, 30, 12, 0.10);
  --kamo-shadow-cta:   0 8px 28px rgba(40, 30, 12, 0.14);
  --kamo-shadow-modal: 0 12px 40px rgba(40, 30, 12, 0.18);
  /* Softer, more familiar radii for the card-led Classic UI */
  --kamo-r-hair: 6px;
  --kamo-r-pad:  8px;
}

/* Classic component adjustments (token swaps don't cover everything) */
[data-theme="light"] .kamo-app-shell__logo img,
[data-theme="light"] .kamo-app-shell__footer-col img {
  /* Per design bundle: bring the bright gold PNG down to the bronze register
     so it harmonises with the deeper bronze used across the linen variant. */
  filter: brightness(0.74) saturate(1.15);
}

/* Structural panels that hardcode the dark midnight ground — route them through
   the linen panel tokens in light so the homepage hero, map label and Explore
   cards/pills follow the theme instead of staying dark. */
[data-theme="light"] .hero-intro-column {
  background: var(--kamo-panel-bg-cta);
  border-color: var(--kamo-panel-border);
}
[data-theme="light"] .market-label {
  background: var(--kamo-panel-bg-strong);
}
[data-theme="light"] .listings-panel__pill {
  background: var(--kamo-panel-bg);
}
[data-theme="light"] .listings-panel__card {
  background: var(--kamo-panel-bg-strong);
}
[data-theme="light"] .market-label--detail .city-detail-close {
  background: var(--kamo-panel-bg-strong);
}

/* Map vignette edges fade to BLACK in the dark skin; in light they must fade to
   the linen page instead (otherwise the map shows dark top/bottom bands). One
   uniform linen vignette covers both the desktop + mobile @media variants. */
[data-theme="light"] .kamo-root--network .map-canvas::after,
[data-theme="light"] .kamo-root--city-detail .map-canvas::after {
  background: linear-gradient(
    to bottom,
    rgba(241, 237, 227, 0.55) 0%,
    transparent 16%,
    transparent 56%,
    rgba(241, 237, 227, 0.7) 100%
  );
}
/* Property-detail document download overlay: soften the dark backdrop in light. */
[data-theme="light"] .property-detail__doc-modal {
  background: rgba(20, 15, 8, 0.55);
}

/* Homepage CTA copy hardcodes linen (dark-skin) text in several media variants;
   on the linen ground that's nearly invisible. Force ink in light. !important
   beats the more-specific .kamo-root--network rules without re-listing them all. */
[data-theme="light"] .cta-about { color: var(--kamo-fg) !important; }
[data-theme="light"] .cta-helper { color: var(--kamo-fg-dim) !important; }

[data-theme="light"] body {
  /* 300-weight body was too thin to read on light; nudge to 400 (also Lora's
     variable-weight floor) */
  font-weight: 400;
}
[data-theme="light"] .kamo-body,
[data-theme="light"] .property-detail__desc,
[data-theme="light"] .kamo-document-main p {
  font-size: 16px;
  line-height: 1.7;
}

/* ── Light mode: fix hard-coded dark-mode rgba values ──────────────────── */

/* Form inputs — the rgba(232,228,220) values are invisible on cream bg */
[data-theme="light"] .enquiry-input,
[data-theme="light"] .enquiry-textarea {
  background: rgba(26, 22, 18, 0.04);
  border-color: rgba(26, 22, 18, 0.16);
}
[data-theme="light"] .enquiry-input:focus,
[data-theme="light"] .enquiry-textarea:focus {
  border-color: var(--kamo-gold-soft);
}

/* kamo-field (used in Contact page, EnquiryGate, etc.) */
[data-theme="light"] .kamo-field {
  background: rgba(26, 22, 18, 0.04);
}

/* Enquiry contact divider */
[data-theme="light"] .enquiry-contact {
  border-top-color: var(--kamo-rule);
}

/* Enquiry close button hover — rgba(232,…) is a light colour, barely visible */
[data-theme="light"] .enquiry-close:hover {
  background: rgba(26, 22, 18, 0.06);
}

/* Property detail aside panel highlight inset */
[data-theme="light"] .property-detail__panel {
  box-shadow: var(--kamo-shadow-panel), inset 0 1px 0 rgba(26, 22, 18, 0.04);
}

/* Modal backdrop — keep it dark in light mode (intentional overlay) */
[data-theme="light"] .enquiry-modal-backdrop {
  background: rgba(20, 15, 8, 0.64);
}

/* Sticky mobile enquire bar */
[data-theme="light"] .ks-sticky-enquire {
  background: var(--kamo-panel-bg-strong);
  border-top-color: var(--kamo-rule);
}

* { box-sizing: border-box; }
html, body, #root { height: 100%; }

/* Smooth document scrolling */
html { scroll-behavior: smooth; }

/* Route transitions — a quiet cross-fade between client-side pages (React
   Router `viewTransition` on nav links). The UA default cross-fades root; we
   only tune the duration and disable it under reduced-motion. */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 240ms;
  animation-timing-function: var(--ease-standard, ease);
}
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation: none !important;
  }
}

/* Interior routes (PageLayout) — allow document scroll; homepage keeps overflow hidden.
   `<html>` alone carries the scroll overflow — it's the actual scrolling element
   (document.scrollingElement) for these routes. `<body>` used to get the SAME
   overflow-y:auto, which made it a scroll container too (per the CSS Overflow
   spec, any non-visible overflow value establishes one, whether or not the box
   ever actually overflows) — body's own height is auto-to-content, so it never
   overflows and never itself scrolls, but being the NEAREST scroll-container
   ancestor to any `position: sticky` descendant (e.g. the Stage/Dossier rails)
   is enough to make native sticky compute its stuck offsets against an inert
   box instead of the element that's really moving — sticky was inert site-wide
   on these routes as a result (verified: removing body's overflow-y here is
   what makes `.ks-lay__rail`'s `position: sticky` start pinning).
   `overflow-x: clip` on body below (NOT `overflow: visible`) is load-bearing,
   and NOT a no-op — two things had to be true at once here, which is why
   this isn't just "remove body's overflow": (1) body must not establish a
   scroll container in EITHER axis, or sticky breaks again exactly as above;
   (2) body must still genuinely CONTAIN horizontal overflow, or content
   wider than the viewport (e.g. a project's price-matrix table, deliberately
   wider than mobile — see .price-matrix-table's own horizontal-scroll
   affordance) leaks into `document.scrollingElement.scrollWidth` and the
   page becomes side-scrollable — caught for real via this file's own e2e
   suite (a mobile Dossier layout test) after the FIRST version of this fix
   used plain `overflow: visible` on body. The reason a NAIVE `overflow-x:
   hidden` on `<html>` doesn't already handle (2) on its own: `hidden` still
   tracks a genuine scrollable-overflow region internally — it only hides the
   scrollbar chrome and blocks user-initiated scroll input, so a descendant's
   overflow can still inflate `scrollWidth` past it (and on some touch
   devices, still be gesture-pannable) — this used to be masked only because
   BODY also had `overflow-x: hidden` stacked on top, doubly containing it;
   removing that stacked hidden for sticky's sake is what exposed the gap.
   `overflow-x: clip` is different: it never establishes a scrollable-overflow
   region in the first place, so nothing downstream can ever measure or pan
   past it — genuinely stricter than `hidden`, not just a synonym (same
   reasoning the homepage rule below already applies to ITS OWN horizontal
   containment, for the same underlying reason). It does NOT work as a
   substitute on `<html>` ITSELF, though — verified: Chromium quietly computes
   `overflow-x: clip` on the ROOT element back down to `hidden` (a root-
   element special case, not a bug in this stylesheet), so the real fix has
   to live on `body`, not `html`. `overflow-y` stays `visible` on body (not
   `clip`) — only the horizontal axis has anything that legitimately needs
   to break out sideways on this site; clip and visible both equally avoid
   establishing a scroll container, so this isn't a tradeoff. */
html.kamo-document-page {
  height: auto;
  min-height: 100%;
  overflow-x: hidden;
  overflow-y: auto;
}
html.kamo-document-page body {
  height: auto;
  min-height: 100%;
  overflow-x: clip;
  overflow-y: visible;
}
html.kamo-document-page #root {
  height: auto;
  min-height: 100%;
}

/* Homepage: a 100svh hero, then content sections scroll below. The document
   scrolls the VIEWPORT — we must NOT make <html> its own scroll container here.
   An `overflow-y:auto` on the root turns <html> into a scrollport, and on iOS
   Safari that detaches IntersectionObserver's implicit (viewport) root from the
   scroll: the hero-intersection that drives the fixed chrome then never fires,
   so the top header stays see-through and the tab bar keeps bleeding light
   content. So we contain horizontal overflow with `overflow-x: clip` instead —
   `clip` clips without establishing a scroll container or forcing overflow-y to
   `auto`, so the viewport stays the vertical scroller and IntersectionObserver
   keeps working. It sits on the ROOT (a `clip` on <body> alone did not contain a
   fixed-attribute-width footer logo that inflated the ICB and stretched the fixed
   header/nav). overflow-y stays visible so nothing here becomes a scroll box. */
html.kamo-home-page,
html.kamo-home-page body {
  height: auto;
  min-height: 100%;
}
html.kamo-home-page {
  overflow-x: clip;
}
html.kamo-home-page body {
  overflow-x: clip;
  overflow-y: visible;
}
html.kamo-home-page #root {
  height: auto;
  min-height: 100%;
}

.noscript-fallback {
  max-width: 36rem;
  margin: 0 auto;
  padding: 2.5rem 1.5rem 3rem;
  font-family: var(--font-sans);
  color: var(--kamo-fg);
  background: var(--kamo-bg);
  line-height: 1.55;
}
.noscript-fallback h1 {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: 1.75rem;
  margin: 0 0 1rem;
}
.noscript-fallback p {
  margin: 0 0 0.85rem;
  color: var(--kamo-fg-dim);
}

/* Keep all app UI above decorative body layers (grain/vignette must stay BELOW #root). */
#root {
  position: relative;
  z-index: 1;
}

body {
  margin: 0;
  background: var(--kamo-bg);
  color: var(--kamo-fg);
  font-family: var(--font-sans);
  font-weight: 300;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow: hidden;
}

/* Subtle film grain — z-index 0 so it shows through map “ocean” only, not stacked on top of UI */
body::before {
  content: "";
  position: fixed; inset: 0;
  pointer-events: none;
  background:
    radial-gradient(120% 75% at 50% 0%, rgba(255, 255, 255, 0.035), transparent 58%),
    radial-gradient(68% 42% at 50% 100%, rgba(0, 0, 0, 0.22), transparent 76%);
  z-index: 0;
}
body::after {
  content: "";
  position: fixed; inset: 0;
  pointer-events: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1   0 0 0 0 1   0 0 0 0 1   0 0 0 0.05 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  opacity: 0.22;
  z-index: 0;
}
/* Document pages sit flat on the surface — the top-glow radials read as a
   murky smudge behind sparse text pages (2026-07-24 audit + owner). The
   homepage and map shells keep their atmospheric wash. */
body:has(.kamo-document-main)::before {
  display: none;
}
/* Light variant: white glow/grain vanish on linen — swap to warm-dark gradients
   and dark-noise grain (per design bundle). */
[data-theme="light"] body::before {
  background:
    radial-gradient(120% 75% at 50% 0%, rgba(120, 92, 50, 0.04), transparent 58%),
    radial-gradient(68% 42% at 50% 100%, rgba(60, 45, 22, 0.06), transparent 76%);
}
[data-theme="light"] body::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0   0 0 0 0 0   0 0 0 0 0   0 0 0 0.05 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  opacity: 0.16;
}

/* ===== Root scaffold ===================================================== */
.kamo-root {
  position: relative;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}

/* Homepage hero: the map fills a viewport-tall box; content sections scroll
   below it (the overlays anchor to this box, unchanged). dvh avoids mobile
   browser-chrome clipping. */
.kamo-root--hero {
  height: 100vh;
  height: 100dvh;
}
.kamo-home {
  position: relative;
  width: 100%;
}
.kamo-home__sections {
  position: relative;
  background: var(--kamo-bg);
}

/* Lead-gen homepage hero (replaces the animated map on `/`). Fast, no animation
   gate; the <h1> is the LCP element so it paints instantly over the CSS wash.
   OWNER: for a real hero photo, drop an optimised image in /public/hero/ and add it
   as the TOP background layer, keeping a scrim so the text stays legible, e.g.:
     background-image:
       linear-gradient(180deg, rgba(7,9,13,0.28), rgba(7,9,13,0.80)),
       url('/hero/hero.jpg');
     background-size: cover; background-position: center; */
.home-hero {
  position: relative;
  min-height: clamp(560px, 88svh, 900px);
  display: flex;
  align-items: center;
  padding: clamp(96px, 16vh, 168px) clamp(24px, 5vw, 64px) clamp(56px, 9vh, 96px);
  overflow: hidden;
  background:
    radial-gradient(120% 92% at 16% 4%, var(--kamo-gold-faint), transparent 52%),
    radial-gradient(90% 80% at 100% 100%, rgba(201, 165, 116, 0.06), transparent 55%),
    var(--kamo-bg);
}
/* Hero media layer: a muted autoplay <video> loop (or a photo) behind the scrim. The
   poster still is set as the .home-hero__media background, so it paints instantly and is
   what shows under prefers-reduced-motion (the video is hidden there). */
.home-hero__media {
  position: absolute;
  inset: 0;
  z-index: 0;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  /* The still is passed as CSS vars (HomeHero.tsx) so portrait phones can get
     the dedicated portrait crop — the landscape 16:9 poster rendered ~45%
     empty sky on a phone-shaped viewport (2026-07-24 audit). */
  background-image: var(--hero-still);
}
@media (max-width: 719px) and (orientation: portrait) {
  .home-hero__media {
    background-image: var(--hero-still-portrait, var(--hero-still));
  }
}
.home-hero__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
@media (prefers-reduced-motion: reduce) {
  /* Honour reduced-motion: drop the loop, keep the still poster background. */
  .home-hero__video {
    display: none;
  }
}
.home-hero--photo::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  /* Light scrim — just enough to anchor the text; legibility is carried by the
     text-shadows below so the video stays bright. */
  background: linear-gradient(180deg, rgba(7, 9, 13, 0.32) 0%, rgba(7, 9, 13, 0.55) 100%);
  pointer-events: none;
}
.home-hero__inner {
  position: relative;
  z-index: 2;
  max-width: 1120px;
  margin: 0 auto;
  width: 100%;
}
/* Over a photo, force warm-white text + the brighter gold eyebrow on BOTH skins
   (the scrim is always dark, so the light-skin bronze would be too low-contrast). */
.home-hero--photo .home-hero__headline {
  color: #f3efe8;
  text-shadow: 0 2px 16px rgba(0, 0, 0, 0.45);
}
.home-hero--photo .home-hero__sub {
  color: rgba(243, 239, 232, 0.92);
  text-shadow: 0 1px 10px rgba(0, 0, 0, 0.4);
}
.home-hero--photo .home-hero__eyebrow {
  color: #d3b07f;
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.45);
}
/* Over the hero video/scrim, force all three CTAs to read on BOTH skins — the
   ghost variants otherwise inherit the theme fg (near-black in light mode) and the
   advisor button would use the dim light-skin bronze. */
.home-hero--photo .cta-action--advisor {
  background: #c9a574;
  border-color: #c9a574;
  color: #1b1407;
}
.home-hero--photo .cta-action--advisor:hover {
  background: #d8b888;
  border-color: #d8b888;
  color: #1b1407;
}
.home-hero--photo .cta-action--whatsapp,
.home-hero--photo .cta-action--browse {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(243, 239, 232, 0.55);
  color: #f3efe8;
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}
.home-hero--photo .cta-action--whatsapp:hover,
.home-hero--photo .cta-action--browse:hover {
  border-color: #c9a574;
  color: #c9a574;
  background: rgba(255, 255, 255, 0.14);
}
.home-hero__eyebrow {
  display: block;
  margin-bottom: 18px;
}
.home-hero__headline {
  margin: 0 0 18px;
  max-width: 20ch;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: clamp(40px, 6vw, 76px);
  line-height: 1.02;
  letter-spacing: var(--track-tight);
  color: var(--kamo-fg);
  text-wrap: balance;
}
.home-hero__sub {
  margin: 0 0 32px;
  max-width: 52ch;
  font-family: var(--font-sans);
  font-weight: 300;
  font-size: clamp(15px, 1.5vw, 19px);
  line-height: 1.6;
  letter-spacing: var(--track-tight);
  color: var(--kamo-fg-dim);
}
.home-hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
}
@media (max-width: 720px) {
  .home-hero {
    min-height: clamp(500px, 80svh, 760px);
    padding-top: clamp(88px, 13vh, 120px);
  }
  /* Slightly tighter tracking for the hero eyebrow on small screens so it reads as
     one un-stretched line. Scoped + specific enough to beat the global .kamo-eyebrow;
     no nowrap, so longer localized eyebrows stay free to wrap rather than overflow. */
  .home-hero .home-hero__eyebrow {
    letter-spacing: 0.2em;
  }
  .home-hero__actions .cta-action {
    flex: 1 1 100%;
    min-height: 48px;
  }
}

/* The homepage wears the standard site toolbar (.kamo-app-shell__header) + mobile
   nav so it reads as the same component as every other page. The only twist: the
   top bar is a FIXED overlay (the AppShell header is sticky/in-flow) so the
   full-bleed hero video runs to the very top behind it. */
.kamo-app-shell__header.kamo-home-header-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
}

.map-canvas {
  position: absolute;
  inset: 0;
  z-index: 1;
  overflow: hidden;
  background: var(--kamo-bg);
}

/* ===== App shell (document + future map routes) ========================== */
.kamo-app-shell--document {
  min-height: 100vh;
  height: auto;
  overflow: visible;
}
.kamo-root.kamo-app-shell--document {
  height: auto;
  min-height: 100vh;
  overflow: visible;
}
.kamo-app-shell--map {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  --explore-chrome-top: 64px;
  --explore-chrome-bottom: calc(56px + env(safe-area-inset-bottom, 0px));
}
.kamo-app-shell--map .kamo-app-shell__main {
  flex: 1;
  min-height: 0;
  overflow: hidden;
}
.kamo-app-shell__header {
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  /* Pad the notch on iPhone (viewport-fit=cover makes the inset live); the bar
     grows by the inset and its glass background fills behind the notch. */
  padding: env(safe-area-inset-top, 0px) clamp(20px, 4vw, 56px) 0;
  min-height: 64px;
  height: auto;
  background: var(--kamo-panel-bg-strong);
  border-bottom: 1px solid var(--kamo-panel-border);
  backdrop-filter: blur(14px);
  box-shadow: 0 1px 0 var(--kamo-rule), inset 0 1px 0 rgba(255, 255, 255, 0.04);
  direction: ltr;
}
.kamo-app-shell__logo {
  display: block;
  flex-shrink: 0;
  text-decoration: none;
  line-height: 0;
}
.kamo-app-shell__logo img {
  height: clamp(44px, 5vw, 60px);
  filter: brightness(0.78) saturate(1.15);
}
.kamo-app-shell__header-right {
  display: flex;
  align-items: center;
  gap: clamp(12px, 2vw, 24px);
}
.kamo-app-shell__nav {
  display: flex;
  align-items: center;
  gap: clamp(16px, 2.5vw, 32px);
}
.kamo-app-shell__nav a,
.kamo-app-shell__enquiry {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
  text-decoration: none;
  color: var(--kamo-fg-dim);
  transition: color var(--dur-fast);
  position: relative;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}
.kamo-app-shell__nav a.is-active {
  color: var(--kamo-gold-text);
}
.kamo-app-shell__nav a.is-active::after {
  content: '';
  position: absolute;
  bottom: -2px;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--kamo-gold);
  border-radius: 1px;
}
.kamo-app-shell__enquiry {
  color: var(--kamo-gold-text);
  border: 1px solid var(--kamo-gold-soft);
  border-radius: 20px;
  padding: 5px 12px;
}
.kamo-app-shell__enquiry:hover {
  background: var(--kamo-gold-faint);
}
.kamo-app-shell__main {
  position: relative;
  z-index: 1;
}
.kamo-app-shell__footer {
  padding: clamp(32px, 5vw, 48px) clamp(24px, 5vw, 64px);
  border-top: 1px solid var(--kamo-rule);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 24px;
  /* Columns share height and align to a common top edge (was: end → ragged). */
  align-items: stretch;
}
.kamo-app-shell__footer-col {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.kamo-app-shell__footer-col img {
  height: 32px;
  /* The footer logo ships with width/height attributes (512×218); without an
     explicit CSS width the 512px presentation-attribute width leaks through and
     the img box overflows the viewport on phones. Cap it so the box tracks the
     column, with the logo letterboxed left via object-fit/position. */
  width: auto;
  max-width: 100%;
  filter: brightness(0.72) saturate(1.1);
  object-fit: contain;
  object-position: left;
}
/* `button` is here for the "Cookie settings" control, which has to be a button
   (it reopens the consent banner, it doesn't navigate). Without it the control
   matched no footer rule at all and rendered at inherited body size/colour next
   to its 12px siblings (owner, 2026-07-25). */
.kamo-app-shell__footer-col > span,
.kamo-app-shell__footer-col a,
.kamo-app-shell__footer-col button {
  font-family: var(--font-sans);
  font-size: 12px;
  color: var(--kamo-fg-dim); /* fg-mute fails WCAG AA on dark (2.74:1) */
  text-decoration: none;
}
/* Strip the native button chrome so it sits flush in the link stack. */
.kamo-app-shell__footer-col button {
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  text-align: start;
  cursor: pointer;
  line-height: inherit;
}
.kamo-app-shell__footer-col a:hover,
.kamo-app-shell__footer-col button:hover {
  color: var(--kamo-gold-text);
}
/* Identity block (imprint-lite): the on-the-ground line wraps as a readable
   measure instead of one long strip across the full-width first column. */
.kamo-app-shell__footer-identity {
  max-width: 44ch;
  line-height: 1.55;
}
/* 24px+ tap targets for the footer links on touch screens. */
@media (max-width: 720px) {
  /* Two columns so the footer reads as a compact 2×2 of link groups instead of
     one long single-column stack (auto-fit collapsed to 1 col below ~408px). */
  .kamo-app-shell__footer {
    grid-template-columns: 1fr 1fr;
    gap: 26px 18px;
  }
  /* Brand + copyright span the full width and sit at the very bottom. */
  .kamo-app-shell__footer-col:first-child {
    grid-column: 1 / -1;
    order: 1;
    margin-top: 6px;
  }
  .kamo-app-shell__footer-col a,
  .kamo-app-shell__footer-col button {
    display: inline-flex;
    align-items: center;
    padding: 10px 0; /* ~32px tap height — clears the 24px AA minimum */
  }
  .kamo-app-shell__footer-col {
    gap: 2px;
  }
}
.kamo-app-shell__footer-label {
  font-family: var(--font-mono) !important;
  font-size: 9px !important;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
  color: var(--kamo-fg-dim);
  margin-bottom: 4px;
}
.kamo-app-shell__mobile-nav {
  display: none;
}
@media (max-width: 720px) {
  .kamo-app-shell__nav {
    display: none;
  }
  .kamo-app-shell__mobile-nav {
    display: flex;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 110;
    justify-content: space-around;
    align-items: center;
    gap: 4px;
    /* Tight bar: hug the bottom (only a hair of padding above the home-indicator
       safe area) so it reclaims screen height from the page. */
    padding: 4px max(12px, env(safe-area-inset-left)) calc(4px + env(safe-area-inset-bottom));
    /* Midnight, OPAQUE. Was 0.85 glass + blur, but iOS Safari renders
       backdrop-filter unreliably on fixed bars — without the blur the wash
       reads as transparency and page text bleeds through (owner's iPhone,
       2026-07-12). Over near-black surfaces opaque looks identical anyway;
       the light theme flips it linen via its own opaque rule below. */
    background: #07090d;
    border-top: 1px solid rgba(243, 239, 232, 0.1);
    direction: ltr;
  }
  .kamo-app-shell__mobile-nav a,
  .kamo-app-shell__mobile-nav button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 40px; /* tap target — comfortably above the 24px AA minimum */
    /* Sentence-case sans, not the 9px mono caps used for eyebrows and labels
       (owner, 2026-07-25). This is navigation, not a label: caps at 9px read as
       decoration and are harder to scan than the words themselves. The uppercase
       eyebrow register stays untouched everywhere else. */
    font-family: var(--font-sans);
    font-size: 11px;
    letter-spacing: normal;
    text-transform: none;
    text-decoration: none;
    color: rgba(243, 239, 232, 0.66);
    background: none;
    border: 0;
    padding: 0 10px;
    cursor: pointer;
  }
  .kamo-app-shell__mobile-nav a.is-active {
    color: #d3b07f;
  }
  /* Homepage: the tab bar is the single persistent bottom chrome and its
     Enquire is the above-the-fold primary CTA — a gold pill. Scoped to the home
     wrapper so the interior AppShell tab bar keeps its plain mono button.
     !important beats the per-theme link-colour overrides below. */
  .kamo-home .kamo-app-shell__mobile-nav button {
    background: #c9a574 !important;
    color: #0a0c10 !important;
    border-radius: 999px;
    padding: 0 16px;
  }
  .kamo-app-shell--document .kamo-app-shell__main {
    padding-bottom: var(--mobile-nav-h);
  }
  /* The AppShell footer is a sibling AFTER <main>, just ahead of the fixed tab
     bar — reserve the nav height so its last row isn't hidden behind it. (The
     home footer lives inside .kamo-home, which carries its own reserve, so this
     is scoped to the app shell and won't double up there.) */
  .kamo-app-shell .kamo-app-shell__footer {
    padding-bottom: calc(var(--mobile-nav-h) + 24px);
  }
  /* Property pages stack the sticky enquire bar (~77px) on top of the nav, so
     the footer reserves the whole stack and main drops its own nav reserve
     (the footer now owns it — avoids a doubled gap before the footer). */
  .kamo-app-shell--property .kamo-document-main {
    padding-bottom: 0;
  }
  .kamo-app-shell--property .kamo-app-shell__footer {
    padding-bottom: calc(var(--mobile-nav-h) + 92px);
  }
}

/* Country TopoJSON — crisp hairlines at any zoom */
.countries path {
  shape-rendering: geometricPrecision;
  vector-effect: non-scaling-stroke;
  paint-order: stroke fill;
}

.country-highlight-halo {
  animation: countryGlowBreath 3.2s ease-in-out infinite;
}
.country-highlight-edge {
  animation: countryGlowBreath 3.2s ease-in-out infinite;
  animation-delay: 0.15s;
}
@keyframes countryGlowBreath {
  0%,
  100% {
    opacity: 0.82;
  }
  50% {
    opacity: 1;
  }
}
@media (prefers-reduced-motion: reduce) {
  .country-highlight-halo,
  .country-highlight-edge {
    animation: none;
    opacity: 1;
  }
}
.map-dismiss-hit {
  cursor: default;
}

/* ===== Top chrome ======================================================== */
/* Logo top-left; Private Enquiries centered; language + coords top-right (LTR chrome in RTL pages). */
.top-chrome {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 12;
  min-height: calc(
    clamp(20px, 3vw, 36px) + var(--kamo-logo-clear-h)
  );
  padding: 0;
  isolation: isolate;
  direction: ltr;
  pointer-events: none;
}

/* Invisible box: measured target for flying logo in header (matches final wordmark footprint). */
.brand-header-anchor {
  position: absolute;
  left: max(16px, env(safe-area-inset-left, 0px));
  top: max(12px, env(safe-area-inset-top, 0px));
  width: var(--kamo-logo-clear-w);
  max-width: 55%;
  height: var(--kamo-logo-clear-h);
  visibility: hidden;
  pointer-events: none;
  box-sizing: border-box;
}

/* Single flying logo: hero slot ↔︎ header via transform (GPU); duration synced with App `HERO_INTRO_MS`. */
.brand-lockup-flight {
  pointer-events: none;
}

.brand-lockup-flight__hit {
  display: block;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  color: inherit;
  font: inherit;
  text-align: inherit;
  -webkit-tap-highlight-color: transparent;
}
.brand-lockup-flight__hit:disabled {
  cursor: default;
}
.brand-lockup-flight__hit:focus-visible {
  outline: 2px solid var(--kamo-gold);
  outline-offset: 3px;
}
.brand-lockup-flight__hit:hover:not(:disabled) .brand-lockup-flight__img {
  filter: drop-shadow(0 2px 14px rgba(201, 165, 116, 0.35))
    drop-shadow(0 2px 12px rgba(0, 0, 0, 0.45));
}

.brand-lockup-flight__transform {
  width: 100%;
  height: 100%;
  transform-origin: 0 0;
  transition: transform 1200ms cubic-bezier(0.4, 0, 0.2, 1);
  will-change: transform;
  backface-visibility: hidden;
}

.brand-lockup-flight__transform--instant {
  transition: none !important;
}

.brand-lockup-flight--snap .brand-lockup-flight__transform {
  transition: none !important;
  will-change: auto;
}

.brand-lockup-flight__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center center;
  isolation: isolate;
  filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.45));
}

/* The flying/transformed logo is decorative and can sit over the map mid-flight;
   never let it intercept map taps (it was blocking the market pins). The header
   logo stays clickable via .brand-lockup-flight__hit's own (untransformed) box. */
.brand-lockup-flight__transform,
.brand-lockup-flight__img {
  pointer-events: none;
}

.top-enquiry-center {
  position: absolute;
  left: 50%;
  top: clamp(20px, 3vw, 36px);
  transform: translateX(-50%);
  z-index: 2;
  direction: ltr;
  pointer-events: none;
  max-width: min(calc(100vw - var(--kamo-logo-clear-w) - 32px), 360px);
}
.top-enquiry-center > * {
  pointer-events: auto;
}

.top-meta-aside {
  position: absolute;
  top: clamp(20px, 3vw, 36px);
  right: clamp(24px, 4vw, 48px);
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  z-index: 2;
  direction: ltr;
  pointer-events: none;
}
.top-meta-aside > * {
  pointer-events: auto;
}
/* Coord readout drops onto its own line below the side-by-side toggles. */
.top-meta-aside .top-meta {
  flex-basis: 100%;
  justify-content: flex-end;
}
/* On the scrolling homepage the hero's top-right toggles must scroll away with
   the hero (as they already do >720px), not stay pinned. The ≤720px rule sets
   position:fixed; this higher-specificity override keeps them inside the hero. */
html.kamo-home-page .top-meta-aside {
  position: absolute;
}

.top-meta {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  min-width: 0;
}

.top-utility-panel {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 6px 10px;
  border-radius: var(--kamo-r-hair);
  background: var(--kamo-panel-bg-cta);
  border: 1px solid var(--kamo-rule);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

/* Language switcher — a compact button that opens a small popover menu,
   mirroring the theme toggle. The wrapper anchors the absolute menu. */
.lang-switcher {
  position: relative;
  display: inline-flex;
}
.lang-toggle {
  gap: 5px;
  color: var(--kamo-fg-dim);
  cursor: pointer;
  transition: color 0.2s ease;
}
.lang-toggle:hover {
  color: var(--kamo-gold-text);
}
.lang-switcher__code {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
}
.lang-toggle__chevron {
  font-size: 8px;
  line-height: 1;
  opacity: 0.7;
}
.lang-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 40;
  display: flex;
  flex-direction: column;
  min-width: 150px;
  padding: 4px;
  border-radius: var(--kamo-r-hair);
  background: var(--kamo-panel-bg-cta);
  border: 1px solid var(--kamo-rule);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.lang-menu__item {
  appearance: none;
  border: 0;
  background: transparent;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 10px;
  border-radius: var(--kamo-r-hair);
  cursor: pointer;
  text-align: start;
  color: var(--kamo-fg-dim);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: var(--track-body);
  transition: color 0.2s ease, background 0.2s ease;
}
.lang-menu__item:hover {
  color: var(--kamo-gold-text);
  background: rgba(201, 165, 116, 0.1);
}
.lang-menu__item--active {
  color: var(--kamo-gold-text);
  font-weight: 500;
}

/* Light/Dark theme toggle — a single sun/moon icon button */
.theme-toggle {
  appearance: none;
  cursor: pointer;
  color: var(--kamo-fg-dim);
  transition: color 0.2s ease;
  min-width: 36px;
  min-height: 34px;
}
.theme-toggle:hover {
  color: var(--kamo-gold-text);
}
.theme-toggle__icon {
  font-size: 15px;
  line-height: 1;
  display: block;
}
@media (max-width: 720px) {
  .theme-toggle {
    min-width: 44px;
    min-height: 44px;
  }
  /* Match the theme toggle's tap target so the side-by-side pair lines up. */
  .lang-toggle {
    min-height: 44px;
  }
}

html[lang='ar'] {
  --font-sans: 'Noto Naskh Arabic', 'Lora', serif;
  --font-serif: 'Amiri', Georgia, serif;
  --font-mono: 'Noto Naskh Arabic', 'Lora', serif;
  --display-size-mult: 1.12;
  --body-size: 17px;
}
html[lang='ar'] :is(h1, h2, h3, .kamo-display, .kamo-h1, .kamo-h2, .kamo-h3) {
  font-weight: 700;
  line-height: 1.75;
}
html[lang='ar'] .kamo-body {
  line-height: 1.9;
}

.enquiry-nav-btn {
  appearance: none;
  margin: 0;
  border: 0;
  background: transparent;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--kamo-fg);
  cursor: pointer;
  padding: 4px 6px;
  line-height: 1.2;
  white-space: nowrap;
  transition: color 0.2s ease;
}
.enquiry-nav-btn:hover {
  color: var(--kamo-gold-text);
}
.enquiry-nav-btn:focus-visible {
  outline: 1px solid var(--kamo-gold);
  outline-offset: 2px;
}

.coord-readout {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-wide);
  color: var(--kamo-fg-dim);
  text-align: right;
  font-variant-numeric: tabular-nums;
  transition: color 0.6s ease;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.55);
}
.coord-readout--idle { color: var(--kamo-fg-mute); }

/* ===== Hero stack (center) =============================================== */
.hero-stack {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;
  pointer-events: none;
}

.hero-copy {
  text-align: center;
  max-width: min(680px, 88vw);
  pointer-events: auto;
  padding: 0 24px;
}

.hero-intro-column {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(12px, 2vh, 24px);
  padding: clamp(18px, 3vh, 28px) clamp(22px, 4vw, 36px);
  border-radius: 3px;
  background: rgba(7, 9, 13, 0.48);
  border: 1px solid rgba(232, 228, 220, 0.08);
  box-shadow:
    0 20px 56px rgba(0, 0, 0, 0.42),
    inset 0 1px 0 rgba(255, 255, 255, 0.04);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

.hero-logo-slot {
  width: min(520px, 88vw);
  height: clamp(96px, 15vw, 150px);
  flex-shrink: 0;
}

.hero-intro-column .hero-eyebrow {
  margin-bottom: 0;
}

.hero-eyebrow {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-gold-text);
  margin-bottom: clamp(16px, 2.5vh, 28px);
  opacity: 0.96;
  text-shadow:
    0 1px 3px rgba(0, 0, 0, 0.9),
    0 0 20px rgba(0, 0, 0, 0.55),
    0 0 1px rgba(201, 165, 116, 0.45);
}

.hero-intro-column .hero-tagline {
  margin: 0;
}

.hero-tagline {
  font-family: var(--font-serif);
  font-weight: 300;
  font-style: italic;
  font-size: clamp(16px, 1.4vw, 21px);
  line-height: 1.5;
  letter-spacing: var(--track-tight);
  color: var(--kamo-fg);
  margin: clamp(28px, 4vh, 44px) auto 0;
  max-width: 58ch;
  text-wrap: balance;
  opacity: 0.97;
  text-shadow:
    0 1px 3px rgba(0, 0, 0, 0.88),
    0 2px 14px rgba(0, 0, 0, 0.45),
    0 0 1px rgba(232, 228, 220, 0.15);
}

/* Tap outside city detail panel → return to network overview */
.market-detail-backdrop {
  position: fixed;
  inset: 0;
  z-index: 9;
  margin: 0;
  padding: 0;
  border: 0;
  background: rgba(4, 6, 10, 0.12);
  cursor: default;
  pointer-events: none;
  opacity: 0;
  transition: opacity 380ms cubic-bezier(0.22, 1, 0.36, 1);
}
.market-detail-backdrop--visible {
  opacity: 1;
}

/* ===== Per-market label (lower left) ===================================== */
.market-label-slot {
  position: absolute;
  left: clamp(24px, 5vw, 56px);
  bottom: clamp(80px, 12vh, 130px);
  z-index: 10;
}
.market-label {
  position: relative;
  z-index: 1;
  pointer-events: auto;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 240px;
  max-width: min(380px, 92vw);
  border-inline-start: 1px solid var(--kamo-gold-soft);
  padding: 12px 14px 12px 18px;
  border-radius: var(--kamo-r-hair);
  background: rgba(7, 9, 13, 0.52);
  border-top: none;
  border-inline-end: none;
  border-bottom: none;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.2);
  backdrop-filter: blur(var(--kamo-panel-blur));
  -webkit-backdrop-filter: blur(var(--kamo-panel-blur));
}
.market-label--detail {
  max-height: min(52vh, 420px);
  min-height: 0;
}
.market-label--exiting {
  opacity: 0;
  transform: translateY(8px);
  pointer-events: none;
  transition:
    opacity 380ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 380ms cubic-bezier(0.22, 1, 0.36, 1);
}
.ml-header {
  flex-shrink: 0;
}
.ml-tour-eyebrow {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-fg-mute);
  margin: 0 0 6px;
}
.market-label--tour .ml-header {
  animation: tourLabelContentIn 380ms cubic-bezier(0.45, 0.05, 0.55, 0.95);
}
@keyframes tourLabelContentIn {
  from {
    opacity: 0.35;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
.ml-index {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-label);
  color: var(--kamo-gold-text);
  text-transform: uppercase;
  margin-bottom: 4px;
}
.ml-name {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: clamp(36px, 4.5vw, 60px);
  line-height: 1;
  letter-spacing: var(--track-tight);
  text-transform: capitalize;
  text-shadow:
    0 1px 3px rgba(0, 0, 0, 0.55),
    0 0 1px rgba(0, 0, 0, 0.65);
}
.ml-region {
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: 12px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-fg-dim);
  margin-top: 4px;
}
.ml-coord {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-wide);
  color: var(--kamo-fg-mute);
  margin-top: 8px;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
}
.ml-summary {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: 14px;
  line-height: 1.45;
  color: var(--kamo-fg);
  margin: 0 0 8px;
  opacity: 0.92;
}

.ml-corridor-guide {
  margin: 0 0 12px;
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
}

.ml-corridor-guide a {
  color: rgba(201, 165, 116, 0.55);
  text-decoration: none;
  transition: color 0.2s ease;
}

.ml-corridor-guide a:hover {
  color: var(--kamo-gold-text);
}

.ml-corridor-guide a:focus-visible {
  outline: 1px solid var(--kamo-gold);
  outline-offset: 3px;
}
.ml-highlights {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.ml-highlights li {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-fg-dim);
  padding-left: 10px;
  position: relative;
}
.ml-highlights li::before {
  content: "·";
  position: absolute;
  left: 0;
  color: var(--kamo-gold-soft);
}
.ml-detail-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding-right: 4px;
  margin-right: -2px;
  animation: mlDetailIn 520ms cubic-bezier(0.22, 1, 0.36, 1) forwards;
  opacity: 0;
  scrollbar-width: thin;
  scrollbar-color: rgba(201, 165, 116, 0.35) transparent;
}
.ml-detail-scroll::-webkit-scrollbar {
  width: 4px;
}
.ml-detail-scroll::-webkit-scrollbar-thumb {
  background: rgba(201, 165, 116, 0.35);
  border-radius: var(--kamo-r-hair);
}
@keyframes mlDetailIn {
  to { opacity: 1; }
}
.ml-stats {
  margin: 0 0 8px;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px 10px;
}
.ml-stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 6px 0 0;
  border-top: 1px solid rgba(201, 165, 116, 0.1);
}
.ml-stat:nth-child(-n + 2) {
  padding-top: 0;
  border-top: none;
}
.ml-stat-label {
  font-family: var(--font-mono);
  font-size: 8.5px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--kamo-fg-dim);
  line-height: 1.3;
}
/* Values stay editorial (Prata) — matches the below-fold market figures and
   keeps a clear label / serif-value distinction. Lining + tabular figures
   so the data aligns cleanly in the 2-col card. */
.ml-stat-value {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: 16px;
  line-height: 1.2;
  letter-spacing: var(--track-tight);
  color: var(--kamo-gold-text);
  font-variant-numeric: lining-nums tabular-nums;
}
.ml-stat-period {
  font-family: var(--font-mono);
  font-size: 7.5px;
  letter-spacing: var(--track-wide);
  color: var(--kamo-fg-dim);
  font-weight: 400;
}
.ml-sources {
  font-family: var(--font-mono);
  font-size: 7.5px;
  letter-spacing: var(--track-wide);
  line-height: 1.4;
  color: var(--kamo-fg-mute);
  margin: 0 0 8px;
  opacity: 0.85;
}
/* ===== Network manifest (right side, final state) ======================== */
.manifest-slot {
  position: absolute;
  right: clamp(24px, 5vw, 56px);
  top: 50%;
  transform: translateY(-50%);
  z-index: 10;
}
.manifest-slot--exit-prep {
  opacity: 0;
  pointer-events: none;
}
.manifest--dismissing .manifest-list li {
  transition: opacity 200ms ease !important;
}
.manifest {
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-width: min(260px, 88vw);
  max-width: min(300px, 42vw);
  padding: clamp(14px, 2vw, 20px) clamp(16px, 2.2vw, 22px);
  border-radius: var(--kamo-r-hair);
  background: var(--kamo-panel-bg-strong);
  border: 1px solid var(--kamo-panel-border);
  box-shadow: var(--kamo-panel-shadow);
  backdrop-filter: blur(13px);
  -webkit-backdrop-filter: blur(13px);
}
.manifest-eyebrow {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-gold-text);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
}
.manifest-hint {
  font-family: var(--font-mono);
  font-size: 8.5px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-fg-mute);
  margin: -8px 0 0;
}
.manifest-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.manifest-list li {
  padding-bottom: 12px;
  border-bottom: 1px solid var(--kamo-rule);
}
.manifest-row {
  appearance: none;
  display: grid;
  grid-template-columns: 32px 1fr auto;
  align-items: baseline;
  gap: 14px;
  width: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  text-align: left;
  color: inherit;
  cursor: pointer;
  transition:
    opacity 0.28s ease,
    border-color 0.28s ease;
  border-inline-start: 1px solid transparent;
  padding-inline-start: 6px;
  margin-inline-start: -6px;
}
.manifest-row:hover {
  opacity: 0.9;
  border-inline-start-color: var(--kamo-gold-soft);
}
.manifest-num {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-wide);
  color: var(--kamo-fg-mute);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}
.manifest-name {
  font-family: var(--font-serif);
  font-size: 22px;
  font-weight: 300;
  letter-spacing: var(--track-body);
  color: var(--kamo-fg);
  text-shadow:
    0 1px 2px rgba(0, 0, 0, 0.65),
    0 0 1px rgba(0, 0, 0, 0.85);
}
.manifest-region {
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-fg-dim);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
}

/* Home network manifest card only — scoped so the explore sidebar's reuse of
   .manifest-row/.manifest-num/.manifest-name (under .listings-panel__markets,
   never inside .manifest) is unaffected. Lift the counter off the failing
   fg-mute, and replace the backwards dimming hover with a clear gold reveal. */
.manifest .manifest-num {
  color: var(--kamo-fg-dim);
  font-variant-numeric: tabular-nums;
}
.manifest .manifest-name,
.manifest .manifest-num {
  transition: color 0.25s ease;
}
.manifest .manifest-row:hover {
  opacity: 1;
  border-inline-start-color: var(--kamo-gold);
}
.manifest .manifest-row:hover .manifest-name {
  color: var(--kamo-gold-text);
}
.manifest .manifest-row:hover .manifest-num {
  color: var(--kamo-gold-text);
}

/* ===== Private enquiries (modal) ========================================= */
.enquiry-modal {
  position: fixed;
  inset: 0;
  /* Above ALL mobile bottom-chrome — nav (110), consent banner (130) — so the
     bottom-sheet form is never occluded by the tab bar or cookie strip. Matches
     the watchlist (600)/doc-gate (500) dialog layer. */
  z-index: 600;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: 0;
}

.enquiry-modal-backdrop {
  position: absolute;
  inset: 0;
  margin: 0;
  padding: 0;
  border: 0;
  background: rgba(7, 9, 13, 0.78);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  cursor: pointer;
}

.enquiry-modal-panel {
  position: relative;
  z-index: 1;
  width: 100%;
  max-height: min(92dvh, 92vh);
  overflow-x: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-gutter: stable;
  scrollbar-width: thin;
  scrollbar-color: rgba(201, 165, 116, 0.38) transparent;
  border-radius: 3px 3px 0 0;
  animation: enquirySheetIn 0.42s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.enquiry-modal-panel::-webkit-scrollbar {
  width: 4px;
}
.enquiry-modal-panel::-webkit-scrollbar-track {
  background: transparent;
}
.enquiry-modal-panel::-webkit-scrollbar-thumb {
  background: rgba(201, 165, 116, 0.32);
  border-radius: var(--kamo-r-hair);
}
.enquiry-modal-panel::-webkit-scrollbar-thumb:hover {
  background: rgba(201, 165, 116, 0.5);
}

@keyframes enquirySheetIn {
  from {
    opacity: 0;
    transform: translateY(24px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@media (min-width: 721px) { /* desktopMin: calc(var(--kamo-bp-mobile) + 1px) */
  .enquiry-modal {
    align-items: center;
    padding: max(24px, env(safe-area-inset-top, 0px))
      max(24px, env(safe-area-inset-right, 0px))
      max(24px, env(safe-area-inset-bottom, 0px))
      max(24px, env(safe-area-inset-left, 0px));
  }
  .enquiry-modal-panel {
    width: min(440px, 100%);
    max-height: min(88dvh, 88vh);
    border-radius: var(--kamo-r-hair);
    animation-name: enquiryModalIn;
  }
}

@keyframes enquiryModalIn {
  from {
    opacity: 0;
    transform: translateY(12px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

.enquiry-block {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: clamp(16px, 2.5vw, 20px) clamp(16px, 2.2vw, 22px)
    max(18px, env(safe-area-inset-bottom, 0px));
  border-radius: inherit;
  background: var(--kamo-panel-bg-strong);
  border: 1px solid var(--kamo-panel-border);
  box-shadow: var(--kamo-panel-shadow);
  backdrop-filter: blur(13px);
  -webkit-backdrop-filter: blur(13px);
}

.enquiry-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

.enquiry-close {
  appearance: none;
  flex-shrink: 0;
  /* 44×44 tap target (Apple min); the glyph stays visually small. */
  width: 44px;
  height: 44px;
  margin: -10px -12px 0 0;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: var(--kamo-r-hair);
  background: transparent;
  color: var(--kamo-fg-dim);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  transition: color 0.2s ease, background 0.2s ease;
}
.enquiry-close:hover {
  color: var(--kamo-gold-text);
  background: rgba(232, 228, 220, 0.06);
}
.enquiry-close:focus-visible {
  outline: 1px solid var(--kamo-gold);
  outline-offset: 2px;
}

/* City detail: dismiss inside panel (mobile only — see @media below) */
.city-detail-close {
  display: none;
}

.enquiry-contact {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 0 2px;
  margin: 0;
  border-top: 1px solid rgba(232, 228, 220, 0.1);
}
.enquiry-contact a {
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 300;
  letter-spacing: var(--track-body);
  color: var(--kamo-fg-dim);
  text-decoration: none;
  transition: color 0.2s ease;
}
.enquiry-contact a:hover {
  color: var(--kamo-gold-text);
}
.enquiry-contact a:focus-visible {
  outline: 1px solid var(--kamo-gold);
  outline-offset: 2px;
}

.enquiry-eyebrow {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-gold-text);
  margin: 0;
  font-weight: 400;
}

.enquiry-helper {
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 300;
  line-height: 1.45;
  letter-spacing: var(--track-body);
  color: var(--kamo-fg-dim);
  margin: 0;
}

.enquiry-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.enquiry-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 0;
}

.enquiry-fieldset {
  border: 0;
  padding: 0;
  margin: 0;
  min-width: 0;
}

.enquiry-label {
  font-family: var(--font-mono);
  /* Readability floor on phones — tiny luxury caps hurt conversion. */
  font-size: clamp(10px, 2.5vw, 11px);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-fg-mute);
}

.enquiry-fieldset .enquiry-label {
  margin-bottom: 2px;
}

.enquiry-input,
.enquiry-textarea {
  appearance: none;
  width: 100%;
  background: rgba(232, 228, 220, 0.04);
  border: 1px solid rgba(232, 228, 220, 0.12);
  border-radius: var(--kamo-r-hair);
  color: var(--kamo-fg);
  font-family: var(--font-sans);
  font-weight: 300;
  font-size: 14px;
  letter-spacing: var(--track-body);
  padding: 10px 11px;
  outline: none;
  transition: border-color 0.25s ease;
}
.enquiry-input:focus,
.enquiry-textarea:focus {
  border-color: var(--kamo-gold-soft);
}
.enquiry-textarea {
  resize: vertical;
  min-height: 88px;
  line-height: 1.45;
}

.enquiry-radio-group {
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.enquiry-radio {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 300;
  line-height: 1.35;
  color: var(--kamo-fg-dim);
  cursor: pointer;
}
.enquiry-radio input {
  margin-top: 3px;
  accent-color: var(--kamo-gold);
  flex-shrink: 0;
}

.enquiry-submit {
  appearance: none;
  align-self: flex-start;
  margin-top: 4px;
  padding: 12px 20px;
  border: 1px solid var(--kamo-gold-soft);
  border-radius: var(--kamo-r-hair);
  background: transparent;
  color: var(--kamo-gold-text);
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  cursor: pointer;
  transition: opacity 0.25s ease, background 0.25s ease;
}
.enquiry-submit:hover:not(:disabled) {
  background: rgba(201, 165, 116, 0.08);
  opacity: 0.9;
}
.enquiry-submit:disabled {
  opacity: 0.45;
  cursor: progress;
}

.enquiry-privacy {
  font-family: var(--font-mono);
  /* Readability floor — 8px legal text was unreadable on phones. */
  font-size: clamp(10px, 2.5vw, 10.5px);
  letter-spacing: var(--track-wide);
  line-height: 1.45;
  color: var(--kamo-fg-mute);
  margin: 0;
  opacity: 0.85;
}
.enquiry-privacy a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.enquiry-privacy a:focus-visible {
  outline: 1px solid var(--kamo-gold);
  outline-offset: 2px;
}
.enquiry-consent {
  margin-top: 0.15rem;
}

.enquiry-done {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 8px 0 4px;
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 16px;
  line-height: 1.4;
  color: var(--kamo-fg);
  margin: 0;
}
.enquiry-done p {
  margin: 0;
}
.enquiry-done-tick {
  color: var(--kamo-gold-text);
  font-size: 9px;
  flex-shrink: 0;
  margin-top: 4px;
}

.enquiry-error {
  font-family: var(--font-sans);
  font-size: 12px;
  color: #e88a8a;
  margin: 0;
}

/* ── Guided brief (adaptive enquiry flow) ────────────────────────────────
   The multi-step brief that is now the default content of the enquiry modal
   (src/enquiry/GuidedBrief.tsx). It reuses the enquiry-* form language and
   the shared selection chips; only the flow chrome below is new. Logical
   properties + flex-start anchoring so everything flows correctly in RTL. */
.brief-progress {
  display: flex; /* flex-start anchors the fill to the reading edge in RTL */
  height: 2px;
  background: var(--kamo-rule);
  border-radius: 1px;
  overflow: hidden;
}
.brief-progress__fill {
  height: 100%;
  background: var(--kamo-gold);
  transition: width 0.4s var(--ease-standard);
}
.brief-step-label {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--kamo-fg-mute);
}
/* The per-step question reuses the enquiry headline serif, one size down so a
   question + chips + nav fit a 375px viewport without inner scrolling. */
.brief-question {
  font-size: clamp(20px, 2.6vw, 26px);
  outline: none; /* focus target on step change; the modal provides context */
}
.brief-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
}
.brief-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-block-start: 4px;
}
.brief-text-btn {
  appearance: none;
  background: none;
  border: 0;
  padding: 4px 0;
  cursor: pointer;
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 300;
  letter-spacing: var(--track-body);
  color: var(--kamo-fg-dim);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.brief-text-btn:hover {
  color: var(--kamo-fg);
}
.brief-text-btn:focus-visible {
  outline: 1px solid var(--kamo-gold);
  outline-offset: 2px;
}
/* Quiet escape hatch to the classic single-screen form */
.brief-switch {
  align-self: center;
  margin-block-start: 2px;
  opacity: 0.75;
}
.brief-summary {
  margin: 0;
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 300;
  font-size: 14px;
  line-height: 1.6;
  color: var(--kamo-fg);
}
.brief-actions {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 12px;
  padding-block-start: 2px;
}

/* ── Property-specific enquiry form ──────────────────────────────────────── */
.property-enquiry-title {
  margin: 4px 0 0;
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 15px;
  line-height: 1.3;
  color: var(--kamo-fg-dim);
}

.enquiry-label-optional {
  /* Scales with the parent label (which now has a 10px floor). */
  font-size: 0.9em;
  letter-spacing: var(--track-wide);
  opacity: 0.7;
  text-transform: uppercase;
  font-family: var(--font-mono);
}

/* ===== CTA block (bottom-left, final state) ============================== */
.cta-slot {
  position: absolute;
  left: clamp(24px, 5vw, 56px);
  bottom: calc(clamp(80px, 12vh, 120px) + env(safe-area-inset-bottom, 0px));
  z-index: 11;
  max-width: min(440px, 86vw);
  pointer-events: none;
  transition:
    left var(--kamo-cta-move-ms, 520ms) cubic-bezier(0.22, 1, 0.36, 1),
    right var(--kamo-cta-move-ms, 520ms) cubic-bezier(0.22, 1, 0.36, 1),
    bottom var(--kamo-cta-move-ms, 520ms) cubic-bezier(0.22, 1, 0.36, 1),
    top var(--kamo-cta-move-ms, 520ms) cubic-bezier(0.22, 1, 0.36, 1),
    transform var(--kamo-cta-move-ms, 520ms) cubic-bezier(0.22, 1, 0.36, 1),
    width var(--kamo-cta-move-ms, 520ms) cubic-bezier(0.22, 1, 0.36, 1),
    max-width var(--kamo-cta-move-ms, 520ms) cubic-bezier(0.22, 1, 0.36, 1);
}
.cta-slot > * {
  pointer-events: auto;
}

/* City detail: panel lower-left — CTA on the right (class applied when panel ready) */
.cta-slot--city-detail {
  left: auto;
  right: clamp(24px, 5vw, 56px);
  transition-delay: 0.15s;
}

.cta-block {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px 18px;
  border-radius: var(--kamo-r-hair);
  background: var(--kamo-panel-bg-cta);
  border: 1px solid var(--kamo-panel-border-cta);
  box-shadow: var(--kamo-panel-shadow-cta);
  backdrop-filter: blur(var(--kamo-panel-blur));
  -webkit-backdrop-filter: blur(var(--kamo-panel-blur));
  position: relative;
}

/* Network stage: map safe area for camera bias (0 = full viewport; overridden on tablet/mobile). */
.kamo-root--network {
  --map-inset-top: 0px;
  --map-inset-bottom: 0px;
}

/* Final “network” stage: subtle gold hairline sweep — position only (no opacity pulse → avoids post-transition flashing). */
.kamo-root--network .cta-block::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 1px;
  pointer-events: none;
  background: linear-gradient(
    90deg,
    transparent 0%,
    transparent 38%,
    rgba(201, 165, 116, 0.55) 50%,
    transparent 62%,
    transparent 100%
  );
  background-size: 55% 100%;
  background-repeat: no-repeat;
  opacity: 0.52;
  animation: kamoCtaHairlineSweep 14s ease-in-out infinite;
}

.kamo-root--network .brand-lockup-flight__img {
  animation: kamoLogoIdleGlow 16s ease-in-out infinite;
}

@keyframes kamoCtaHairlineSweep {
  0%, 100% { background-position: -40% 0; }
  50% { background-position: 140% 0; }
}

@keyframes kamoLogoIdleGlow {
  0%, 100% {
    filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.45));
  }
  50% {
    filter:
      drop-shadow(0 2px 13px rgba(0, 0, 0, 0.48))
      drop-shadow(0 0 22px rgba(201, 165, 116, 0.06));
  }
}
.cta-eyebrow {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-gold-text);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
}

.cta-about {
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 300;
  line-height: 1.5;
  letter-spacing: var(--track-body);
  color: rgba(232, 228, 220, 0.92);
  margin: 0;
  max-width: 42ch;
}

.cta-helper {
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 300;
  line-height: 1.45;
  letter-spacing: var(--track-body);
  color: var(--kamo-fg-dim);
  margin: 0;
  max-width: 42ch;
}

.cta-form {
  display: flex;
  align-items: stretch;
  gap: 0;
  border-bottom: 1px solid var(--kamo-fg-dim);
  transition: border-color 0.3s ease;
}
.cta-form:focus-within { border-color: var(--kamo-gold); }

.cta-input {
  flex: 1;
  appearance: none;
  background: transparent;
  border: 0;
  color: var(--kamo-fg);
  font-family: var(--font-sans);
  font-weight: 300;
  font-size: 16px;
  letter-spacing: var(--track-body);
  padding: 12px 4px;
  outline: none;
  min-width: 0;
}
.cta-input::placeholder { color: var(--kamo-fg-dim); font-weight: 300; }
.cta-input.is-error { color: #e88a8a; }

.cta-btn {
  appearance: none;
  background: transparent;
  border: 0;
  color: var(--kamo-gold-text);
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 11px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  padding: 12px 4px 12px 24px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  transition: opacity 0.25s ease, gap 0.25s ease;
}
.cta-btn:hover { gap: 16px; opacity: 0.85; }
.cta-btn:disabled { opacity: 0.4; cursor: progress; }

.cta-done {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 0;
  border-bottom: 1px solid var(--kamo-gold-soft);
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 17px;
  color: var(--kamo-fg);
}
.cta-done-tick {
  color: var(--kamo-gold-text);
  font-size: 9px;
}

/* ===== Stage indicator (top-right, while zooming markets) ================= */
.stage-indicator {
  position: absolute;
  top: 50%;
  right: clamp(24px, 5vw, 56px);
  transform: translateY(-50%);
  display: none; /* shown only when network manifest absent — see below */
  z-index: 10;
}

/* ===== Bottom chrome ===================================================== */
.bottom-chrome {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: clamp(20px, 3vw, 32px);
  padding-right: max(clamp(24px, 4vw, 48px), env(safe-area-inset-right, 0px));
  padding-left: max(clamp(24px, 4vw, 48px), env(safe-area-inset-left, 0px));
  padding-bottom: max(clamp(20px, 3vw, 32px), env(safe-area-inset-bottom, 0px));
  pointer-events: none;
}

.footer-text {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-fg-mute);
  pointer-events: auto;
}

.scrub-controls {
  display: flex;
  align-items: center;
  gap: 18px;
  pointer-events: auto;
  margin-left: auto;
}
.scrub-btn {
  appearance: none;
  background: transparent;
  border: 0;
  color: var(--kamo-fg-dim);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 0;
  transition: color 0.25s ease;
}
.scrub-btn:hover { color: var(--kamo-gold-text); }

.scrub-btn--skip {
  font-size: 9px;
  letter-spacing: var(--track-label);
  color: var(--kamo-fg-mute);
  opacity: 0.65;
  padding: 4px 0;
}
.scrub-btn--skip:hover {
  opacity: 1;
  color: var(--kamo-gold-text);
}

.scrub-btn--replay,
.scrub-btn--back {
  color: var(--kamo-fg-mute);
  opacity: 0.55;
  padding: 6px 0;
}
.scrub-btn--replay:hover,
.scrub-btn--back:hover {
  opacity: 1;
  color: var(--kamo-gold-text);
}

.scrub-dots {
  display: flex;
  align-items: center;
  gap: 4px;
}
/* Thin visible segment, but a full 44×44px hit area (content-box + padding) so
   the timeline is reachable; resting 2px/fg-dim makes the stages discoverable
   to a first-time visitor without competing with the gold active segment. */
.scrub-dot {
  appearance: none;
  box-sizing: content-box;
  width: 24px;
  height: 2px;
  border: 0;
  background: var(--kamo-fg-dim);
  padding: 21px 10px;
  background-clip: content-box;
  cursor: pointer;
  transition: background 0.25s ease, width 0.25s ease;
}
/* background-COLOR (not the shorthand) so background-clip: content-box survives —
   otherwise the gold fills the 44px padded hit box and the segment reads as a block. */
.scrub-dot.is-active { background-color: var(--kamo-gold); width: 34px; }
.scrub-dot:hover:not(.is-active) { background-color: var(--kamo-fg); }

/* Short wide viewports (e.g. 1280×720): same top-manifest / bottom-CTA network band as tablet. */
@media (max-height: 740px) and (min-width: 721px) {
  .kamo-root--network {
    --network-logo-clear: max(
      62px,
      calc(env(safe-area-inset-top, 0px) + clamp(42px, 10vw, 58px) + 10px)
    );
    --network-manifest-top: calc(var(--network-logo-clear) + 22px);
    --network-manifest-max-h: min(32vh, 220px);
    --network-ui-bottom: calc(80px + env(safe-area-inset-bottom, 0px));
    --network-cta-stack-h: 168px;
    --map-inset-top: calc(
      var(--network-manifest-top) + var(--network-manifest-max-h) + 14px
    );
    --map-inset-bottom: calc(
      var(--network-ui-bottom) + var(--network-cta-stack-h) + 20px
    );
  }
  .kamo-root--network .manifest-slot {
    top: var(--network-manifest-top);
    bottom: auto;
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    width: min(340px, calc(100vw - 32px));
    max-width: min(340px, calc(100vw - 32px));
  }
  .kamo-root--network .manifest {
    max-height: var(--network-manifest-max-h);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }
  .kamo-root--network .cta-slot {
    left: 50%;
    right: auto;
    bottom: var(--network-ui-bottom);
    transform: translateX(-50%);
    width: min(340px, calc(100vw - 32px));
    max-width: min(340px, calc(100vw - 32px));
  }
}

/* ===== Responsive — tablet ============================================== */
@media (max-width: 960px) and (min-width: 721px) {
  :root {
    --kamo-logo-clear-w: min(228px, 38vw);
    --kamo-logo-clear-h: clamp(42px, 7vw, 54px);
  }

  .top-chrome {
    padding: 14px 20px;
    gap: 10px;
  }

  .top-enquiry-center {
    max-width: min(calc(100vw - var(--kamo-logo-clear-w) - 28px), 320px);
  }

  .top-meta-aside {
    top: 14px;
    right: 20px;
  }

  .top-utility-panel {
    padding: 5px 8px;
  }

  .enquiry-nav-btn {
    font-size: 9px;
    letter-spacing: var(--track-wide);
    padding: 3px 5px;
  }

  .coord-readout {
    font-size: 8px;
    letter-spacing: var(--track-wide);
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 6px 14px;
    max-width: 100%;
  }
}

@media (max-width: 960px) {
  /* Network: logo → manifest (top) → map → CTA (bottom) — same band as mobile */
  .kamo-root--network {
    --network-logo-clear: max(
      62px,
      calc(env(safe-area-inset-top, 0px) + clamp(42px, 10vw, 58px) + 10px)
    );
    /* +38 (was +22) so the panel header clears the stacked theme/language chrome. */
    --network-manifest-top: calc(var(--network-logo-clear) + 38px);
    /* Fit all four markets (≈345px of content) without the 4th clipping/scrolling
       out; capped so it still clears the bottom CTA stack. */
    --network-manifest-max-h: min(46vh, 348px);
    --network-ui-bottom: calc(80px + env(safe-area-inset-bottom, 0px));
    --network-cta-stack-h: 168px;
    --map-inset-top: calc(
      var(--network-manifest-top) + var(--network-manifest-max-h) + 14px
    );
    --map-inset-bottom: calc(
      var(--network-ui-bottom) + var(--network-cta-stack-h) + 20px
    );
  }

  .kamo-root--network .map-canvas::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 2;
    background: linear-gradient(
      to bottom,
      rgba(7, 9, 13, 0.48) 0%,
      transparent 14%,
      transparent 54%,
      rgba(7, 9, 13, 0.58) 100%
    );
  }

  .kamo-root--network .manifest-slot {
    top: var(--network-manifest-top);
    bottom: auto;
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    width: min(340px, calc(100vw - 32px));
    max-width: min(340px, calc(100vw - 32px));
    margin: 0;
  }
  .kamo-root--network .manifest {
    min-width: 0;
    gap: 10px;
    max-width: none;
    padding: 12px 14px;
    max-height: var(--network-manifest-max-h);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
    scrollbar-color: rgba(201, 165, 116, 0.35) transparent;
  }
  .kamo-root--network .cta-slot {
    left: 50%;
    right: auto;
    bottom: var(--network-ui-bottom);
    transform: translateX(-50%);
    width: min(340px, calc(100vw - 32px));
    max-width: min(340px, calc(100vw - 32px));
  }

  /* Stacked email CTA: brand → identity → helper → form */
  .kamo-root--network .cta-slot .cta-block,
  .kamo-root--city-detail .cta-slot--city-detail .cta-block {
    gap: 0;
    padding: 12px 14px;
  }
  .kamo-root--network .cta-slot .cta-eyebrow,
  .kamo-root--city-detail .cta-slot--city-detail .cta-eyebrow {
    margin: 0;
    font-size: 10px;
    font-weight: 500;
    letter-spacing: var(--track-label);
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
  }
  .kamo-root--network .cta-slot .cta-about,
  .kamo-root--city-detail .cta-slot--city-detail .cta-about {
    margin: 6px 0 0;
    font-family: var(--font-serif);
    font-size: 12px;
    font-weight: 300;
    line-height: 1.45;
    max-width: none;
  }
  .kamo-root--network .cta-slot .cta-helper,
  .kamo-root--city-detail .cta-slot--city-detail .cta-helper {
    margin: 10px 0 0;
    font-size: 10px;
    line-height: 1.35;
    max-width: none;
    color: rgba(232, 228, 220, 0.72);
  }
  .kamo-root--network .cta-slot .cta-form,
  .kamo-root--city-detail .cta-slot--city-detail .cta-form {
    margin: 12px 0 0;
    padding-top: 10px;
    border-top: 1px solid var(--kamo-rule);
    border-bottom: 1px solid var(--kamo-fg-mute);
  }
  .kamo-root--network .cta-slot .cta-input,
  .kamo-root--city-detail .cta-slot--city-detail .cta-input {
    font-size: 16px;
    padding: 10px 2px;
    min-height: 44px;
  }
  .kamo-root--network .cta-slot .cta-btn,
  .kamo-root--city-detail .cta-slot--city-detail .cta-btn {
    padding: 10px 2px 10px 12px;
    font-size: 9px;
    letter-spacing: var(--track-label);
    min-height: 44px;
    gap: 8px;
  }
  .kamo-root--network .cta-slot .cta-btn svg,
  .kamo-root--city-detail .cta-slot--city-detail .cta-btn svg {
    width: 11px;
    height: 8px;
  }
  .kamo-root--network .cta-slot .cta-privacy,
  .kamo-root--city-detail .cta-slot--city-detail .cta-privacy {
    margin: 8px 0 0;
    font-size: 8px;
  }
  .kamo-root--network .cta-slot .cta-consent,
  .kamo-root--city-detail .cta-slot--city-detail .cta-consent {
    margin: 8px 0 0;
    gap: 8px;
  }
  .kamo-root--network .cta-slot .cta-consent label,
  .kamo-root--city-detail .cta-slot--city-detail .cta-consent label {
    font-size: 10px;
    line-height: 1.35;
  }
  .kamo-root--network .cta-slot .cta-error-msg,
  .kamo-root--city-detail .cta-slot--city-detail .cta-error-msg {
    margin: 6px 0 0;
    font-size: 10px;
  }
  .kamo-root--network .cta-slot .cta-done,
  .kamo-root--city-detail .cta-slot--city-detail .cta-done {
    margin: 12px 0 0;
    padding-top: 10px;
    border-top: 1px solid var(--kamo-rule);
    font-size: 14px;
    padding-bottom: 8px;
    gap: 10px;
  }

  /* Stacked panels: center headlines; list rows and form stay left */
  .kamo-root--network .manifest-eyebrow,
  .kamo-root--network .manifest-hint {
    text-align: center;
  }
  .kamo-root--network .cta-slot .cta-eyebrow,
  .kamo-root--network .cta-slot .cta-about,
  .kamo-root--network .cta-slot .cta-helper,
  .kamo-root--city-detail .cta-slot--city-detail .cta-eyebrow,
  .kamo-root--city-detail .cta-slot--city-detail .cta-about,
  .kamo-root--city-detail .cta-slot--city-detail .cta-helper,
  .kamo-root--network .cta-slot .cta-privacy,
  .kamo-root--city-detail .cta-slot--city-detail .cta-privacy,
  .kamo-root--network .cta-slot .cta-consent label,
  .kamo-root--city-detail .cta-slot--city-detail .cta-consent label,
  .kamo-root--network .cta-slot .cta-error-msg,
  .kamo-root--city-detail .cta-slot--city-detail .cta-error-msg {
    text-align: center;
  }
  .kamo-root--network .cta-slot .cta-done,
  .kamo-root--city-detail .cta-slot--city-detail .cta-done {
    justify-content: center;
  }
}

/* ── Map-forward home ───────────────────────────────────────────────────────
   Keep the home (network) CTA compact so the interactive map + market pins are
   the hero and the camera can frame the pins clear of (and tappable above) it.
   The heavy email signup / sub / legal are hidden on the home view only — they
   stay available via the enquiry flow and on the city-detail CTA. */
.kamo-root--network .cta-slot .cta-about,
.kamo-root--network .cta-slot .cta-form,
.kamo-root--network .cta-slot .cta-helper,
.kamo-root--network .cta-slot .cta-privacy,
.kamo-root--network .cta-slot .cta-consent,
.kamo-root--network .cta-slot .cta-error-msg {
  display: none;
}
.kamo-root--network .cta-block--concierge {
  gap: 10px;
  padding: 14px 16px;
}
.kamo-root--network .concierge-headline {
  font-size: clamp(19px, 2.3vw, 26px);
  margin: 2px 0 2px;
}
.kamo-root--network .cta-actions--concierge {
  margin: 4px 0 0;
}

/* Tablet (721–960px): compact panel typography — phone-like scale in 340px boxes */
@media (max-width: 960px) and (min-width: 721px) {
  .kamo-root--network {
    --network-manifest-max-h: min(38vh, 280px);
  }

  /* Markets in Focus */
  .kamo-root--network .manifest-hint {
    margin: -4px 0 0;
  }
  .kamo-root--network .manifest-eyebrow {
    font-size: 9px;
    letter-spacing: var(--track-label);
  }
  .kamo-root--network .manifest-list {
    gap: 8px;
  }
  .kamo-root--network .manifest-list li {
    padding-bottom: 8px;
  }
  .kamo-root--network .manifest-row {
    grid-template-columns: 24px 1fr auto;
    gap: 10px;
  }
  .kamo-root--network .manifest-name {
    font-size: 16px;
  }
  .kamo-root--network .manifest-num {
    font-size: 9px;
  }
  .kamo-root--network .manifest-region {
    font-size: 8.5px;
    letter-spacing: var(--track-label);
  }
}

/* Short landscape phones (e.g. 844×390): tighten vertical band so manifest and CTA clear. */
@media (max-width: 960px) and (max-height: 640px) {
  .kamo-root--network {
    --network-manifest-max-h: min(22vh, 100px);
    --network-cta-stack-h: 188px;
    --network-ui-bottom: calc(56px + env(safe-area-inset-bottom, 0px));
  }
  .kamo-root--network .cta-about {
    -webkit-line-clamp: 1;
    line-clamp: 1;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .kamo-root--network .cta-helper {
    -webkit-line-clamp: 1;
    line-clamp: 1;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
}

/* Tablet city detail: stacked layout (same band as mobile, roomier panel). */
@media (max-width: 960px) and (min-width: 721px) {
  .kamo-root--city-detail {
    --city-detail-logo-clear: max(
      68px,
      calc(env(safe-area-inset-top, 0px) + 58px + 12px)
    );
    --city-detail-cta-top: calc(var(--city-detail-logo-clear) + 10px);
    --city-detail-cta-stack-h: 124px;
    --city-detail-ui-bottom: calc(80px + env(safe-area-inset-bottom, 0px));
    --city-detail-panel-max-h: min(44vh, 360px);
    --city-detail-marker-gap: 20px;
    --map-inset-top: calc(
      var(--city-detail-cta-top) + var(--city-detail-cta-stack-h) + 14px
    );
    --map-inset-bottom: calc(
      var(--city-detail-ui-bottom) + var(--city-detail-panel-max-h) +
        var(--city-detail-marker-gap)
    );
  }
  .kamo-root--city-detail .market-label-slot {
    top: auto;
    bottom: var(--city-detail-ui-bottom);
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    width: min(400px, calc(100vw - 48px));
    text-align: center;
  }
  .kamo-root--city-detail .market-label--detail {
    max-height: var(--city-detail-panel-max-h);
    max-width: min(400px, calc(100vw - 48px));
    margin: 0 auto;
  }
  .kamo-root--city-detail .cta-slot--city-detail {
    left: 50%;
    right: auto;
    bottom: auto;
    top: var(--city-detail-cta-top);
    width: min(400px, calc(100vw - 48px));
    max-width: min(400px, calc(100vw - 48px));
    transform: translateX(-50%);
    transition-delay: 0s;
  }
  .kamo-root--city-detail .cta-slot--city-detail .cta-about {
    -webkit-line-clamp: 2;
    line-clamp: 2;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .kamo-root--city-detail .cta-slot--city-detail .cta-helper {
    -webkit-line-clamp: 1;
    line-clamp: 1;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .kamo-root--city-detail .map-canvas::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 2;
    background: linear-gradient(
      to bottom,
      rgba(7, 9, 13, 0.3) 0%,
      transparent 14%,
      transparent 72%,
      rgba(7, 9, 13, 0.4) 100%
    );
  }
}

/* ===== Responsive — mobile / portrait =================================== */
@media (max-width: 720px) {
  .hero-copy.hero-intro-column {
    padding: 16px 18px 18px;
    gap: 11px;
    max-width: min(92vw, 340px);
    background: rgba(7, 9, 13, 0.52);
    border: none;
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.32);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
  }
  .hero-tagline { font-size: 14px; max-width: 36ch; }
  .hero-intro-column .hero-tagline { margin: 0; }
  .hero-eyebrow { font-size: 10px; letter-spacing: var(--track-label); margin-bottom: 0; }

  :root {
    --kamo-logo-clear-w: min(200px, 56vw);
    --kamo-logo-clear-h: clamp(42px, 10vw, 58px);
  }

  .top-chrome {
    padding: 16px 18px;
  }

  .brand-header-anchor {
    left: max(14px, env(safe-area-inset-left, 0px));
    top: max(10px, env(safe-area-inset-top, 0px));
    /* Tight hit target: wide box + centered object-fit looked “between” corner and center */
    width: var(--kamo-logo-clear-w);
    max-width: 62%;
    height: var(--kamo-logo-clear-h);
  }

  .brand-lockup-flight--header .brand-lockup-flight__img {
    object-position: left center;
  }

  .hero-logo-slot {
    width: min(78vw, 320px);
    height: clamp(48px, 10vw, 72px);
  }

  .top-chrome {
    min-height: calc(
      max(14px, env(safe-area-inset-top, 0px)) + var(--kamo-logo-clear-h) + 8px
    );
  }

  .top-enquiry-center {
    /* Overlapped the logo at phone widths. Explore + Enquire are already covered
       on the homepage by the markets manifest, the CTA panel and the WhatsApp FAB.
       !important overrides the inline display:flex set in App.tsx. */
    display: none !important;
  }

  .top-meta-aside {
    position: fixed;
    top: max(14px, env(safe-area-inset-top, 0px));
    right: max(18px, env(safe-area-inset-right, 0px));
    z-index: 13;
  }

  .top-meta {
    display: none;
  }

  .top-utility-panel {
    padding: 5px 8px;
  }

  .enquiry-nav-btn {
    font-size: 8px;
    letter-spacing: var(--track-wide);
    padding: 3px 4px;
    max-width: min(42vw, 148px);
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .market-label-slot {
    left: 20px;
    right: 20px;
    bottom: auto;
    top: 22%;
    text-align: center;
    transition:
      top 0.55s cubic-bezier(0.22, 1, 0.36, 1),
      bottom 0.55s cubic-bezier(0.22, 1, 0.36, 1);
  }
  /* City detail: logo → CTA (top) → map → detail panel (bottom) */
  .kamo-root--city-detail {
    --city-detail-logo-clear: max(
      62px,
      calc(env(safe-area-inset-top, 0px) + clamp(42px, 10vw, 58px) + 10px)
    );
    --city-detail-cta-top: calc(var(--city-detail-logo-clear) + 8px);
    --city-detail-cta-stack-h: 118px;
    --city-detail-ui-bottom: calc(72px + env(safe-area-inset-bottom, 0px));
    --city-detail-panel-max-h: min(40vh, 320px);
    --city-detail-marker-gap: 20px;
    --map-inset-top: calc(
      var(--city-detail-cta-top) + var(--city-detail-cta-stack-h) + 12px
    );
    --map-inset-bottom: calc(
      var(--city-detail-ui-bottom) + var(--city-detail-panel-max-h) +
        var(--city-detail-marker-gap)
    );
  }
  .kamo-root--city-detail .market-label-slot {
    top: auto;
    bottom: var(--city-detail-ui-bottom);
  }
  .market-label {
    border-inline-start: 0;
    border-top: 1px solid rgba(232, 228, 220, 0.14);
    padding: 11px 12px;
    align-items: center;
    min-width: 0;
    max-width: min(340px, 92vw);
    margin: 0 auto;
    background: var(--kamo-panel-bg-strong);
    box-shadow: 0 14px 40px rgba(0, 0, 0, 0.38);
    backdrop-filter: blur(11px);
    -webkit-backdrop-filter: blur(11px);
  }
  .market-label--detail {
    max-height: min(48vh, 380px);
    text-align: left;
    align-items: stretch;
  }
  .kamo-root--city-detail .market-label--detail {
    max-height: var(--city-detail-panel-max-h);
  }
  .kamo-root--city-detail .market-label--detail .ml-name {
    font-size: 24px;
  }
  .kamo-root--city-detail .market-label--detail .ml-region {
    text-transform: none;
    letter-spacing: var(--track-wide);
  }
  .market-label--detail .city-detail-close {
    display: flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: 2;
    width: 32px;
    height: 32px;
    margin: 0;
    padding: 0;
    appearance: none;
    border: 1px solid rgba(232, 228, 220, 0.14);
    border-radius: var(--kamo-r-hair);
    background: rgba(7, 9, 13, 0.55);
    color: var(--kamo-fg-dim);
    font-size: 22px;
    line-height: 1;
    cursor: pointer;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.28);
    transition:
      color 0.2s ease,
      background 0.2s ease,
      border-color 0.2s ease;
  }
  .market-label--detail .city-detail-close:hover {
    color: var(--kamo-gold);
    background: rgba(7, 9, 13, 0.72);
    border-color: rgba(201, 165, 116, 0.35);
  }
  .market-label--detail .ml-header {
    padding-right: 36px;
  }
  .market-label--detail .ml-stats {
    grid-template-columns: 1fr;
  }
  .ml-index {
    font-size: 9px;
    letter-spacing: var(--track-label);
    margin-bottom: 2px;
  }
  .ml-name {
    font-size: 26px;
    line-height: 1.06;
  }
  .ml-region {
    font-size: 10px;
    letter-spacing: var(--track-wide);
    text-transform: none;
  }
  .marker-overlay--city-detail .marker-label {
    text-transform: none;
    letter-spacing: var(--track-body);
  }

  .kamo-root--network .map-canvas::after {
    background: linear-gradient(
      to bottom,
      rgba(7, 9, 13, 0.28) 0%,
      transparent 12%,
      transparent 68%,
      rgba(7, 9, 13, 0.45) 100%
    );
  }

  /* Network markers (mobile) — country strokes match desktop via WorldMap inline styles */
  .kamo-root--network .marker--network .marker-crosshair {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
  }
  .kamo-root--network .marker--network .marker-ring {
    opacity: 1;
    stroke-width: 3.5px;
  }
  .kamo-root--network .marker--network .marker-dot {
    transform: scale(1.5);
    transform-box: fill-box;
    transform-origin: center;
  }
  .kamo-root--network .marker--network .marker-pulse {
    opacity: 0.72;
    stroke-width: 3px;
    animation: kamoPulseNetworkMobile 2.6s cubic-bezier(0.5, 0, 0.5, 1) infinite;
  }
  .kamo-root--network .marker--interactive .marker-invite {
    opacity: 0.42;
    stroke-width: 1.35px;
    animation: markerInviteNetworkMobile 2.8s ease-in-out infinite;
  }
  .kamo-root--network .marker--interactive:active .marker-visual,
  .kamo-root--network .marker--interactive:focus-within .marker-visual {
    transform: scale(1.12);
  }
  .kamo-root--network .marker--interactive:active .marker-crosshair,
  .kamo-root--network .marker--interactive:focus-within .marker-crosshair {
    opacity: 0;
    visibility: hidden;
  }
  /* Network picks use nearest-marker layer — keep per-pin hits small for keyboard focus only. */
  .kamo-root--network .marker-overlay--network-pick .marker-hit {
    transform: none;
  }

  /* User pick from network: avoid crosshair re-animation flash */
  .kamo-root--city-detail .marker--focus-in .marker-crosshair {
    opacity: 0.5;
    animation: none;
  }
  .kamo-root--city-detail .marker--focus-in .marker-pulse {
    animation: kamoPulse 2200ms cubic-bezier(0.5, 0, 0.5, 1) infinite;
  }
  .marker-overlay--city-detail .marker-label {
    fill: var(--kamo-gold);
    letter-spacing: var(--track-wide);
    stroke: rgba(7, 9, 13, 0.96);
    stroke-width: 5px;
  }
  .kamo-root--city-detail .marker-visual {
    transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1);
  }
  .kamo-root--city-detail .countries path {
    transition:
      stroke 0.5s ease,
      fill 0.5s ease,
      opacity 0.5s ease;
  }
  .kamo-root--nav-enter .countries path,
  .kamo-root--nav-exit .countries path {
    transition: none;
  }

  .kamo-root--city-detail .map-canvas::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 2;
    background: linear-gradient(
      to bottom,
      rgba(7, 9, 13, 0.32) 0%,
      transparent 14%,
      transparent 72%,
      rgba(7, 9, 13, 0.42) 100%
    );
  }

  /* Orchestrated network → city: crossfade map vignettes with camera progress */
  .kamo-root--nav-enter.kamo-root--network .map-canvas::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 2;
    background: linear-gradient(
      to bottom,
      rgba(7, 9, 13, 0.28) 0%,
      transparent 12%,
      transparent 68%,
      rgba(7, 9, 13, 0.45) 100%
    );
    opacity: calc(1 - var(--nav-progress, 0));
    transition: none;
  }
  .kamo-root--nav-enter.kamo-root--network .map-canvas::after {
    opacity: calc(1 - var(--nav-progress, 0));
  }
  .kamo-root--nav-enter.kamo-root--city-detail .map-canvas::after {
    opacity: var(--nav-progress, 0);
  }

  .manifest-list { gap: 8px; }
  .manifest-list li {
    grid-template-columns: 24px 1fr auto;
    gap: 10px;
    padding-bottom: 8px;
  }
  .manifest-name { font-size: 16px; }
  .manifest-region { font-size: 8.5px; letter-spacing: var(--track-label); }
  .manifest-num { font-size: 9px; }

  .enquiry-modal-panel {
    max-height: min(88dvh, 88vh);
  }
  .enquiry-block {
    gap: 11px;
    padding: 16px 16px max(20px, env(safe-area-inset-bottom, 0px));
  }
  .enquiry-helper {
    font-size: 11px;
  }
  .enquiry-radio {
    font-size: 11px;
    min-height: 36px;
    align-items: center;
  }
  .enquiry-radio input {
    width: 18px;
    height: 18px;
    margin-top: 0;
  }
  .enquiry-input,
  .enquiry-textarea {
    font-size: 16px;
    padding: 12px 11px;
  }
  .enquiry-submit {
    width: 100%;
    text-align: center;
    min-height: 48px;
    align-self: stretch;
  }
  .cta-slot {
    left: max(20px, env(safe-area-inset-left, 0px));
    right: auto;
    bottom: calc(80px + env(safe-area-inset-bottom, 0px));
    max-width: min(290px, calc(100vw - 40px));
    transition:
      left 0.55s cubic-bezier(0.22, 1, 0.36, 1),
      right 0.55s cubic-bezier(0.22, 1, 0.36, 1),
      bottom 0.55s cubic-bezier(0.22, 1, 0.36, 1),
      top 0.55s cubic-bezier(0.22, 1, 0.36, 1),
      transform 0.55s cubic-bezier(0.22, 1, 0.36, 1),
      max-width 0.55s cubic-bezier(0.22, 1, 0.36, 1);
  }
  .kamo-root--city-detail .cta-slot--city-detail {
    left: 50%;
    right: auto;
    bottom: auto;
    top: var(--city-detail-cta-top);
    width: min(320px, calc(100vw - 32px));
    max-width: min(320px, calc(100vw - 32px));
    transform: translateX(-50%);
    transition-delay: 0s;
  }
  .kamo-root--city-detail .cta-slot--city-detail .cta-about {
    -webkit-line-clamp: 2;
    line-clamp: 2;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .kamo-root--city-detail .cta-slot--city-detail .cta-helper {
    -webkit-line-clamp: 1;
    line-clamp: 1;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .kamo-root--city-detail .cta-slot--city-detail .cta-input,
  .kamo-root--city-detail .cta-slot--city-detail .cta-btn {
    min-height: 40px;
  }
  .kamo-root--network .cta-slot .cta-block,
  .kamo-root--city-detail .cta-slot--city-detail .cta-block {
    background: var(--kamo-panel-bg-strong);
    border: 1px solid rgba(232, 228, 220, 0.14);
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.38);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
  }
  .kamo-root--network .cta-slot .cta-form {
    flex-wrap: nowrap;
  }

  .bottom-chrome {
    flex-direction: column;
    gap: 10px;
    align-items: center;
    padding-top: 14px;
    padding-right: max(18px, env(safe-area-inset-right, 0px));
    padding-left: max(18px, env(safe-area-inset-left, 0px));
    padding-bottom: max(14px, env(safe-area-inset-bottom, 0px));
  }
  .footer-text { font-size: 9px; letter-spacing: var(--track-label); text-align: center; }

  /* Scrub dots keep their base 44×44 hit area on this short band (the old
     padding:12px 0 override collapsed it once the base moved to content-box). */
  .scrub-btn { padding: 8px 0; }

  .marker-hit {
    transform: scale(1.35);
    transform-box: fill-box;
    transform-origin: center;
  }
  .marker.marker--idle .marker-ring { opacity: 0.62; }
  .marker.marker--idle .marker-dot { opacity: 1; }
  .marker .marker-dot {
    transform: scale(1.22);
    transform-box: fill-box;
    transform-origin: center;
  }
  .marker--active .marker-crosshair { opacity: 0.84; }
  .marker-crosshair line { stroke-width: 2.45px; }
  .marker-ring { stroke-width: 3px; }
  .marker-pulse { stroke-width: 2.75px; }
}

/* Short / landscape: stacked city-detail at any width when height is tight */
@media (max-height: 640px) {
  .kamo-root--city-detail {
    --city-detail-logo-clear: max(
      48px,
      calc(env(safe-area-inset-top, 0px) + clamp(38px, 9vw, 52px) + 6px)
    );
    --city-detail-cta-top: calc(var(--city-detail-logo-clear) + 4px);
    --city-detail-cta-stack-h: 132px;
    --city-detail-ui-bottom: calc(56px + env(safe-area-inset-bottom, 0px));
    --city-detail-panel-max-h: min(28vh, 184px);
    --city-detail-marker-gap: 16px;
    --map-inset-top: calc(
      var(--city-detail-cta-top) + var(--city-detail-cta-stack-h) + 8px
    );
    --map-inset-bottom: calc(
      var(--city-detail-ui-bottom) + var(--city-detail-panel-max-h) +
        var(--city-detail-marker-gap)
    );
  }
  .kamo-root--city-detail .market-label-slot {
    top: auto;
    bottom: var(--city-detail-ui-bottom);
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    width: min(320px, calc(100vw - 32px));
    text-align: center;
  }
  .kamo-root--city-detail .market-label--detail {
    max-height: var(--city-detail-panel-max-h);
    max-width: min(320px, calc(100vw - 32px));
    margin: 0 auto;
  }
  .kamo-root--city-detail .cta-slot--city-detail {
    left: 50%;
    right: auto;
    bottom: auto;
    top: var(--city-detail-cta-top);
    width: min(320px, calc(100vw - 32px));
    max-width: min(320px, calc(100vw - 32px));
    transform: translateX(-50%);
    transition-delay: 0s;
  }
  .kamo-root--city-detail .cta-slot--city-detail .cta-about {
    -webkit-line-clamp: 1;
    line-clamp: 1;
  }
  .kamo-root--city-detail .cta-slot--city-detail .cta-input,
  .kamo-root--city-detail .cta-slot--city-detail .cta-btn {
    min-height: 38px;
  }
}

/* ===== Responsive — very narrow ========================================= */
@media (max-width: 380px) {
  .hero-tagline { font-size: 13px; }
  .ml-name { font-size: 24px; }
}

/* ===== Marker states (SVG, screen-space overlay) ======================== */

/* Hidden during scenic intro / inactive city-tour beats */
.marker--hidden .marker-visual {
  opacity: 0;
  transition: opacity 300ms ease;
}

/* Idle markers: dim, small — shorter transitions avoid double-emphasis across stage swaps */
.marker .marker-crosshair { opacity: 0; transition: opacity 320ms cubic-bezier(0.65,0,0.35,1); }
.marker .marker-pulse     { opacity: 0; transition: opacity 280ms ease; }
.marker .marker-ring      { opacity: 0.35; transition: opacity 320ms cubic-bezier(0.65,0,0.35,1); }
.marker .marker-dot       { opacity: 0.7;  transition: opacity 320ms cubic-bezier(0.65,0,0.35,1); }

/* Active: crosshair on, ring pulsing */
.marker--active .marker-crosshair { opacity: 0.45; }
.marker--active .marker-ring  { opacity: 1; }
.marker--active .marker-dot   { opacity: 1; }
.marker--active .marker-pulse {
  opacity: 1;
  animation: kamoPulse 2200ms cubic-bezier(0.5, 0, 0.5, 1) infinite;
  transform-box: fill-box;
  transform-origin: center;
}

/* User zoom from network: crosshair fades in after camera starts */
.marker--focus-in .marker-crosshair {
  opacity: 0.45;
  animation: markerCrosshairIn 0.55s ease 0.32s both;
}
@keyframes markerCrosshairIn {
  from { opacity: 0; }
  to { opacity: 0.45; }
}
.marker--focus-in .marker-ring { opacity: 1; }
.marker--focus-in .marker-dot { opacity: 1; }
.marker--focus-in .marker-pulse {
  opacity: 1;
  animation: kamoPulse 2200ms cubic-bezier(0.5, 0, 0.5, 1) infinite;
  transform-box: fill-box;
  transform-origin: center;
}
.marker-overlay--exiting-network .marker--network:not(.marker--focus-in) .marker-ring {
  opacity: 0.55;
  transition: opacity 500ms ease;
}
.marker-overlay--exiting-network .marker--network:not(.marker--focus-in) .marker-dot {
  opacity: 0.65;
  transition: opacity 500ms ease;
}

@keyframes kamoPulse {
  0%   { r: 6;  opacity: 0.85; stroke-width: 1.4; }
  80%  { r: 22; opacity: 0;    stroke-width: 0.6; }
  100% { r: 22; opacity: 0;    stroke-width: 0.6; }
}

/* Intro city tour: all pins visible; active beat highlighted separately */
.marker--tour-idle .marker-ring {
  opacity: 0.5;
  transition: opacity 400ms ease;
}
.marker--tour-idle .marker-dot {
  opacity: 0.55;
  transition: opacity 400ms ease;
}
.marker--tour-idle .marker-pulse {
  opacity: 0.28;
  animation: kamoPulseSlow 3600ms cubic-bezier(0.5, 0, 0.5, 1) infinite;
}

/* Network: all rings visible, no crosshair, slow pulse */
.marker--network .marker-ring  { opacity: 1; }
.marker--network .marker-dot   { opacity: 1; }
.marker--network .marker-pulse {
  opacity: 0.55;
  animation: kamoPulseSlow 3400ms cubic-bezier(0.5, 0, 0.5, 1) infinite;
}
@keyframes kamoPulseSlow {
  0%   { r: 6;  opacity: 0.55; }
  85%  { r: 18; opacity: 0;    }
  100% { r: 18; opacity: 0;    }
}

@keyframes kamoPulseNetworkMobile {
  0%   { r: 7;  opacity: 0.78; stroke-width: 3px; }
  80%  { r: 24; opacity: 0;    stroke-width: 1.2px; }
  100% { r: 24; opacity: 0;    stroke-width: 1.2px; }
}

@keyframes markerInviteNetworkMobile {
  0%,
  100% {
    opacity: 0.32;
  }
  50% {
    opacity: 0.52;
  }
}

.marker-overlay--interactive {
  pointer-events: all;
}

/* City detail: peer pins stay visible and clickable while reading another market */
.marker-overlay--city-detail .marker-label {
  font-family: var(--font-mono);
  letter-spacing: var(--track-wide);
  text-transform: capitalize;
  fill: var(--kamo-fg);
  paint-order: stroke fill;
  stroke: rgba(7, 9, 13, 0.92);
  stroke-width: 4px;
  stroke-linejoin: round;
  pointer-events: none;
  opacity: 0;
  transition: opacity 400ms cubic-bezier(0.22, 1, 0.36, 1);
}
.marker-overlay--city-detail .marker-label--ready {
  opacity: 1;
}
.marker-overlay--city-detail .marker-label--current {
  fill: var(--kamo-gold);
}

/* Network-view market labels (R1a): quiet mono names that fade in once the
   network settles. Scoped away from the city-detail overlay (its own rule
   above drives the city-detail labels). Mounted at opacity 0 then revealed via
   .marker-label--ready so the reveal is a calm fade, not a pop. */
.marker-overlay:not(.marker-overlay--city-detail) .marker-label--network {
  font-family: var(--font-mono);
  letter-spacing: var(--track-wide);
  text-transform: capitalize;
  fill: var(--kamo-fg);
  paint-order: stroke fill;
  stroke: rgba(7, 9, 13, 0.92);
  stroke-width: 4px;
  stroke-linejoin: round;
  pointer-events: none;
  opacity: 0;
  transition: opacity 400ms cubic-bezier(0.22, 1, 0.36, 1);
}
.marker-overlay:not(.marker-overlay--city-detail) .marker-label--network.marker-label--ready {
  opacity: 0.82;
}
.marker-overlay:not(.marker-overlay--city-detail) .marker-label--network.marker-label--current {
  fill: var(--kamo-gold);
}

/* Light theme: the dark text halo (built for the dark map) muddies the dark labels
   on the light terrain. Flip it to a warm near-white knockout so they stay crisp,
   and bring the small network labels to full opacity so they read on the light map. */
[data-theme="light"] .marker-overlay--city-detail .marker-label,
[data-theme="light"] .marker-overlay:not(.marker-overlay--city-detail) .marker-label--network {
  stroke: rgba(250, 247, 241, 0.95);
}
[data-theme="light"] .marker-overlay:not(.marker-overlay--city-detail) .marker-label--network.marker-label--ready {
  opacity: 1;
}
@media (prefers-reduced-motion: reduce) {
  .marker-label--network {
    transition: none;
  }
}
/* Avoid label crowding on the smallest phones — keep the pins, drop the names. */
@media (max-width: 380px) {
  .marker-label--network {
    display: none;
  }
}
.marker-hit-area {
  pointer-events: all;
  cursor: pointer;
}
.marker-hit-group:focus-visible .marker-hit-area {
  outline: 1px solid var(--kamo-gold);
  outline-offset: 3px;
}
.marker--interactive.marker--labeled:hover .marker-label,
.marker--interactive.marker--labeled:focus-within .marker-label {
  fill: var(--kamo-gold);
}
.marker-overlay--city-detail .marker--network .marker-visual {
  opacity: 0.72;
}
.marker-overlay--city-detail .marker--active .marker-visual {
  opacity: 1;
}
.marker-overlay--city-detail .marker--network .marker-ring {
  opacity: 0.85;
}
.marker-overlay--city-detail .marker--network .marker-dot {
  opacity: 0.9;
}
.marker-overlay--city-detail .marker--network .marker-pulse {
  opacity: 0.45;
}

.marker--interactive {
  cursor: pointer;
}

.marker--interactive .marker-invite {
  opacity: 0.2;
  transition: opacity 400ms ease;
  animation: markerInvitePulse 4.5s ease-in-out infinite;
}
.marker--interactive:hover .marker-visual,
.marker--interactive:focus-within .marker-visual {
  transform: scale(1.08);
  transition: transform 400ms cubic-bezier(0.22, 1, 0.36, 1);
}
.marker--interactive .marker-visual {
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 400ms cubic-bezier(0.22, 1, 0.36, 1);
}
.marker--interactive:hover .marker-ring,
.marker--interactive:focus-within .marker-ring {
  opacity: 1;
}
.marker--interactive:hover .marker-invite,
.marker--interactive:focus-within .marker-invite {
  opacity: 0.42;
}
@keyframes markerInvitePulse {
  0%, 100% { opacity: 0.16; }
  50% { opacity: 0.28; }
}

.marker-overlay--network-pick .marker-hit {
  pointer-events: none;
}

.marker-network-hit-layer {
  pointer-events: all;
  cursor: pointer;
  touch-action: manipulation;
}

.marker-hit {
  pointer-events: all;
  cursor: pointer;
}

.marker-hit:focus-visible {
  outline: 1px solid var(--kamo-gold);
  outline-offset: 3px;
}

/* ===== Top-chrome entrance animations =================================== */
@keyframes kamoFadeDown {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0);    }
}
@keyframes kamoFadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* ===== Accessibility / motion-reduced =================================== */
@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.2s !important; animation-duration: 0.2s !important; }
  .marker-overlay--city-detail .marker-label {
    opacity: 1;
    transition: none;
  }
  .marker-pulse {
    animation: none !important;
    opacity: 0 !important;
  }
  .brand-lockup-flight {
    transition: none !important;
  }
  .kamo-root--network .cta-block::before,
  .kamo-root--network .brand-lockup-flight__img {
    animation: none !important;
  }
}

/* Screen reader utilities & focus ========================================= */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Accessible parallel to the (aria-hidden) SVG map on Explore: each market/area
   has a real button wired to the same browse handlers. Buttons are visually
   hidden until focused, then surface as a chip so sighted keyboard users can
   see where they are. The home map uses .sr-only instead (fully hidden). */
.map-a11y-nav {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 6;
}
.map-a11y-nav button {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
  background: none;
  color: inherit;
}
.map-a11y-nav button:focus-visible {
  position: static;
  width: auto;
  height: auto;
  margin: 12px;
  padding: 9px 14px;
  clip: auto;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--kamo-fg);
  background: var(--kamo-panel, rgba(8, 10, 14, 0.94));
  border: 1px solid var(--kamo-gold);
  border-radius: var(--kamo-r-hair);
  cursor: pointer;
}

.cta-input:focus-visible,
.cta-btn:focus-visible,
.scrub-btn:focus-visible,
.scrub-dot:focus-visible,
.manifest-row:focus-visible,
.city-detail-close:focus-visible,
.enquiry-submit:focus-visible {
  outline: 1px solid var(--kamo-gold);
  outline-offset: 3px;
}

.cta-privacy {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--kamo-fg-mute);
  line-height: 1.55;
  margin: 12px 0 0;
}
.cta-privacy a {
  color: var(--kamo-gold-soft);
}
.cta-privacy a:focus-visible {
  outline: 1px solid var(--kamo-gold);
  outline-offset: 2px;
}

.cta-consent {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-top: 14px;
}
.cta-consent input {
  margin-top: 3px;
  accent-color: var(--kamo-gold);
}
/* Owner feedback, 2026-08-05: "the privacy-policy checkbox text looks
   weird". Diagnosis (screenshotted on a project + listing enquiry section):
   the label's own font/size/weight WERE already the site's body-serif
   token (--font-sans resolves to Lora, not an actual sans — this design
   system's body copy is serif throughout, see the KÂMO type-system notes),
   so that part was fine — but three things weren't: (1) `font-weight: 300`
   at 12px is thinner than any other running text on the page, reading
   frailer than intended rather than deliberately "fine print"; (2) the
   inline `<a>` had NO rule of its own anywhere, so it fell back to the
   UA-default blue/underline — a jarring, off-brand color note against this
   page's warm gold/dim palette, unlike every OTHER inline privacy link on
   the site (.cta-privacy a, .enquiry-privacy a), which are already branded
   gold; (3) no measure constraint, so inside the new Stage/Dossier layouts'
   wider enquiry section this line could stretch far past a comfortable
   reading width before wrapping. Fixed all three below — kept it small
   (fine print is supposed to read quietly, not loudly) and did not touch
   layout/markup, per the brief. */
.cta-consent label {
  display: block;
  max-width: 60ch;
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: 13px;
  line-height: 1.55;
  letter-spacing: var(--track-body);
  color: var(--kamo-fg-dim);
}
.cta-consent label a {
  color: var(--kamo-gold-soft);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.cta-consent label a:hover {
  color: var(--kamo-gold-text);
}
.cta-consent label a:focus-visible {
  outline: 1px solid var(--kamo-gold);
  outline-offset: 2px;
}
/* Re-centers the checkbox against the label's now-explicit 13px/1.55 first
   line (≈20px tall) instead of the old fixed 2-3px guess, which was tuned
   for whatever the label's PREVIOUS, unset line-height happened to inherit
   from each different enquiry form's own surrounding context — inconsistent
   by construction. Scoped past both `.cta-consent input` and the shared
   `.enquiry-radio, .enquiry-consent input[type="checkbox"]` rule (index.css,
   "Refined radio / checkbox" section) on purpose — this checkbox's own
   vertical alignment shouldn't move the unrelated `.enquiry-radio` question
   choices in GuidedBrief that happen to share that rule. */
.cta-consent.enquiry-consent input[type="checkbox"] {
  margin-top: 3px;
}

.cta-error-msg {
  font-family: var(--font-sans);
  font-size: 12px;
  color: #e88a8a;
  margin-top: 10px;
}

/* ===== RTL (Arabic) ======================================================= */
html[dir='rtl'] .manifest-row,
html[dir='rtl'] .cta-block,
html[dir='rtl'] .enquiry-block,
html[dir='rtl'] .market-label--detail .ml-detail-scroll {
  text-align: right;
}
html[dir='rtl'] .kamo-root--network .manifest-eyebrow,
html[dir='rtl'] .kamo-root--network .manifest-hint,
html[dir='rtl'] .kamo-root--network .cta-slot .cta-eyebrow,
html[dir='rtl'] .kamo-root--network .cta-slot .cta-about,
html[dir='rtl'] .kamo-root--network .cta-slot .cta-helper,
html[dir='rtl'] .kamo-root--city-detail .cta-slot--city-detail .cta-eyebrow,
html[dir='rtl'] .kamo-root--city-detail .cta-slot--city-detail .cta-about,
html[dir='rtl'] .kamo-root--city-detail .cta-slot--city-detail .cta-helper {
  text-align: center;
}
html[dir='rtl'] .manifest-list li[style] {
  transform: none !important;
}
html[dir='rtl'] .top-chrome .enquiry-nav-btn {
  direction: rtl;
}

/* ── RTL (Arabic) — content/guide pages ─────────────────────────────────────
   Covers the location/developer/compound/insight templates (ContentPageLayout,
   SeoGuide) and the pages that share their layout classes (ProjectPage, the
   /guides, /insights, /markets index pages). Most directional fixes for these
   templates were converted to CSS logical properties in place (padding-inline/
   -block, inset-inline-*) instead of being duplicated here — a logical
   property is byte-for-byte equivalent to the LTR value it replaced, so it
   needs no separate [dir="rtl"] rule. Only the two cases below have no
   logical-property equivalent. */

/* Breadcrumb "/" separator (a literal glyph in the trail text — ContentPageLayout,
   SeoGuide, ProjectPage, GuidesIndex, InsightsIndex, MarketsIndex all render the
   same `<span aria-hidden> / </span>`). Mirror it to "\" so it still reads as a
   separator once the trail itself reverses under bidi. inline-block is required:
   CSS transforms have no effect on non-replaced inline boxes (same reason
   .ks-text-cta__arrow below is inline-block). */
[dir='rtl'] .seo-guide-breadcrumb span[aria-hidden] {
  display: inline-block;
  transform: scaleX(-1);
}

/* Guide/location/developer photo-hero band (ContentPageLayout's photoHero):
   the warm radial wash is deliberately off-center toward 8% from the left
   edge. background/gradient position offsets have no logical-property
   equivalent (no "inline-start" keyword for gradient coordinates), so the
   hotspot is mirrored explicitly for RTL. */
[dir='rtl'] .kamo-page-hero--photo {
  background:
    radial-gradient(90% 80% at 92% 0%, rgba(201, 165, 116, 0.10), transparent 55%),
    #0a0c10;
}

/* Hard invariant: Arabic script must never be letter-spaced or case-transformed,
   regardless of what any component-level rule sets (deliberately or by accident). */
[dir="rtl"], [dir="rtl"] * {
  letter-spacing: 0 !important;
  text-transform: none !important;
}

/* ============================================================================
   Semantic type roles — design system classes
============================================================================ */
.kamo-display, .kamo-h1 {
  font-family: var(--font-serif); font-weight: 400;
  font-size: calc(clamp(36px, 4.5vw, 60px) * var(--display-size-mult)); line-height: 1.08;
  text-transform: var(--display-transform);
  letter-spacing: var(--track-display); color: var(--kamo-fg); text-wrap: balance;
}
.kamo-h2 {
  font-family: var(--font-serif); font-weight: 400;
  font-size: 20px; text-transform: var(--display-transform);
  letter-spacing: var(--track-display);
  line-height: 1.3; color: var(--kamo-fg);
}
.kamo-h3 {
  font-family: var(--font-sans); font-weight: 500;
  font-size: 17px; line-height: 1.4;
  letter-spacing: var(--track-tight); color: var(--kamo-fg); margin: 0;
}
.kamo-tagline {
  /* Plain sans lede (Variant A) — the italic serif read as "luxury template". */
  font-family: var(--font-sans); font-weight: 400;
  font-size: 16px; line-height: 1.6;
  letter-spacing: var(--track-body); color: var(--kamo-fg);
}
.kamo-body { font-family: var(--font-sans); font-weight: 400; font-size: var(--body-size); line-height: 1.75; letter-spacing: var(--track-body); color: var(--kamo-fg); }
.kamo-measure { max-width: 46ch; }
.kamo-body--compact { font-size: 14px; line-height: 1.6; }
.kamo-body-dim { color: var(--kamo-fg-dim); }

/* Prose/content links — guide, insight, market and property-description bodies
   render raw <a> from prerendered/CMS HTML (no class). Unstyled, they fall back
   to the UA blue + :visited purple, which looks broken (worst in dark mode).
   Brand them gold in BOTH skins (theme-aware --kamo-gold-text), and pin :visited
   so clicked links stop going purple. Matches the prerendered guide skin
   (public/seo-guide.css). Scoped to unclassed <a> so styled links are untouched. */
.kamo-body a:not([class]),
.kamo-tagline a:not([class]) {
  color: var(--kamo-gold-text);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: color var(--dur-fast), opacity var(--dur-fast);
}
.kamo-body a:not([class]):visited,
.kamo-tagline a:not([class]):visited { color: var(--kamo-gold-text); }
.kamo-body a:not([class]):hover,
.kamo-tagline a:not([class]):hover { color: var(--kamo-gold); opacity: 0.9; }
.kamo-eyebrow { font-family: var(--font-mono); font-weight: 500; font-size: 10px; letter-spacing: var(--track-label); text-transform: uppercase; color: var(--kamo-gold-text); }
.kamo-label   { font-family: var(--font-mono); font-size: 10px; font-weight: 500; letter-spacing: var(--track-label); text-transform: uppercase; color: var(--kamo-fg-dim); }
.kamo-coord   { font-family: var(--font-mono); font-size: 10px; letter-spacing: var(--track-wide); font-variant-numeric: tabular-nums; color: var(--kamo-fg-dim); }
.kamo-index   { font-family: var(--font-mono); font-size: 10px; letter-spacing: var(--track-label); text-transform: uppercase; color: var(--kamo-gold-text); }
.kamo-region  { font-family: var(--font-sans); font-weight: 400; font-size: 12px; letter-spacing: var(--track-label); text-transform: uppercase; color: var(--kamo-fg-dim); }
.kamo-stat    { font-family: var(--font-serif); font-weight: 400; font-size: 15px; line-height: 1.2; color: var(--kamo-gold-text); }

/* ============================================================================
   Interior page animations — visual refresh
============================================================================ */

/* Breathing glow — for featured panels and hero accents */
@keyframes kamoBreath {
  0%, 100% { opacity: 0.82; }
  50%       { opacity: 1; }
}
.kamo-breathe { animation: kamoBreath 4s ease-in-out infinite; }

/* Hairline gold sweep — apply to elements with position:relative */
@keyframes kamoSweep {
  0%   { background-position: -200% 0; }
  100% { background-position:  200% 0; }
}
.kamo-sweep {
  position: relative;
}
.kamo-sweep::before {
  content: '';
  position: absolute; top: 0; left: 0; right: 0; height: 1px;
  background: linear-gradient(90deg, transparent 0%, var(--kamo-gold) 50%, transparent 100%);
  background-size: 200% 100%;
  animation: kamoSweep 10s ease-in-out infinite;
  pointer-events: none;
}

/* Staggered fade-up entrance — for grid items */
@keyframes kamoFadeUp {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: translateY(0); }
}
.kamo-fade-up {
  animation: kamoFadeUp var(--dur-mid) var(--ease-emphasised) both;
}

/* One-shot header sweep on page load */
@keyframes kamoSweepOnce {
  0%   { background-position: -200% 0; opacity: 0; }
  20%  { opacity: 1; }
  100% { background-position:  200% 0; opacity: 0; }
}
.kamo-sweep-once::after {
  content: '';
  position: absolute; bottom: -1px; left: 0; right: 0; height: 1px;
  background: linear-gradient(90deg, transparent, var(--kamo-gold), transparent);
  background-size: 200% 100%;
  animation: kamoSweepOnce 1.4s var(--ease-emphasised) both;
  pointer-events: none;
}

/* ============================================================================
   Interior document pages — layout rhythm (d5-inspired editorial spacing)
============================================================================ */
.kamo-document main {
  padding-bottom: clamp(32px, 5vw, 56px);
}

.kamo-page-hero {
  position: relative;
  max-width: 1120px;
  margin: 0 auto;
  padding: var(--hero-pad-top) clamp(24px, 5vw, 64px) clamp(28px, 4vw, 48px);
}
/* Hero rhythm: one source of truth for the eyebrow→h1 gap so pages stop
   carrying their own inline display/margin duplicates of the same spacing. */
.kamo-page-hero .kamo-eyebrow,
.explore-page__intro .kamo-eyebrow {
  display: block;
  margin-bottom: 14px;
}
.kamo-page-hero .kamo-h1 {
  margin: 0 0 14px;
}
/* Property-detail and guide/insight pages open on a full-bleed photo band
   (thumbs or hero image) directly above the text hero — close that gap so
   the title doesn't float too far from the imagery it's captioning. */
.kamo-page-hero--photo + .kamo-page-hero {
  padding-top: clamp(24px, 3vw, 40px);
}
/* No hero wash: the gold radial panel behind interior heroes read as a
   smudge next to the flat Explore header (owner, 2026-07-24). Heroes sit
   directly on the page surface. */

.kamo-page-hero > * {
  position: relative;
}

/* SPA breadcrumb in the content hero. Mirrors public/seo-guide.css so the
   client-rendered trail matches the static prerender. */
.seo-guide-breadcrumb {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--kamo-fg-mute);
}
.seo-guide-breadcrumb a {
  color: var(--kamo-fg-dim);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-color: var(--kamo-rule);
}
.seo-guide-breadcrumb a:hover {
  color: var(--kamo-gold-text);
}

.kamo-section {
  max-width: 1120px;
  margin: 0 auto;
  /* Asymmetric: room above content (under the section rule), less below — the
     old symmetric 88px doubled into ~176px of dead air at every boundary. */
  padding: clamp(40px, 5.5vw, 64px) clamp(24px, 5vw, 64px) clamp(32px, 4.5vw, 52px);
}

.kamo-section--rule {
  border-top: 1px solid var(--kamo-rule);
}

.kamo-stat-cell {
  padding: clamp(24px, 4vw, 40px) clamp(20px, 3vw, 40px);
  display: flex;
  flex-direction: column;
  gap: 6px;
  border-inline-end: 1px solid var(--kamo-rule);
}
.kamo-stat-cell:last-child {
  border-inline-end: none;
}
.kamo-stat-cell__value {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: clamp(28px, 4vw, 48px);
  color: var(--kamo-gold-text);
  line-height: 1;
}
.kamo-stat-cell__label {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
  color: var(--kamo-fg-dim);
}
.kamo-stat-cell__sub {
  font-family: var(--font-sans);
  font-size: 11px;
  color: var(--kamo-fg-mute);
  margin-top: 2px;
}

/* ============================================================================
   The KÂMO Ledger — masthead + data-table typography (2026-08 launch).
   Ported from the approved mockup (which itself mirrored these exact site
   tokens — --kamo-bg/--kamo-fg/--font-serif/--font-sans/--track-* etc. — see
   the mockup's own header comment and src/content/ledger.ts). Scoped under
   `.kamo-ledger` rather than folded into the sitewide `.kamo-*` type roles
   above: a broadsheet's hairline rules, tabular-numeral data table, and drop
   cap are specific to this one strand, not general-purpose primitives.
   `--kamo-ledger-rule-strong` is the one token the mockup introduced that the
   site doesn't already have (the site only has --kamo-rule); defined once per
   skin, locally, rather than added to the sitewide token set for one page.
============================================================================ */
.kamo-ledger {
  --kamo-ledger-rule-strong: rgba(232, 228, 220, 0.28);
}
[data-theme="light"] .kamo-ledger {
  --kamo-ledger-rule-strong: rgba(26, 22, 18, 0.28);
}

.kamo-ledger-masthead {
  text-align: center;
}
.kamo-ledger-kicker {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-fg-mute);
  margin: 0 0 14px;
}
.kamo-ledger-masthead h1 {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(38px, 8vw, 72px);
  line-height: 1.05;
  letter-spacing: 0.01em;
  margin: 0;
  color: var(--kamo-fg);
}
.kamo-ledger-dateline {
  margin: 16px 0 0;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-gold-text);
}
.kamo-ledger-dek {
  max-width: 46ch;
  margin: 20px auto 0;
  font-family: var(--font-sans);
  font-style: italic;
  font-size: 16px;
  line-height: 1.6;
  color: var(--kamo-fg-dim);
}
.kamo-ledger-rules {
  margin-top: clamp(20px, 4vw, 28px);
}
.kamo-ledger-rule-thick {
  border-top: 3px solid var(--kamo-fg);
  opacity: 0.85;
}
.kamo-ledger-rule-thin {
  border-top: 1px solid var(--kamo-ledger-rule-strong);
  margin-top: 4px;
}

.kamo-ledger-section {
  max-width: 700px;
  margin: 0 auto;
  padding: clamp(32px, 6vw, 48px) clamp(20px, 5vw, 28px);
}
.kamo-ledger-section + .kamo-ledger-section {
  border-top: 1px solid var(--kamo-rule);
}

.kamo-ledger-lead h2 {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(26px, 4.4vw, 36px);
  line-height: 1.15;
  letter-spacing: 0.005em;
  margin: 14px 0 22px;
  max-width: 20ch;
}
.kamo-ledger-lead-body p {
  margin: 0 0 20px;
  color: var(--kamo-fg);
  font-family: var(--font-sans);
  font-size: var(--body-size);
  line-height: 1.7;
  letter-spacing: var(--track-body);
}
.kamo-ledger-lead-body p:first-of-type::first-letter {
  font-family: var(--font-serif);
  font-size: 3.4em;
  float: left;
  line-height: 0.86;
  padding: 0.03em 0.08em 0 0;
  color: var(--kamo-gold-text);
}
.kamo-ledger-lead-body p:last-of-type {
  margin-bottom: 0;
}
@media (max-width: 480px) {
  .kamo-ledger-lead-body p:first-of-type::first-letter {
    font-size: 2.9em;
  }
}
.kamo-ledger-byline {
  margin-top: 26px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--kamo-fg-mute);
}

.kamo-ledger-matrices h2 {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(24px, 4vw, 30px);
  margin: 14px 0 16px;
}
.kamo-ledger-standfirst {
  margin: 0 0 26px;
  color: var(--kamo-fg-dim);
  max-width: 56ch;
  font-size: 16px;
  line-height: 1.65;
}
.kamo-ledger-table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
table.kamo-ledger-table {
  width: 100%;
  min-width: 560px;
  border-collapse: collapse;
  font-size: 15px;
}
.kamo-ledger-table thead th {
  text-align: left;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 10.5px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-fg-mute);
  padding: 0 10px 10px 0;
  border-bottom: 1px solid var(--kamo-ledger-rule-strong);
}
.kamo-ledger-table thead th.kamo-ledger-num {
  text-align: right;
}
.kamo-ledger-table tbody td {
  padding: 13px 10px 13px 0;
  border-bottom: 1px solid var(--kamo-rule);
  vertical-align: baseline;
}
.kamo-ledger-table tbody tr:last-child td {
  border-bottom: 1px solid var(--kamo-ledger-rule-strong);
}
.kamo-ledger-dev {
  font-family: var(--font-serif);
  font-size: 15.5px;
  color: var(--kamo-fg);
}
.kamo-ledger-market,
.kamo-ledger-unit {
  font-family: var(--font-sans);
  font-size: 13.5px;
  color: var(--kamo-fg-dim);
}
/* ≤560px: Market, Entry-unit, and Area fold into a sub-line under the
   development name, leaving three columns — Development, Entry price, EGP/sqm —
   that fit a 390px viewport with NO horizontal scroll. Price is the point of
   this table, and the right edge is where mobile clipping bites (nowrap
   numerals force overflow with any more columns). */
.kamo-ledger-market-sub {
  display: none;
}
@media (max-width: 560px) {
  .kamo-ledger-table thead th:nth-child(2),
  .kamo-ledger-table thead th:nth-child(3),
  .kamo-ledger-table thead th:nth-child(4),
  .kamo-ledger-table td.kamo-ledger-market,
  .kamo-ledger-table td.kamo-ledger-unit,
  .kamo-ledger-table td.kamo-ledger-area {
    display: none;
  }
  .kamo-ledger-market-sub {
    display: block;
    font-family: var(--font-sans);
    font-size: 12px;
    line-height: 1.45;
    color: var(--kamo-fg-dim);
    margin-top: 3px;
  }
  table.kamo-ledger-table {
    min-width: 0;
    font-size: 14px;
  }
  .kamo-ledger-table tbody td {
    vertical-align: top;
  }
}
.kamo-ledger-table td.kamo-ledger-num {
  text-align: right;
  font-family: var(--font-serif);
  font-variant-numeric: lining-nums tabular-nums;
  letter-spacing: var(--track-tight);
  white-space: nowrap;
}
.kamo-ledger-table td.kamo-ledger-price {
  color: var(--kamo-fg);
}
.kamo-ledger-table td.kamo-ledger-psqm {
  color: var(--kamo-gold-text);
}
.kamo-ledger-source-note {
  margin-top: 18px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: var(--track-wide);
  line-height: 1.6;
  color: var(--kamo-fg-mute);
}

.kamo-ledger-moved ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
.kamo-ledger-moved li {
  padding: 16px 0;
  border-top: 1px solid var(--kamo-rule);
  font-size: 16px;
  line-height: 1.6;
}
.kamo-ledger-moved li:first-child {
  border-top: none;
  padding-top: 0;
}
.kamo-ledger-moved li strong {
  font-family: var(--font-serif);
  font-weight: 400;
}
.kamo-ledger-cite {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: var(--track-wide);
  color: var(--kamo-fg-mute);
}

.kamo-ledger-end-matter {
  text-align: center;
}
.kamo-ledger-end-matter p {
  margin: 0 0 14px;
  color: var(--kamo-fg-dim);
  font-size: 15px;
}
.kamo-ledger-cta {
  appearance: none;
  background: none;
  border: none;
  border-bottom: 1px solid var(--kamo-gold-soft);
  padding: 0 0 2px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-serif);
  font-size: 18px;
  color: var(--kamo-gold-text);
  text-decoration: none;
  cursor: pointer;
  transition: border-color var(--dur-fast);
}
.kamo-ledger-cta:hover {
  border-bottom-color: var(--kamo-gold-text);
}

.kamo-ledger-colophon {
  text-align: center;
  padding-top: 28px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-fg-mute);
}
.kamo-ledger-cite-line {
  text-align: center;
  padding-top: 8px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-wide);
  color: var(--kamo-fg-mute);
}

/* Insights-index pin (2026-08): a restrained hairline-ruled band above the
   essay grid, not a card — masthead-styled, linking to the latest issue and
   the archive. */
.kamo-ledger-pin {
  max-width: 1120px;
  margin: 0 auto;
  padding: 20px clamp(24px, 5vw, 64px);
  border-top: 1px solid var(--kamo-rule);
  border-bottom: 1px solid var(--kamo-rule);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 20px;
}
.kamo-ledger-pin__issue {
  font-family: var(--font-serif);
  font-size: 16px;
  color: var(--kamo-fg);
  text-decoration: none;
}
.kamo-ledger-pin__issue:hover {
  color: var(--kamo-gold-text);
}
.kamo-ledger-pin__archive {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-gold-text);
  text-decoration: none;
  white-space: nowrap;
}
.kamo-ledger-pin__archive:hover {
  color: var(--kamo-gold);
}

.kamo-split-head {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: 48px;
  margin-bottom: clamp(40px, 6vw, 72px);
}

.kamo-market-card {
  position: relative;
  padding: 22px 24px;
  border: 1px solid var(--kamo-panel-border);
  border-radius: var(--kamo-r-pad);
  background: var(--kamo-gold-faint);
  display: flex;
  flex-direction: column;
  gap: 6px;
  transition: border-color var(--dur-base) var(--ease-standard),
              background var(--dur-base) var(--ease-standard),
              transform var(--dur-base) var(--ease-emphasised);
}
.kamo-market-card:hover {
  border-color: var(--kamo-gold-soft);
  background: color-mix(in srgb, var(--kamo-gold) 16%, transparent);
  transform: translateY(-2px);
}
.kamo-market-card:hover .kamo-market-card__stat-label {
  color: var(--kamo-gold-soft);
}
@media (prefers-reduced-motion: reduce) {
  .kamo-market-card {
    transition: border-color var(--dur-base), background var(--dur-base);
  }
  .kamo-market-card:hover {
    transform: none;
  }
}
/* The stat is the headline figure — pin it to the card bottom (so figures align
   across the row) and give the value real serif weight over a quiet mono caption. */
.kamo-market-card__stat {
  margin-top: auto;
  padding-top: 14px;
  border-top: 1px solid var(--kamo-rule);
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.kamo-market-card__stat-value {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: 24px;
  line-height: 1.1;
  letter-spacing: var(--track-tight);
  color: var(--kamo-gold-text);
  font-variant-numeric: tabular-nums;
}
.kamo-market-card__stat-label {
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--kamo-fg-mute);
  transition: color var(--dur-base) var(--ease-standard);
}
/* Visual market cards — a representative listing cover behind a scrim, light text
   on both skins (the scrim is always dark). */
.kamo-market-card--photo {
  min-height: 250px;
  background-color: var(--kamo-bg-deep);
  background-size: cover;
  background-position: center;
  border-color: transparent;
  overflow: hidden;
  isolation: isolate;
}
.kamo-market-card--photo::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg, rgba(7, 9, 13, 0.18) 0%, rgba(7, 9, 13, 0.82) 100%);
  transition: background var(--dur-base) var(--ease-standard);
}
.kamo-market-card--photo:hover {
  background-color: var(--kamo-bg-deep);
  border-color: var(--kamo-gold-soft);
}
.kamo-market-card--photo:hover::before {
  background: linear-gradient(180deg, rgba(7, 9, 13, 0.26) 0%, rgba(7, 9, 13, 0.88) 100%);
}
.kamo-market-card--photo .kamo-h2 {
  color: #f3efe8;
}
.kamo-market-card--photo .kamo-region {
  color: rgba(243, 239, 232, 0.72);
}
.kamo-market-card--photo .kamo-body-dim {
  color: rgba(243, 239, 232, 0.82) !important;
}
.kamo-market-card--photo .kamo-market-card__stat {
  border-top-color: rgba(243, 239, 232, 0.22);
}
.kamo-market-card--photo .kamo-market-card__stat-value {
  color: #dcc08f;
}
.kamo-market-card--photo .kamo-market-card__stat-label {
  color: rgba(243, 239, 232, 0.6);
}
.kamo-market-card--photo:hover .kamo-market-card__stat-label {
  color: rgba(243, 239, 232, 0.78);
}
/* Homepage "How we work" — de-boxed editorial capability columns. A single
   hairline left rule (warms to gold on hover) replaces the boxy fill+frame;
   the brand gold comes from the 01–06 numbered indices set in the JSX. */
.kamo-cap-card {
  display: flex;
  flex-direction: column;
  padding: 4px 0 4px 18px;
  border-inline-start: 1px solid var(--kamo-rule);
  transition: border-color var(--dur-fast) var(--ease-standard);
}
.kamo-cap-card:hover {
  border-left-color: var(--kamo-gold-soft);
}
@media (max-width: 720px) {
  .kamo-cap-card {
    padding-left: 14px;
  }
}

.kamo-market-card--featured {
  padding: clamp(24px, 4vw, 40px);
  margin-bottom: 16px;
  border-inline-start: 3px solid var(--kamo-gold);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 24px;
  align-items: center;
}
.kamo-market-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));
  gap: 12px;
}

.kamo-developer-chip {
  padding: 16px 20px;
  border: 1px solid var(--kamo-panel-border);
  border-radius: var(--kamo-r-hair);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: border-color var(--dur-fast), background var(--dur-fast);
  cursor: default;
}
.kamo-developer-chip:hover {
  border-color: var(--kamo-gold-soft);
  background: var(--kamo-gold-faint);
}
.kamo-developer-chip__name {
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: var(--track-body);
  text-transform: uppercase;
  color: var(--kamo-fg-dim);
  transition: color var(--dur-fast);
}
.kamo-developer-chip:hover .kamo-developer-chip__name {
  color: var(--kamo-gold-text);
}
.kamo-developer-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 12px;
}

/* Content (location/developer/compound/insight) SPA pages: read-more + FAQ. */
.content-readmore > summary,
.content-faq > summary {
  cursor: pointer;
  list-style: none;
  font-family: var(--font-mono);
  letter-spacing: var(--track-body);
  color: var(--kamo-gold-text);
}
.content-readmore > summary::-webkit-details-marker,
.content-faq > summary::-webkit-details-marker {
  display: none;
}
.content-readmore > summary {
  font-size: 11px;
  text-transform: uppercase;
  padding: 6px 0;
}
.content-faq {
  border-bottom: 1px solid var(--kamo-panel-border);
}
/* FAQ questions read as editorial serif, not terminal mono */
.content-faq > summary {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: 17px;
  line-height: 1.35;
  letter-spacing: var(--track-tight);
  color: var(--kamo-fg);
  /* Logical (was padding: 15px 24px 15px 0): the "+" marker below reserves
     room at the *end* of the line, whichever edge that is per direction. */
  padding-block: 15px;
  padding-inline: 0 24px;
  position: relative;
  transition: color var(--dur-fast) var(--ease-standard);
}
.content-faq > summary::after {
  content: '+';
  position: absolute;
  /* Logical (was right: 2px) so the marker stays at the line-end edge in RTL. */
  inset-inline-end: 2px;
  top: 50%;
  transform: translateY(-50%);
  font-family: var(--font-serif);
  font-size: 18px;
  color: var(--kamo-gold);
  transition: transform var(--dur-base) var(--ease-emphasised);
}
.content-faq[open] > summary {
  color: var(--kamo-gold-text);
}
.content-faq[open] > summary::after {
  transform: translateY(-50%) rotate(45deg);
}
.content-faq > p {
  margin: 0 0 16px;
  font-family: var(--font-sans);
  font-size: 13.5px;
  line-height: 1.7;
  max-width: 64ch;
}

/* Developer partner logo wall (homepage + /about). Each logo is rendered as a
   CSS-masked monochrome SILHOUETTE: the asset's alpha shape is painted with a
   theme-aware ink and tinted gold on hover. Source colour is irrelevant, so
   every mark reads identically on both themes (no "white logo vanishes on the
   light theme" failure). Missing logos fall back to the .kamo-developer-chip__name
   wordmark, so the wall is always presentable. */
.kamo-partner-logos {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: clamp(12px, 2vw, 20px);
}
.kamo-partner-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 84px;
  padding: 18px 16px;
  border: 1px solid var(--kamo-panel-border);
  border-radius: var(--kamo-r-hair);
  text-decoration: none;
  transition: border-color var(--dur-base) var(--ease-emphasised),
              background var(--dur-base) var(--ease-emphasised),
              transform var(--dur-base) var(--ease-emphasised);
}
.kamo-partner-logo:hover {
  border-color: var(--kamo-gold-soft);
  background: var(--kamo-gold-faint);
  transform: translateY(-2px);
}
/* The mask box is uniform; `contain` fits each silhouette inside it, and the
   per-logo --logo-scale evens out perceived cap-height across marks. */
.kamo-partner-logo__mark {
  width: 100%;
  max-width: 132px;
  height: 44px;
  display: block;
  background-color: var(--kamo-fg-dim);
  transform: scale(var(--logo-scale, 1));
  -webkit-mask-image: var(--logo-src);
  mask-image: var(--logo-src);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  transition: background-color var(--dur-base) var(--ease-emphasised),
              transform var(--dur-base) var(--ease-emphasised);
}
.kamo-partner-logo:hover .kamo-partner-logo__mark {
  background-color: var(--kamo-gold);
  transform: scale(calc(var(--logo-scale, 1) * 1.04));
}
.kamo-partner-logo .kamo-developer-chip__name {
  text-align: center;
  font-size: 16px;
  font-weight: 500;
  letter-spacing: var(--track-wide);
  color: var(--kamo-fg-dim);
  transition: color var(--dur-base) var(--ease-emphasised);
}
.kamo-partner-logo:hover .kamo-developer-chip__name {
  color: var(--kamo-gold-text);
}
@media (prefers-reduced-motion: reduce) {
  .kamo-partner-logo:hover {
    transform: none;
  }
  .kamo-partner-logo:hover .kamo-partner-logo__mark {
    transform: scale(var(--logo-scale, 1));
  }
}

.kamo-contact-detail {
  border-inline-start: 1px solid var(--kamo-gold-soft);
  padding-left: 16px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.kamo-link-plain {
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--kamo-fg);
  text-decoration: none;
  transition: color var(--dur-fast);
}
.kamo-link-plain:hover {
  color: var(--kamo-gold-text);
}

.kamo-field {
  appearance: none;
  width: 100%;
  box-sizing: border-box;
  outline: none;
  background: rgba(232, 228, 220, 0.04);
  border: 1px solid var(--kamo-panel-border);
  border-radius: var(--kamo-r-hair);
  color: var(--kamo-fg);
  font-family: var(--font-sans);
  font-weight: 300;
  font-size: 14px;
  letter-spacing: var(--track-body);
  padding: 10px 11px;
  transition: border-color var(--dur-fast);
}
.kamo-field:focus {
  border-color: var(--kamo-gold-soft);
}
.kamo-field--textarea {
  resize: vertical;
  min-height: 96px;
}

.kamo-stat-bar {
  border-top: 1px solid var(--kamo-rule);
  border-bottom: 1px solid var(--kamo-rule);
  overflow: hidden;
}

.kamo-stat-bar__inner {
  max-width: 1120px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
}

/* Homepage credibility band: a clean 3-up that stacks to one column on phones
   (the 3 narrow columns crowd the values + subs below ~640px). */
.kamo-home__stats .kamo-stat-bar__inner {
  grid-template-columns: repeat(3, 1fr);
}
@media (max-width: 640px) {
  .kamo-home__stats .kamo-stat-bar__inner {
    grid-template-columns: 1fr;
  }
  .kamo-home__stats .kamo-stat-cell {
    border-inline-end: none;
  }
  .kamo-home__stats .kamo-stat-cell:not(:last-child) {
    border-bottom: 1px solid var(--kamo-rule);
  }
}

/* Brand credibility band (home + about): the flat hairline version read as
   plain — lift the three cells into distinct gold-edged panels and give the
   type a deliberate rhythm: mono eyebrow on top (flex `order`, so the markup
   and the property-detail stat bar stay untouched), serif display value with
   negative tracking, then a relaxed sub line. (.kamo-stat-bar__inner in the
   selector outranks the joined-border base rules and the 640px home
   overrides above.) */
.kamo-stat-bar--brand {
  border-top: none;
  border-bottom: none;
  /* The hairline version sat flush against the hero as a joined band; the
     floating cards need air above (vs the hero) and a little below so the
     panel shadow isn't clipped by the next section's edge. */
  padding-top: clamp(40px, 6vw, 72px);
  padding-bottom: clamp(12px, 2vw, 24px);
}
.kamo-stat-bar--brand .kamo-stat-bar__inner {
  /* BRAND_STATS gained a 4th entry in the 2026-07-12 copy pass — 4-across
     desktop, 2×2 tablet (below), 1-col mobile (680px query further down). */
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(12px, 2vw, 20px);
  padding: 0 clamp(16px, 4vw, 40px);
}
@media (max-width: 960px) {
  .kamo-stat-bar--brand .kamo-stat-bar__inner {
    grid-template-columns: repeat(2, 1fr);
  }
}
.kamo-stat-bar--brand .kamo-stat-bar__inner .kamo-stat-cell {
  gap: 0;
  padding: clamp(20px, 3vw, 30px) clamp(18px, 2.4vw, 30px) clamp(22px, 3.2vw, 34px);
  border: 1px solid var(--kamo-panel-border);
  border-top: 2px solid var(--kamo-gold-soft);
  border-radius: var(--kamo-r-hair);
  background: linear-gradient(165deg, var(--kamo-gold-faint) 0%, rgba(232, 228, 220, 0.02) 62%);
  box-shadow: var(--kamo-shadow-panel);
}
.kamo-stat-bar--brand .kamo-stat-bar__inner .kamo-stat-cell__label {
  order: -1;
  font-size: 10px;
  letter-spacing: var(--track-label);
  margin-bottom: clamp(12px, 1.6vw, 18px);
}
.kamo-stat-bar--brand .kamo-stat-bar__inner .kamo-stat-cell__value {
  font-size: clamp(26px, 3vw, 40px);
  line-height: 1.05;
  margin-bottom: clamp(8px, 1.2vw, 12px);
}
.kamo-stat-bar--brand .kamo-stat-bar__inner .kamo-stat-cell__sub {
  font-size: 12px;
  line-height: 1.6;
  letter-spacing: var(--track-tight);
  max-width: 30ch;
  margin-top: 0;
}
/* Phones: stack to one column (covers /about too — the home-only 640px rule
   above doesn't reach it). */
@media (max-width: 680px) {
  .kamo-stat-bar--brand .kamo-stat-bar__inner {
    grid-template-columns: 1fr;
  }
}

/* ===== Property detail — map hero + market-label panel =================== */
/* Location-section map (relocated out of the hero into its own framed panel). */
.property-detail__map-wrap {
  position: relative;
  height: clamp(260px, 38vh, 420px);
  margin-top: 18px;
  border: 1px solid var(--kamo-rule);
  border-radius: var(--kamo-r-pad);
  overflow: hidden;
}
.property-detail__map {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.property-detail__map.map-canvas,
.property-detail__map .map-canvas {
  width: 100%;
  height: 100%;
}
/* Compound editorial story — the listing's project narrative, pulled from the
   compounds taxonomy and linked through to the full compound page. */
.property-detail__compound {
  padding-top: 4px;
}
.property-detail__compound-title {
  margin: 0 0 14px;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: clamp(20px, 2.4vw, 28px);
  line-height: 1.15;
}
.property-detail__compound-link {
  display: inline-block;
  margin-top: 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: var(--track-wide);
  color: var(--kamo-gold-text);
  text-decoration: none;
}
.property-detail__compound-link:hover {
  text-decoration: underline;
}

/* Full-screen photo lightbox. */
.property-detail__lightbox {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(16px, 5vw, 64px);
  background: rgba(5, 6, 9, 0.94);
  backdrop-filter: blur(4px);
  animation: kamoFadeIn var(--dur-fast, 0.18s) ease;
}
.property-detail__lightbox-figure {
  margin: 0;
  max-width: min(1200px, 92vw);
  max-height: 88vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}
.property-detail__lightbox-img {
  max-width: 100%;
  max-height: 82vh;
  object-fit: contain;
  border-radius: var(--kamo-r-hair, 2px);
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6);
}
/* Shown only while the full-size image is still decoding (centred in the
   full-screen lightbox); unmounts on load. */
.property-detail__lightbox-spinner {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 2px solid rgba(243, 239, 232, 0.22);
  border-top-color: var(--kamo-gold);
  animation: kamoSpin 0.8s linear infinite;
  pointer-events: none;
}
@keyframes kamoSpin {
  to {
    transform: translate(-50%, -50%) rotate(360deg);
  }
}
@media (prefers-reduced-motion: reduce) {
  .property-detail__lightbox-spinner {
    animation: none;
  }
}
.property-detail__lightbox-count {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: var(--track-wider);
  color: rgba(243, 239, 232, 0.66);
}
.property-detail__lightbox-close {
  position: absolute;
  top: clamp(12px, 3vw, 28px);
  inset-inline-end: clamp(12px, 3vw, 28px);
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  color: #f3efe8;
  font-size: 18px;
  cursor: pointer;
  transition: background var(--dur-fast);
}
.property-detail__lightbox-close:hover {
  background: rgba(255, 255, 255, 0.18);
}
.property-detail__lightbox-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 52px;
  height: 52px;
  border: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  color: #f3efe8;
  font-size: 30px;
  line-height: 1;
  cursor: pointer;
  transition: background var(--dur-fast);
}
.property-detail__lightbox-nav:hover {
  background: rgba(255, 255, 255, 0.18);
}
.property-detail__lightbox-nav--prev {
  inset-inline-start: clamp(8px, 3vw, 32px);
}
.property-detail__lightbox-nav--next {
  inset-inline-end: clamp(8px, 3vw, 32px);
}
/* Mirror the ‹/› glyphs to match: under RTL, --prev sits on the physical
   right (its logical "start") and should still point toward it, same
   pattern as .khero-btn__arrow / .ks-btn__arrow below. */
[dir='rtl'] .property-detail__lightbox-nav {
  transform: translateY(-50%) scaleX(-1);
}
.property-detail__stats {
  /* Flex, not auto-fit grid: grid's auto-repeat can't take intrinsic minimums,
     so the nowrap full price ("EGP 109,000,000") used to overflow its track and
     collide with the bedrooms cell at tablet widths. Flex sizes each cell to
     its content and wraps whole cells to the next row instead. */
  display: flex;
  flex-wrap: wrap;
}
.property-detail__stats .kamo-stat-cell {
  flex: 1 1 auto;
}
/* Full prices run long — smaller clamp than the other stat values, no wrap. */
.property-detail__stats .kamo-stat-cell__value--price {
  font-size: clamp(24px, 3vw, 36px);
  white-space: nowrap;
}
.property-detail__description {
  margin: 0;
  line-height: 1.75;
  font-size: 14px;
  white-space: pre-line;
}
.property-detail__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.property-detail__chip {
  padding: 5px 12px;
  border-radius: 20px;
  border: 1px solid var(--kamo-gold-soft);
  background: var(--kamo-gold-faint);
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--kamo-gold-text);
}
.property-detail__video {
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 0;
  border-radius: var(--kamo-r-pad);
}
.property-detail__location {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.property-detail__price {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: clamp(22px, 2.2vw, 28px);
  color: var(--kamo-gold-text);
  line-height: 1.15;
  overflow-wrap: break-word;
}
/* USD reference line under the exact native price (dual-currency frame). */
.property-detail__price-ref {
  display: block;
  font-family: var(--font-sans);
  font-size: 13px;
  letter-spacing: var(--track-body);
  color: var(--kamo-fg-dim);
  margin-top: 2px;
}
/* Cost-of-ownership line: quiet but adjacent to the price, tooltip on hover. */
.property-detail__price-sc {
  display: block;
  font-family: var(--font-sans);
  font-size: 12px;
  letter-spacing: var(--track-body);
  color: var(--kamo-fg-dim);
  margin-top: 8px;
  cursor: help;
  text-decoration: underline dotted rgba(201, 165, 116, 0.45);
  text-underline-offset: 3px;
}
.property-detail__badges {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  border-top: 1px solid var(--kamo-rule);
  padding-top: 14px;
}
.property-detail__badge {
  padding: 3px 10px;
  border-radius: var(--kamo-r-hair);
  border: 1px solid var(--kamo-panel-border);
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--kamo-fg-dim);
}
.property-detail__badge--gold {
  border-color: var(--kamo-gold-soft);
  color: var(--kamo-gold-text);
}
.property-detail__panel-section {
  border-top: 1px solid var(--kamo-rule);
  padding-top: 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.property-detail__downloads {
  gap: 10px;
}
.property-detail__doc-link {
  text-decoration: none;
}
.property-detail__plan {
  display: flex;
  flex-direction: column;
}
/* Unit mix (off-plan products): label+spec | area | from-price per row */
.property-detail__units {
  display: flex;
  flex-direction: column;
}
.property-detail__unit-row {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: baseline;
  gap: 16px;
  padding: 10px 0;
  border-bottom: 1px solid var(--kamo-rule);
}
.property-detail__unit-label {
  font-size: 13px;
  color: var(--kamo-fg);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.property-detail__unit-spec {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--kamo-fg-mute);
}
@media (max-width: 560px) {
  .property-detail__unit-row {
    grid-template-columns: 1fr auto;
  }
  .property-detail__unit-row .kamo-coord {
    display: none;
  }
}
.property-detail__plan-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 12px;
  padding: 8px 0;
  border-bottom: 1px solid var(--kamo-rule);
}
.property-detail__plan-row--3 {
  grid-template-columns: 1fr auto auto;
}
.property-detail__plan-notes {
  margin: 10px 0 0;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--kamo-fg-mute);
  line-height: 1.5;
}
.property-detail__doc-done {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--kamo-gold-text);
}
.property-detail__doc-modal {
  position: fixed;
  inset: 0;
  z-index: 500;
  background: rgba(7, 9, 13, 0.72);
  backdrop-filter: blur(6px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.property-detail__doc-panel {
  width: 100%;
  max-width: 420px;
  padding: 28px;
  background: var(--kamo-panel-bg-strong);
  border: 1px solid var(--kamo-panel-border);
  border-radius: var(--kamo-r-pad);
  box-shadow: var(--kamo-shadow-modal);
}
.property-detail__doc-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.property-detail__doc-actions {
  display: flex;
  gap: 12px;
  justify-content: flex-end;
}
.property-detail__form-error {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--kamo-error);
}
.property-detail__state {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 60vh;
}
.property-detail__state--column {
  flex-direction: column;
  gap: 16px;
}

.enquiry-listing-context {
  margin: 0 0 12px;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: 15px;
  line-height: 1.35;
  color: var(--kamo-gold-text);
}

@media (max-width: 720px) {
  .ks-sticky-enquire {
    display: flex;
    position: fixed;
    left: 0;
    right: 0;
    /* Sits flush on top of the bottom nav — was 56px, 5px short of the real
       61px nav, so it tucked behind it. Single source of truth now. */
    bottom: var(--mobile-nav-h);
    z-index: 105;
    padding: 10px 16px;
    gap: 10px;
    background: var(--kamo-panel-bg-strong);
    border-top: 1px solid var(--kamo-panel-border);
    backdrop-filter: blur(12px);
  }
  /* The footer follows the article and carries the full fixed-chrome reserve
     (.kamo-app-shell--property footer rule below), so the article only needs a
     little air before the footer — not the whole bar + nav stack. */
  .property-detail {
    padding-bottom: 32px;
  }
  .ks-sticky-enquire .kamo-btn,
  .ks-sticky-enquire .cta-action {
    flex: 1;
    justify-content: center;
    min-height: 44px;
    touch-action: manipulation;
  }
  .kamo-document-main .kamo-field,
  .kamo-document-main .kamo-field--textarea {
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
  }
}

.ks-sticky-enquire {
  display: none;
}

/* Collapsible tool/disclosure (calculators, documents) — used on mobile so the
   page reads calmly at rest. The summary is a real 44px+ button. */
.kamo-disclosure {
  display: flex;
  flex-direction: column;
}
.kamo-disclosure__toggle {
  width: 100%;
  min-height: 52px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 12px 0;
  background: transparent;
  border: 0;
  border-top: 1px solid var(--kamo-rule);
  color: var(--kamo-fg);
  cursor: pointer;
  text-align: start;
  touch-action: manipulation;
}
.kamo-disclosure__titles {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}
.kamo-disclosure__title {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: 15px;
  line-height: 1.1;
  color: var(--kamo-fg);
}
.kamo-disclosure__hint {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--kamo-fg-mute);
}
.kamo-disclosure__chevron {
  flex-shrink: 0;
  color: var(--kamo-gold-text);
  transition: transform var(--dur-base) var(--ease-standard);
}
.kamo-disclosure--open .kamo-disclosure__chevron {
  transform: rotate(180deg);
}
.kamo-disclosure__panel {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 6px 0 18px;
}
@media (prefers-reduced-motion: reduce) {
  .kamo-disclosure__chevron {
    transition: none;
  }
}

@media (max-width: 720px) {
  /* Sticky: one primary action + a small WhatsApp icon (was two equal CTAs). */
  .ks-sticky-enquire > button {
    flex: 1;
    min-height: 46px;
    justify-content: center;
    touch-action: manipulation;
  }
  .ks-sticky-enquire a.ks-sticky-enquire__wa {
    flex: 0 0 48px;
    min-width: 48px;
    width: 48px;
    padding: 0;
  }

  /* Location map: shorter, and non-interactive via a tap-to-Maps cover so the
     page scrolls over it instead of the map panning. */
  .property-detail__map-wrap {
    height: clamp(160px, 26vh, 210px);
  }
  .property-detail__map-cover {
    position: absolute;
    inset: 0;
    z-index: 2;
    display: flex;
    align-items: flex-end;
    justify-content: flex-end;
    padding: 12px;
    text-decoration: none;
    -webkit-tap-highlight-color: transparent;
  }
  .property-detail__map-cover-chip {
    display: inline-flex;
    align-items: center;
    min-height: 36px;
    padding: 8px 14px;
    border-radius: 999px;
    border: 1px solid rgba(243, 239, 232, 0.4);
    background: rgba(7, 9, 13, 0.62);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    color: #f3efe8;
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: var(--track-wider);
    text-transform: uppercase;
  }


  /* Location card link — the heavy map sits behind a "Show map" disclosure. */
  .property-detail__map-link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    margin-top: 12px;
    color: var(--kamo-gold-text);
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: var(--track-wider);
    text-transform: uppercase;
    text-decoration: none;
  }

  /* Sticky bar: keep the price in view through the long scroll. */
  .ks-sticky-enquire__price {
    flex: 0 0 auto;
    align-self: center;
    padding-inline-start: 2px;
    font-family: var(--font-serif);
    font-weight: 300;
    font-size: 17px;
    line-height: 1;
    color: var(--kamo-gold-text);
    white-space: nowrap;
  }
}

/* ===== Explore hub (/explore) ============================================ */
.kamo-explore {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
.kamo-explore > .kamo-root {
  width: 100%;
  height: 100%;
}
.kamo-explore__listings-slot {
  position: absolute;
  z-index: 10;
  pointer-events: none;
}
.kamo-explore__listings-slot > .listings-panel {
  pointer-events: auto;
}

/* Network: manifest-slot pattern (right rail in LTR; mirrors under RTL) */
.kamo-explore--network .kamo-explore__listings-slot {
  inset-inline-end: clamp(24px, 5vw, 56px);
  top: 50%;
  transform: translateY(-50%);
  width: min(360px, calc(100vw - 48px));
  max-width: min(360px, 42vw);
  max-height: min(78vh, 640px);
}

/* SPA fallback for /egypt/:slug (static HTML remains canonical). */
.seo-guide-spa {
  max-width: 42rem;
  margin: 0 auto;
  padding: clamp(24px, 5vw, 48px);
  font-family: var(--font-sans);
  color: var(--kamo-fg);
}
.seo-guide-spa__brand {
  font-family: var(--font-serif);
  font-weight: 300;
  color: var(--kamo-fg);
  text-decoration: none;
}
.seo-guide-spa__cta-primary {
  font-weight: 500;
  color: var(--kamo-accent, #c9a574);
}

/* Region detail: sub-area picker band */
.kamo-explore--region-detail {
  --city-detail-ui-bottom: clamp(80px, 12vh, 130px);
  --city-detail-panel-max-h: min(42vh, 340px);
}
.kamo-explore--region-detail .kamo-explore__listings-slot {
  left: clamp(24px, 5vw, 56px);
  right: clamp(24px, 5vw, 56px);
  bottom: var(--city-detail-ui-bottom);
  top: auto;
  transform: none;
  width: auto;
  max-width: none;
  max-height: var(--city-detail-panel-max-h);
}

/* City detail: market-label-slot pattern (bottom band) */
.kamo-explore--city-detail {
  --city-detail-ui-bottom: clamp(80px, 12vh, 130px);
  --city-detail-panel-max-h: min(44vh, 360px);
}
.kamo-explore--city-detail .kamo-explore__listings-slot {
  left: clamp(24px, 5vw, 56px);
  right: clamp(24px, 5vw, 56px);
  bottom: var(--city-detail-ui-bottom);
  top: auto;
  transform: none;
  width: auto;
  max-width: none;
  max-height: var(--city-detail-panel-max-h);
}

.listings-panel {
  display: flex;
  flex-direction: column;
  gap: 0;
  min-height: 0;
  max-height: inherit;
  padding: clamp(14px, 2vw, 18px) clamp(16px, 2.2vw, 20px);
  border-radius: var(--kamo-r-hair);
  background: var(--kamo-panel-bg-strong);
  border: 1px solid var(--kamo-panel-border);
  box-shadow: var(--kamo-panel-shadow);
  backdrop-filter: blur(13px);
  -webkit-backdrop-filter: blur(13px);
}
.listings-panel__search {
  width: 100%;
  margin-bottom: 10px;
  flex-shrink: 0;
  font-size: 13px;
}

/* ===== Watchlist ========================================================= */
.listings-panel__card-wrap {
  position: relative;
}
.watchlist-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr));
  gap: clamp(12px, 2vw, 20px);
}
/* List-row cards in this grid (watchlist + "Featured properties" on location/
   compound/developer pages): equalize heights across each row and pin the price
   to the bottom edge. */
.watchlist-grid .listings-panel__card-wrap {
  height: 100%;
}
.watchlist-grid .listings-panel__card {
  height: 100%;
}
.watchlist-grid .listings-panel__card-price {
  margin-top: auto;
  /* The floating pair sits at the bottom flex-end corner (.listings-panel__card-actions
     uses justify-content: flex-end, which follows direction — bottom-right in LTR,
     bottom-left in RTL), and the price is the bottom-most content — so it reserves
     the room the title used to (2026-07-25). Logical (was padding-right: 92px) so
     the reserved space tracks the pair under RTL too. */
  padding-inline-end: 92px;
}
.watchlist-btn {
  appearance: none;
  cursor: pointer;
  font-family: var(--font-sans);
  color: var(--kamo-gold-text);
  transition: color var(--dur-fast), background var(--dur-fast), border-color var(--dur-fast);
}
/* Card overlay actions — bottom-right (owner, 2026-07-25). They used to be
   pinned individually at top:10px, where on the row-layout cards they landed on
   the title. One flex container instead: the buttons keep their circle styling
   and the container decides where the pair sits, per card layout. */
.listings-panel__card-actions {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  gap: 6px;
  padding: 10px;
  /* The container spans the card, so it must not eat clicks meant for the
     card link underneath — only the buttons themselves are interactive. */
  pointer-events: none;
}
.listings-panel__card-actions > * {
  pointer-events: auto;
}
/* Inside the container they are flex children, not pinned overlays. The
   absolute positioning below still applies elsewhere (property-detail hero). */
.listings-panel__card-actions .watchlist-btn--icon,
.listings-panel__card-actions .listings-panel__card-wa {
  position: static;
}
/* Photo-on-top cards (explore grid, location/compound shelves): the card's own
   bottom-right is where the price sits, so the pair rides the bottom of the
   PHOTO instead. Mirrors the media box's aspect-ratio so it tracks any width. */
.kamo-featured-grid .listings-panel__card-actions {
  inset: 0 0 auto 0;
  aspect-ratio: 3 / 2;
}

/* Icon variant: overlay on a listing card */
.watchlist-btn--icon {
  position: absolute;
  top: 10px;
  inset-inline-end: 10px;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid var(--kamo-panel-border);
  background: var(--kamo-panel-bg-strong);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  box-shadow: var(--kamo-shadow-panel);
  font-size: 16px;
  line-height: 1;
}
.watchlist-btn--icon:hover {
  border-color: var(--kamo-gold-soft);
}
/* WhatsApp overlay on a listing card — same circle treatment as the heart,
   seated just inside it (heart: end 10px + 40px wide + 6px gap). Mirrors as a
   pair with .watchlist-btn--icon under RTL. */
.listings-panel__card-wa {
  position: absolute;
  top: 10px;
  inset-inline-end: 56px;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid var(--kamo-panel-border);
  background: var(--kamo-panel-bg-strong);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  box-shadow: var(--kamo-shadow-panel);
  color: var(--kamo-gold-text);
  line-height: 1;
}
.listings-panel__card-wa:hover {
  border-color: var(--kamo-gold-soft);
}
/* The 96px map-sidebar rows are too tight for a second floating circle — the
   WhatsApp CTA lives on the grid/featured/watchlist variants + detail page. */
.listings-panel__cards .listings-panel__card-wa {
  display: none;
}
.watchlist-btn--icon.is-saved {
  background: var(--kamo-gold-faint);
  border-color: var(--kamo-gold-soft);
}
/* Full variant: a button under the enquire CTA on property detail */
.watchlist-btn--full {
  width: 100%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 12px 22px;
  border: 1px solid var(--kamo-panel-border);
  border-radius: var(--kamo-r-hair);
  background: transparent;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
}
.watchlist-btn--full:hover {
  border-color: var(--kamo-gold-soft);
}
.watchlist-btn--full.is-saved {
  border-color: var(--kamo-gold-soft);
  background: var(--kamo-gold-faint);
}
.watchlist-btn__heart {
  font-size: 15px;
  line-height: 1;
}

/* Email-capture prompt */
.watchlist-modal {
  position: fixed;
  inset: 0;
  z-index: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}
.watchlist-modal__backdrop {
  position: absolute;
  inset: 0;
  border: 0;
  cursor: pointer;
  background: rgba(7, 9, 13, 0.62);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
[data-theme="light"] .watchlist-modal__backdrop {
  background: rgba(20, 15, 8, 0.55);
}
.watchlist-modal__panel {
  position: relative;
  z-index: 1;
  width: min(420px, 100%);
  padding: clamp(20px, 3vw, 28px);
  border-radius: var(--kamo-r-pad);
  background: var(--kamo-panel-bg-strong);
  border: 1px solid var(--kamo-panel-border);
  box-shadow: var(--kamo-shadow-modal);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}

/* ===== Status badge (sold / under contract) ============================== */
.status-badge {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: var(--kamo-r-hair);
  border: 1px solid currentColor;
  line-height: 1;
}
.status-badge--sold {
  color: var(--kamo-error);
  background: rgba(232, 138, 138, 0.12);
}
.status-badge--under_contract {
  color: var(--kamo-gold-text);
  background: var(--kamo-gold-faint);
}
/* ProjectCard's "Off-plan" chip (src/components/ProjectCard.tsx) — distinguishes
   off-plan cards from resale ones in a mixed /explore grid. Same treatment as
   under_contract (gold-on-faint) since it's informational, not an urgency
   signal. Positioned with a logical inset so it mirrors correctly under the
   ar locale without a separate [dir="rtl"] override. */
.status-badge--offplan {
  color: var(--kamo-gold-text);
  background: var(--kamo-gold-faint);
}
.project-card__badge {
  position: absolute;
  /* Bottom corner: the top of the media box belongs to the market label —
     at narrow card widths the two collided (owner 2026-07-24). */
  inset-block-end: 8px;
  inset-inline-end: 8px;
  z-index: 2;
}
/* Card variant: a bold full-width ribbon across the bottom of the cover (clears
   the watchlist heart top-right and the market label top-left) for FOMO. */
.listings-panel__card-status {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  top: auto;
  z-index: 2;
  text-align: center;
  border: 0;
  border-radius: 0;
  padding: 6px;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: var(--track-label);
}
.listings-panel__card-status.status-badge--sold {
  background: var(--kamo-error);
  color: #fff;
}
.listings-panel__card-status.status-badge--under_contract {
  background: var(--kamo-gold);
  color: #fff;
}
/* Dim unavailable cards but keep them legible + enquirable */
.listings-panel__card.is-unavailable .listings-panel__card-media {
  filter: grayscale(0.5);
  opacity: 0.78;
}
/* ===== Sold / under-offer FOMO banner (property detail) ================== */
.property-detail__fomo {
  max-width: 1120px;
  margin: 0 auto;
  padding: 16px clamp(24px, 5vw, 64px);
  display: flex;
  align-items: center;
  gap: 14px;
  border-bottom: 1px solid var(--kamo-rule);
}
.property-detail__fomo--sold { background: rgba(232, 138, 138, 0.08); }
.property-detail__fomo--under_contract { background: var(--kamo-gold-faint); }
.property-detail__fomo-tag {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  padding: 5px 10px;
  border-radius: var(--kamo-r-hair);
  color: #fff;
}
.property-detail__fomo--sold .property-detail__fomo-tag { background: var(--kamo-error); }
.property-detail__fomo--under_contract .property-detail__fomo-tag { background: var(--kamo-gold); }
.property-detail__fomo-copy {
  margin: 0;
  font-family: var(--font-serif);
  font-style: italic;
  font-size: clamp(15px, 1.6vw, 18px);
  line-height: 1.4;
  color: var(--kamo-fg);
}

/* Property page keeps one enquire CTA per device: hide the in-panel button on
   mobile (the sticky bottom bar is the mobile CTA); desktop hides the sticky. */
@media (max-width: 720px) {
  .property-detail__aside-enquire { display: none; }
}

/* ===== Per-listing price approximation =================================== */
.price-approx {
  margin-top: 8px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
/* Click-to-reveal trigger — the converter stays hidden until requested. */
.price-approx__toggle {
  appearance: none;
  align-self: flex-start;
  margin-top: 8px;
  background: transparent;
  border: 1px solid var(--kamo-panel-border);
  border-radius: var(--kamo-r-hair);
  color: var(--kamo-fg-dim);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  padding: 6px 10px;
  cursor: pointer;
  transition: color var(--dur-fast), border-color var(--dur-fast);
}
.price-approx__toggle:hover {
  color: var(--kamo-gold-text);
  border-color: var(--kamo-gold-soft);
}
.price-approx__row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.price-approx__value {
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--kamo-fg-dim);
}
.price-approx__select {
  appearance: none;
  background: transparent;
  border: 1px solid var(--kamo-panel-border);
  border-radius: var(--kamo-r-hair);
  color: var(--kamo-fg-dim);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-wide);
  padding: 2px 6px;
  cursor: pointer;
}
.price-approx__note {
  font-family: var(--font-mono);
  font-size: 8px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--kamo-fg-mute);
}

/* More-detail "Enquire" link button (matches the sibling text links) */
.listings-panel__more-detail-link-btn {
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--kamo-gold-text);
  cursor: pointer;
}
.listings-panel__more-detail-link-btn:hover {
  text-decoration: underline;
}

/* ===== Explore enquiry nudge (animated popup) ============================ */
.enquiry-nudge {
  position: fixed;
  left: clamp(16px, 4vw, 32px);
  bottom: clamp(16px, 4vh, 32px);
  z-index: 90;
  width: min(320px, calc(100vw - 32px));
  padding: 18px 20px 16px;
  border-radius: var(--kamo-r-pad);
  background: var(--kamo-panel-bg-strong);
  border: 1px solid var(--kamo-panel-border);
  box-shadow: var(--kamo-shadow-modal);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  animation: enquiryNudgeIn 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes enquiryNudgeIn {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: translateY(0); }
}
.enquiry-nudge__close {
  position: absolute;
  top: 8px;
  right: 8px;
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--kamo-fg-mute);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  padding: 4px;
}
.enquiry-nudge__close:hover { color: var(--kamo-gold-text); }
.enquiry-nudge__eyebrow {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: var(--track-widest);
  text-transform: uppercase;
  color: var(--kamo-gold-text);
}
.enquiry-nudge__text {
  font-family: var(--font-sans);
  font-size: 13px;
  line-height: 1.5;
  color: var(--kamo-fg-dim);
  margin: 8px 0 12px;
}
.enquiry-nudge__cta {
  appearance: none;
  background: transparent;
  border: 1px solid var(--kamo-gold-soft);
  border-radius: var(--kamo-r-hair);
  color: var(--kamo-gold-text);
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
  padding: 9px 16px;
  cursor: pointer;
  transition: background 0.2s ease;
}
.enquiry-nudge__cta:hover { background: var(--kamo-gold-faint); }
/* Desktop shows the full copy; the short variants are mobile-only (see below). */
.enquiry-nudge__text--short,
.enquiry-nudge__cta--short { display: none; }
@media (max-width: 720px) {
  /* Slim bar pinned under the top bar (owner, 2026-07-25). It used to float at a
     fixed offset above the bottom chrome, which left it hanging mid-screen
     between the listings sheet, the tab bar and the FAB — three things whose
     heights all vary. The top edge is the one stable anchor on this page, so it
     docks there and slides down instead of up. */
  .enquiry-nudge {
    left: 12px;
    right: 12px;
    width: auto;
    top: calc(env(safe-area-inset-top, 0px) + 64px);
    bottom: auto;
    z-index: 103;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 36px 12px 14px;
    animation-name: enquiryNudgeInTop;
  }
  @keyframes enquiryNudgeInTop {
    from { opacity: 0; transform: translateY(-18px); }
    to   { opacity: 1; transform: translateY(0); }
  }
  .enquiry-nudge__eyebrow { display: none; }
  .enquiry-nudge__text { margin: 0; flex: 1; font-size: 12px; line-height: 1.4; }
  .enquiry-nudge__text--full { display: none; }
  .enquiry-nudge__text--short { display: inline; }
  .enquiry-nudge__cta { flex-shrink: 0; padding: 8px 12px; }
  .enquiry-nudge__cta--full { display: none; }
  .enquiry-nudge__cta--short { display: inline; }
  .enquiry-nudge__close { top: 50%; right: 8px; transform: translateY(-50%); }
}
.listings-panel__body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-height: 0;
  flex: 1;
}
.listings-panel__sheet-handle {
  display: none;
}
.listings-panel__sheet-grip {
  display: block;
  width: 36px;
  height: 4px;
  margin: 0 auto 8px;
  border-radius: var(--kamo-r-hair);
  background: var(--kamo-gold-soft);
}
.listings-panel__sheet-handle {
  width: 100%;
  padding: 10px 12px 6px;
  border: 0;
  background: transparent;
  color: var(--kamo-fg);
  cursor: pointer;
  text-align: start;
}
.listings-panel__sheet-title {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-gold-text);
}
.listings-panel__sheet-chevron {
  float: right;
  font-size: 10px;
  color: var(--kamo-fg-mute);
}
[dir='rtl'] .listings-panel__sheet-chevron {
  float: left;
}
/* Same mirroring pattern as .khero-btn__arrow / .ks-text-cta__arrow: the
   glyph is a plain "←" (this label reads forward in LTR), so under RTL it
   gets flipped to point the way "back" actually reads. */
.listings-panel__back-arrow {
  display: inline-block;
}
[dir='rtl'] .listings-panel__back-arrow {
  transform: scaleX(-1);
}
.listings-panel__back {
  display: block;
  width: 100%;
  margin-bottom: 10px;
  padding: 8px 0;
  min-height: 44px;
  text-align: start;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-fg-mute);
  background: none;
  border: 0;
  cursor: pointer;
  touch-action: manipulation;
}
.listings-panel__back:hover {
  color: var(--kamo-gold-text);
}
.listings-panel__header-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  flex-shrink: 0;
}
.listings-panel__header {
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
}
@media (max-width: 720px) {
  .listings-panel__sheet-bar {
    display: flex;
    flex-direction: column;
    gap: 4px;
  }
  .listings-panel--sheet .listings-panel__sheet-handle {
    display: block;
  }
  .listings-panel__back--inline {
    margin: 8px 12px 0;
    width: calc(100% - 24px);
  }
  .listings-panel--sheet {
    padding-top: 0;
    /* Solid opaque bottom-sheet "box" so the map never bleeds through behind
       the listings; it grows to cover the map as the sheet expands. */
    background: var(--kamo-bg);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border-radius: 14px 14px 0 0;
  }
}
.listings-panel__eyebrow {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-gold-text);
}
.listings-panel__count {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-fg-mute);
}
.listings-panel__markets {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex-shrink: 0;
  max-height: min(28vh, 220px);
  overflow-y: auto;
  scrollbar-width: thin;
}
.listings-panel__markets li {
  padding-bottom: 10px;
  border-bottom: 1px solid var(--kamo-rule);
}
.listings-panel__markets .manifest-row.is-active {
  border-inline-start-color: var(--kamo-gold-soft);
  opacity: 1;
}
.listings-panel__areas {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex-shrink: 0;
  max-height: min(38vh, 280px);
  overflow-y: auto;
  scrollbar-width: thin;
}
.listings-panel__areas .manifest-row--area {
  min-height: 44px;
}
.listings-panel__areas .manifest-row.is-active,
.listings-panel__areas .manifest-row--area:hover {
  border-inline-start-color: var(--kamo-gold);
  opacity: 1;
}
.listings-panel__more-detail {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 0 4px;
  border-top: 1px solid var(--kamo-rule);
  flex-shrink: 0;
}
.listings-panel__more-detail-label {
  font-family: var(--font-mono);
  font-size: 8px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-fg-mute);
}
.listings-panel__more-detail-links {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 14px;
  font-size: 12px;
}
.listings-panel__more-detail-links a {
  color: var(--kamo-gold-text);
  text-decoration: none;
}
.listings-panel__more-detail-links a:hover {
  text-decoration: underline;
}
.marker--area-active .marker-dot--area {
  filter: drop-shadow(0 0 6px rgba(201, 165, 116, 0.85));
}
.marker--area-muted {
  opacity: 0.55;
}
.marker-label--area-active {
  fill: var(--kamo-gold);
  font-weight: 600;
}
.marker-label--area {
  fill: rgba(232, 228, 220, 0.92);
  paint-order: stroke fill;
  stroke: rgba(8, 9, 12, 0.75);
  stroke-width: 3px;
}
.marker-hit--area {
  cursor: pointer;
}
.marker-overlay--region-detail .marker-label--area {
  font-size: inherit;
}
.listings-panel__types {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  flex-shrink: 0;
}
.listings-panel__pill {
  padding: 6px 12px;
  border-radius: 20px;
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 8px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  border: 1px solid var(--kamo-panel-border);
  background: rgba(7, 9, 13, 0.45);
  color: var(--kamo-fg-dim);
  transition: all var(--dur-fast) var(--ease-standard);
  white-space: nowrap;
}
.listings-panel__pill.is-active {
  border-color: var(--kamo-gold);
  background: var(--kamo-gold);
  color: var(--kamo-bg);
}
.listings-panel__scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  padding-inline-end: 2px;
}
.listings-panel__status {
  margin: 0;
  padding: 16px 0;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-wide);
  color: var(--kamo-fg-mute);
  text-align: center;
}
.listings-panel__status--error {
  color: var(--kamo-error);
}
.listings-panel__cards {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.listings-panel__card {
  display: grid;
  grid-template-columns: 96px 1fr;
  gap: 12px;
  text-decoration: none;
  color: inherit;
  border: 1px solid var(--kamo-panel-border);
  border-bottom-width: 2px;
  border-radius: var(--kamo-r-pad);
  overflow: hidden;
  background: rgba(7, 9, 13, 0.35);
  transition:
    transform var(--dur-base) var(--ease-emphasised),
    box-shadow var(--dur-base) var(--ease-emphasised);
}
.listings-panel__card:hover {
  transform: translateY(-2px);
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.2);
}
.listings-panel__card-media {
  position: relative;
  min-height: 72px;
  /* Clip the hover photo-zoom (below) so the cover can scale within its frame. */
  overflow: hidden;
}
.listings-panel__card-market {
  position: absolute;
  top: 8px;
  /* Logical (was left: 8px) so the caption sits at the reading-start corner
     in RTL instead of pinning to the physical left under an Arabic layout. */
  inset-inline-start: 8px;
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
  color: var(--kamo-fg-mute);
  max-width: calc(100% - 16px);
  line-height: 1.3;
}
.listings-panel__card-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Editorial hover treatment mirroring the market cards: a subtle cover zoom plus
   a gold border warm-up. Scoped to img so the .kamo-cover-fallback gradient div
   (which shares the class) is never transformed. */
img.listings-panel__card-img {
  transform: scale(1);
  transition: transform 450ms var(--ease-emphasised);
  /* Gentle fade-in so covers settle in rather than popping. */
  animation: kamoFadeIn 400ms ease both;
}
.listings-panel__card:hover img.listings-panel__card-img {
  transform: scale(1.06);
}
.listings-panel__card:hover {
  border-color: var(--kamo-gold-soft);
}
@media (prefers-reduced-motion: reduce) {
  img.listings-panel__card-img {
    transition: none;
    animation: none;
    transform: none;
  }
  .listings-panel__card:hover img.listings-panel__card-img {
    transform: none;
  }
}
/* Quiet desktop-only abandonment reassurance (ExitReassurance). Bottom-right,
   above page content but below dialogs (modal 600). Desktop only, so it never
   collides with the mobile bottom chrome. */
.kamo-exit-reassure {
  position: fixed;
  right: clamp(16px, 3vw, 32px);
  bottom: clamp(16px, 3vw, 32px);
  z-index: 140;
  width: min(340px, calc(100vw - 32px));
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 20px 22px;
  background: var(--kamo-panel-bg-strong);
  border: 1px solid var(--kamo-panel-border);
  border-radius: var(--kamo-r-soft, 6px);
  box-shadow: var(--kamo-shadow-panel);
  backdrop-filter: blur(var(--kamo-panel-blur, 12px));
  -webkit-backdrop-filter: blur(var(--kamo-panel-blur, 12px));
  animation: kamo-exit-reassure-in 260ms var(--ease-standard, ease) both;
}
@keyframes kamo-exit-reassure-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .kamo-exit-reassure { animation: none; }
}
.kamo-exit-reassure__close {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  appearance: none;
  background: none;
  border: 0;
  color: var(--kamo-fg-dim);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}
.kamo-exit-reassure__close:hover { color: var(--kamo-fg); }
.kamo-exit-reassure__text {
  margin: 0;
  font-family: var(--font-serif, serif);
  font-size: 15px;
  line-height: 1.5;
  color: var(--kamo-fg);
}
.kamo-exit-reassure__actions {
  display: flex;
  gap: 10px;
  margin-top: 2px;
}

/* Calm market-tinted gradient shown by <ListingCover> when a photo 404s — far
   nicer than the broken-image glyph. Carries the original img class too, so it
   inherits the same box (absolute/full-bleed for cards, the hero frame, etc.). */
.kamo-cover-fallback {
  background:
    radial-gradient(
      120% 120% at 50% -10%,
      color-mix(in srgb, var(--cover-accent, var(--kamo-gold)) 20%, transparent),
      transparent 68%
    ),
    linear-gradient(155deg, var(--kamo-panel-bg-strong), var(--kamo-bg-deep));
}
.listings-panel__card-media--photo .listings-panel__card-market {
  color: var(--kamo-fg);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
  z-index: 1;
}
.listings-panel__card-body {
  /* Logical (was padding: 10px 12px 10px 0): the grid's auto-placed columns
     already flip under RTL, so "0" must stay the edge next to the media
     column (inline-start) and "12px" the outer edge (inline-end). */
  padding-block: 10px;
  padding-inline: 0 12px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.listings-panel__card-dev {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--kamo-fg-mute);
}
.listings-panel__card-title {
  margin: 0;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: 15px;
  line-height: 1.2;
  color: var(--kamo-fg);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.listings-panel__card-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: var(--track-body);
  color: var(--kamo-fg-dim);
}
.listings-panel__card-price {
  font-family: var(--font-serif);
  font-size: 14px;
  margin-top: 2px;
}
/* Second currency line under the price: quiet, sans, clearly approximate. */
.listings-panel__card-price-ref {
  display: block;
  font-family: var(--font-sans);
  font-size: 11px;
  letter-spacing: var(--track-body);
  opacity: 0.62;
  margin-top: 1px;
}

/* Homepage "Featured" grid — an editorial variant of the shared compact listing
   card, scoped to .kamo-featured-grid so the explore-sidebar card stays untouched.
   Reflows the 96px list-row into a vertical card: real 3:2 hero, scrimmed bottom-
   left market caption, editorial serif price, and a two-line title. */
/* Equalize the row: grid stretches the wraps; the card fills its wrap and the
   price pins to the bottom edge so all four cards read as one clean line. */
.kamo-featured-grid .listings-panel__card-wrap {
  height: 100%;
}
.kamo-featured-grid .listings-panel__card {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-width: 0;
  border-bottom-width: 1px;
}
.kamo-featured-grid .listings-panel__card-media {
  aspect-ratio: 3 / 2;
  min-height: 0;
  width: 100%;
}
/* Soft gradient so the caption reads over any photo edge — anchored to the top
   now, following the caption there (see card-market below). */
.kamo-featured-grid .listings-panel__card-media::after {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 56%;
  background: linear-gradient(to bottom, rgba(7, 9, 13, 0.62), transparent);
  pointer-events: none;
}
/* Lift the sold/under-offer bar to the top so it can't collide with the caption. */
.kamo-featured-grid .listings-panel__card-status {
  top: 0;
  bottom: auto;
}
/* Caption rides the TOP of the photo (2026-07-25). It used to sit bottom-left,
   which is where the WhatsApp/heart pair moved to — on a ~166px card the two
   collide, and reserving room for the buttons would have left the caption about
   56px to render "RED SEA · EGYPT" in. Swapping them keeps both readable at any
   card width; the scrim below follows the caption up. */
.kamo-featured-grid .listings-panel__card-market {
  top: 12px;
  bottom: auto;
  /* Logical (was left: 14px) — same reasoning as the base card-market rule. */
  inset-inline-start: 14px;
  font-size: 10px;
  letter-spacing: var(--track-wider);
  /* Caption sits on the dark scrim regardless of skin — keep it warm-white. */
  color: #e8e4dc;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
  z-index: 2;
}
.kamo-featured-grid .listings-panel__card-body {
  padding: 14px 16px 16px;
  gap: 6px;
  flex: 1;
  min-width: 0;
}
.kamo-featured-grid .listings-panel__card-title {
  font-size: 17px;
  line-height: 1.3;
  white-space: normal;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.kamo-featured-grid .listings-panel__card-facts {
  margin-top: 2px;
  color: var(--kamo-fg-dim);
}
.kamo-featured-grid .listings-panel__card-price {
  font-size: clamp(20px, 2.2vw, 24px);
  letter-spacing: var(--track-tight);
  line-height: 1.1;
  margin-top: auto;
  padding-top: 6px;
}

/* ── /explore properties-first grid ──────────────────────────────────────────
   The default view of /explore: a full-width editorial grid (reusing the
   .kamo-featured-grid card treatment) with the map demoted to a toggle. */
.explore-page {
  max-width: 1240px;
  margin: 0 auto;
  /* Deliberately tighter than --hero-pad-top: filters follow immediately
     under the title, so the page doesn't want the full hero air on top. */
  padding: clamp(20px, 4vw, 44px) clamp(16px, 4vw, 40px) 96px;
}
.explore-page__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px 28px;
  flex-wrap: wrap;
  margin-bottom: 26px;
}
.explore-page__intro {
  min-width: 0;
}
.explore-page__title {
  margin: 4px 0 8px;
}
.explore-page__sub {
  max-width: 540px;
  margin: 0;
  font-size: 14px;
  line-height: 1.6;
}
.explore-page__mapbtn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  flex-shrink: 0;
  padding: 11px 18px;
  border-radius: 999px;
  border: 1px solid var(--kamo-rule);
  background: transparent;
  color: var(--kamo-fg);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color 0.2s ease, color 0.2s ease;
}
.explore-page__mapbtn:hover {
  border-color: var(--kamo-gold);
  color: var(--kamo-gold-text);
}
.explore-page__mapbtn svg {
  width: 16px;
  height: 16px;
}
/* Off-plan projects have no coordinates (see the plan's out-of-scope note),
   so the map toggle is disabled while the Off-plan stage filter is active. */
.explore-page__mapbtn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
.explore-page__mapbtn:disabled:hover {
  border-color: var(--kamo-rule);
  color: var(--kamo-fg);
}

/* Head action group: the Filters toggle + Map view (Filters collapses the chips
   behind one button; the count badge keeps applied filters visible). */
.explore-page__head-actions {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
  flex-wrap: wrap;
}
.explore-page__filterbtn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  flex-shrink: 0;
  padding: 11px 18px;
  border-radius: 999px;
  border: 1px solid var(--kamo-rule);
  background: transparent;
  color: var(--kamo-fg);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color 0.2s ease, color 0.2s ease;
}
.explore-page__filterbtn:hover,
.explore-page__filterbtn.is-open {
  border-color: var(--kamo-gold);
  color: var(--kamo-gold-text);
}
.explore-page__filterbtn svg {
  width: 16px;
  height: 16px;
}
.explore-page__filterbtn-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--kamo-gold);
  color: var(--kamo-bg-deep);
  font-size: 10px;
  letter-spacing: 0;
}

/* Results header: count + sort on line 1, secondary actions on line 2 — the
   sort control can't get clipped off-screen and the email-alert prompt reads
   clearly instead of being squeezed into the count line. */
.explore-page__count-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.explore-page__count-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 16px;
  margin-top: 12px;
}
.explore-page__sort {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}
.explore-page__sort-select {
  max-width: 172px;
}

.explore-filters {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 22px;
  padding-bottom: 22px;
  border-bottom: 1px solid var(--kamo-rule);
}
/* Collapsed filters: the search box carries its own underline, so drop the
   container's second divider + its padding — no doubled line below the search. */
.explore-filters:not(.explore-filters--open) {
  padding-bottom: 0;
  border-bottom: none;
}
.explore-filters__search {
  max-width: 440px;
}
.explore-filters__row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}
.explore-filters__label {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
  color: var(--kamo-fg-dim);
  width: 52px;
  flex-shrink: 0;
}
.explore-filters__clear {
  /* No margin: the parent .explore-page__count-actions already spaces
     children with `gap` — a hardcoded margin-left here was redundant in LTR
     and would land on the wrong (outer) edge once the row mirrors under RTL. */
  padding: 4px 6px;
  border: 0;
  background: transparent;
  color: var(--kamo-gold-text);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  cursor: pointer;
}
.explore-filters__clear:hover {
  text-decoration: underline;
}

/* Compact filter dropdowns — one chip per category, the chip shows the active
   selection (and turns gold) so it's obvious what's applied. */
.explore-filters__dropdowns {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.explore-filter-dd {
  position: relative;
}
.explore-filter-dd__trigger {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 38px;
  padding: 8px 14px;
  border: 1px solid var(--kamo-panel-border);
  border-radius: 999px;
  background: transparent;
  color: var(--kamo-fg-dim);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
  transition: border-color var(--dur-fast), color var(--dur-fast), background var(--dur-fast);
}
.explore-filter-dd__trigger:hover {
  border-color: var(--kamo-gold-soft);
  color: var(--kamo-fg);
}
.explore-filter-dd__trigger.is-active {
  border-color: var(--kamo-gold-soft);
  background: var(--kamo-gold-faint);
  color: var(--kamo-gold-text);
}
.explore-filter-dd__trigger.is-open {
  border-color: var(--kamo-gold);
  color: var(--kamo-gold-text);
}
.explore-filter-dd__trigger:focus-visible {
  outline: 2px solid var(--kamo-gold);
  outline-offset: 2px;
}
.explore-filter-dd__chevron {
  flex-shrink: 0;
  opacity: 0.7;
  transition: transform var(--dur-fast);
}
.explore-filter-dd__trigger.is-open .explore-filter-dd__chevron {
  transform: rotate(180deg);
}
.explore-filter-dd__panel {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 40;
  min-width: 190px;
  max-width: min(280px, calc(100vw - 32px));
  max-height: 320px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 6px;
  background: var(--kamo-panel-bg-strong);
  border: 1px solid var(--kamo-panel-border);
  border-radius: var(--kamo-r-pad);
  box-shadow: var(--kamo-shadow-modal);
  backdrop-filter: blur(var(--kamo-panel-blur));
  -webkit-backdrop-filter: blur(var(--kamo-panel-blur));
}
/* Deliberately physical (not inset-inline-*): ExploreGrid.tsx's toggleOpen
   decides this class from the trigger's raw getBoundingClientRect().left vs
   window.innerWidth — a viewport-overflow check, not a text-direction one.
   That physical geometry is correct as-is under RTL too (flexbox already
   mirrors chip order, so a trigger's on-screen position reflects whichever
   edge it actually sits near) — converting this to a logical property would
   decouple it from the physical check that assigns it. Verified 2026-07-31,
   don't "fix" this to inset-inline-end. */
.explore-filter-dd__panel--right {
  left: auto;
  right: 0;
}
.explore-filter-dd__opt {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  min-height: 38px;
  padding: 9px 12px;
  border: 0;
  border-radius: var(--kamo-r-hair);
  background: transparent;
  color: var(--kamo-fg-dim);
  font-family: var(--font-sans);
  font-size: 13px;
  text-align: start;
  cursor: pointer;
  transition: background var(--dur-fast), color var(--dur-fast);
}
.explore-filter-dd__opt:hover {
  background: rgba(232, 228, 220, 0.06);
  color: var(--kamo-fg);
}
.explore-filter-dd__opt.is-selected {
  color: var(--kamo-gold-text);
}
.explore-filter-dd__opt svg {
  flex-shrink: 0;
  color: var(--kamo-gold-text);
}
/* Grouped sections inside the "Refine" disclosure (secondary facets):
   a quiet mono eyebrow per group, hairline rules between groups. */
.explore-filter-dd__group {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.explore-filter-dd__group + .explore-filter-dd__group {
  margin-top: 6px;
  padding-top: 8px;
  border-top: 1px solid var(--kamo-panel-border);
}
.explore-filter-dd__group-label {
  padding: 4px 12px 2px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--kamo-fg-dim);
  opacity: 0.7;
}

.explore-page__count {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: var(--track-wide);
  color: var(--kamo-fg-dim);
  margin: 0 0 16px;
}

.explore-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: clamp(16px, 2vw, 26px);
}

.explore-page__status {
  font-size: 14px;
  color: var(--kamo-fg-dim);
}
.explore-page__status--error {
  color: var(--kamo-error);
}
.explore-page__empty {
  padding: 56px 0;
  text-align: center;
}
.explore-page__empty-clear {
  margin-top: 12px;
  padding: 10px 18px;
  border: 1px solid var(--kamo-rule);
  border-radius: 999px;
  background: transparent;
  color: var(--kamo-gold-text);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color 0.2s ease;
}
.explore-page__empty-clear:hover {
  border-color: var(--kamo-gold);
}

/* Floating "back to grid" control over the map view. */
.explore-view-toggle {
  position: fixed;
  /* Clear the notch: the fixed header carries env(safe-area-inset-top), so the
     toggle that sits just below it must offset by the same inset or it slides
     under the header on a notched iPhone. */
  top: calc(74px + env(safe-area-inset-top, 0px));
  left: 50%;
  transform: translateX(-50%);
  z-index: 45;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  border-radius: 999px;
  border: 1px solid var(--kamo-rule);
  background: var(--kamo-bg-deep, rgba(7, 9, 13, 0.92));
  backdrop-filter: blur(8px);
  color: var(--kamo-fg);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
  cursor: pointer;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.28);
  transition: border-color 0.2s ease, color 0.2s ease;
}
.explore-view-toggle:hover {
  border-color: var(--kamo-gold);
  color: var(--kamo-gold-text);
}
.explore-view-toggle svg {
  width: 15px;
  height: 15px;
}

/* Keyboard focus rings for the Explore filter controls — these were missed by
   the site-wide :focus-visible gold-ring convention. Resting appearance is
   untouched; the ring only shows on keyboard focus. Heart button uses a tighter
   offset (and rounds with its circular shape) since it floats over a card photo. */
.listings-panel__pill:focus-visible,
.explore-page__mapbtn:focus-visible,
.explore-view-toggle:focus-visible,
.explore-filters__clear:focus-visible,
.explore-page__empty-clear:focus-visible {
  outline: 1px solid var(--kamo-gold);
  outline-offset: 3px;
}
.watchlist-btn:focus-visible {
  outline: 1px solid var(--kamo-gold);
  outline-offset: 2px;
}

@media (max-width: 600px) {
  .explore-grid {
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 12px;
  }
  .explore-filters__label {
    width: 100%;
  }
}

.manifest-explore-link {
  margin: 4px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--kamo-rule);
}
.manifest-explore-link a {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
  color: var(--kamo-gold-text);
  text-decoration: none;
}
.manifest-explore-link a:hover {
  text-decoration: underline;
}

@media (max-width: 720px) {
  .kamo-explore--network .kamo-explore__listings-slot {
    left: 8px;
    right: 8px;
    top: auto;
    bottom: var(--explore-chrome-bottom);
    transform: none;
    width: auto;
    max-width: none;
    max-height: min(46dvh, 360px);
  }
  .kamo-explore--region-detail {
    --city-detail-ui-bottom: var(--explore-chrome-bottom);
    --city-detail-panel-max-h: min(40dvh, 320px);
  }
  .kamo-explore--region-detail .kamo-explore__listings-slot {
    left: 16px;
    right: 16px;
  }
  .kamo-explore--city-detail,
  .kamo-explore--area-detail {
    --city-detail-ui-bottom: var(--explore-chrome-bottom);
    --city-detail-panel-max-h: min(44dvh, 360px);
  }
  .kamo-explore--city-detail .kamo-explore__listings-slot,
  .kamo-explore--area-detail .kamo-explore__listings-slot {
    left: 16px;
    right: 16px;
  }
  .kamo-explore--panel-collapsed .kamo-explore__listings-slot {
    max-height: none;
    pointer-events: none;
  }
  .kamo-explore--panel-collapsed .listings-panel--sheet {
    pointer-events: auto;
  }
  .listings-panel--collapsed {
    max-height: none;
    padding-bottom: 0;
  }
  .listings-panel--collapsed .listings-panel__body--hidden {
    display: none;
  }
  /* Expanded: the solid sheet grows tall to cover the map while browsing. */
  .listings-panel--expanded {
    max-height: min(92dvh, 760px);
  }
  /* Grow the slot to contain the expanded panel so the card list gets a real
     (scrollable) height instead of overflowing below the viewport. */
  .kamo-explore--panel-expanded .kamo-explore__listings-slot {
    max-height: min(92dvh, 760px);
  }
  /* Scroll the whole panel body on mobile so the card list (below the areas /
     type filters in region view) is reachable rather than squeezed to zero. */
  .listings-panel--expanded .listings-panel__body {
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
  }
  .listings-panel--expanded .listings-panel__scroll {
    flex: none;
    overflow: visible;
  }
  .listings-panel__sheet-handle {
    touch-action: manipulation;
  }
  .manifest-row,
  .listings-panel__pill,
  .listings-panel__card {
    touch-action: manipulation;
  }
  .manifest-row {
    min-height: 44px;
    padding-top: 4px;
    padding-bottom: 4px;
  }
  .listings-panel__pill {
    min-height: 44px;
    padding: 10px 12px;
  }
  .listings-panel__card {
    grid-template-columns: 80px 1fr;
    min-height: 44px;
  }
  .listings-panel {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
  .listings-panel__scroll {
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
  }
  .listings-panel__cards > .listings-panel__card {
    content-visibility: auto;
    contain-intrinsic-size: auto 88px;
  }
}

@media (max-height: 520px) {
  .kamo-explore--city-detail {
    --city-detail-ui-bottom: calc(56px + env(safe-area-inset-bottom, 0px));
    --city-detail-panel-max-h: min(28vh, 184px);
  }
}

/* ============================================================================
   WhatsApp floating CTA — primary contact channel for Egypt / the Gulf
============================================================================ */
.kamo-whatsapp-fab {
  position: fixed;
  right: clamp(16px, 4vw, 28px);
  bottom: clamp(16px, 4vw, 28px);
  z-index: 102;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  /* Brand register, not Meta green: midnight glass with a gold hairline ring
     and gold glyph — the same family as the header pills (both themes). */
  background: rgba(7, 9, 13, 0.82);
  border: 1px solid rgba(201, 165, 116, 0.55);
  color: #c9a574;
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  box-shadow: var(--kamo-shadow-cta);
  transition: transform var(--dur-fast) var(--ease-standard),
    box-shadow var(--dur-fast) var(--ease-standard),
    background var(--dur-fast) var(--ease-standard),
    color var(--dur-fast) var(--ease-standard),
    opacity var(--dur-fast) var(--ease-standard);
}
/* Homepage desktop: the cinematic hero carries its own WhatsApp CTA, so keep the
   floating FAB out of the hero and fade it in once the hero scrolls away (mirrors
   the mobile pattern, which hides the FAB on the homepage entirely). */
html.kamo-home-page:not(.kamo-past-hero) .kamo-whatsapp-fab {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
.kamo-whatsapp-fab:hover {
  transform: translateY(-2px) scale(1.04);
  background: #c9a574;
  color: #1a1005;
  border-color: #c9a574;
  box-shadow: 0 18px 46px rgba(0, 0, 0, 0.42);
}
.kamo-whatsapp-fab:focus-visible {
  outline: 2px solid var(--kamo-gold);
  outline-offset: 3px;
}
@media (max-width: 720px) {
  /* Lift above the bottom mobile nav bar. */
  .kamo-whatsapp-fab {
    bottom: calc(64px + env(safe-area-inset-bottom, 0px));
    width: 48px;
    height: 48px;
  }
  /* On property pages the full-width sticky "Enquire" bar already carries a
     WhatsApp action; the floating FAB only duplicates it and floats over the
     stat band / content. Hide it here (same call as the homepage). */
  body:has(.ks-sticky-enquire) .kamo-whatsapp-fab {
    display: none;
  }
}
/* The desktop exit-reassurance card owns the same bottom-right corner as the
   FAB (and carries its own WhatsApp action) — the FAB yields while it shows. */
body:has(.kamo-exit-reassure) .kamo-whatsapp-fab {
  display: none;
}
@media (max-width: 720px) {
  /* iOS zooms the page when focusing any input under 16px — keep form fields at
     16px on phones so the layout never jumps. */
  .enquiry-input,
  .enquiry-textarea,
  .cta-input,
  .listings-panel__search,
  .kamo-field {
    font-size: 16px;
  }
}
@media (prefers-reduced-motion: reduce) {
  .kamo-whatsapp-fab {
    transition: none;
  }
  .kamo-whatsapp-fab:hover {
    transform: none;
  }
}

/* ============================================================================
   Cookie-consent banner (Consent Mode v2)
============================================================================ */
.kamo-consent-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 130;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-4) var(--space-6);
  padding: var(--space-5) var(--space-6)
    calc(var(--space-5) + env(safe-area-inset-bottom, 0px));
  background: var(--kamo-panel-bg-strong);
  border-top: 1px solid var(--kamo-panel-border);
  backdrop-filter: blur(var(--kamo-panel-blur));
  -webkit-backdrop-filter: blur(var(--kamo-panel-blur));
  box-shadow: var(--kamo-shadow-panel);
}
@media (max-width: 719px) {
  /* Float the cookie strip ABOVE the tab bar rather than covering it — the nav
     must stay tappable while consent is pending. The nav owns the safe-area
     inset below it, so the banner drops its own bottom inset here. */
  .kamo-consent-banner {
    bottom: var(--mobile-nav-h);
    padding-bottom: var(--space-5);
  }
}
.kamo-consent-banner__text {
  margin: 0;
  max-width: 62ch;
  font-family: var(--font-sans);
  font-weight: 300;
  font-size: 12px;
  line-height: 1.5;
  letter-spacing: var(--track-body);
  color: var(--kamo-fg-dim);
}
.kamo-consent-banner__text a {
  color: var(--kamo-gold-text);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.kamo-consent-banner__actions {
  display: inline-flex;
  gap: var(--space-3);
  flex-shrink: 0;
}
.kamo-consent-btn {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  padding: 9px 16px;
  border-radius: var(--kamo-r-hair);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-standard),
    border-color var(--dur-fast) var(--ease-standard),
    color var(--dur-fast) var(--ease-standard);
}
.kamo-consent-btn--accept {
  background: var(--kamo-gold);
  border: 1px solid var(--kamo-gold);
  color: var(--kamo-bg-deep);
}
.kamo-consent-btn--accept:hover {
  background: #d8b888;
  border-color: #d8b888;
}
.kamo-consent-btn--decline {
  background: transparent;
  border: 1px solid var(--kamo-panel-border-cta);
  color: var(--kamo-fg-dim);
}
.kamo-consent-btn--decline:hover {
  color: var(--kamo-fg);
  border-color: var(--kamo-gold-soft);
}
.kamo-consent-btn:focus-visible {
  outline: 2px solid var(--kamo-gold);
  outline-offset: 2px;
}

/* ============================================================================
   Hero primary CTAs — "Speak to an advisor" / WhatsApp (money-first)
============================================================================ */
.cta-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin: 6px 0 14px;
}
.cta-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 11px 18px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  border-radius: var(--kamo-r-hair);
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-standard),
    border-color var(--dur-fast) var(--ease-standard),
    color var(--dur-fast) var(--ease-standard);
}
.cta-action--advisor {
  background: var(--kamo-gold);
  border: 1px solid var(--kamo-gold);
  color: var(--kamo-bg-deep);
}
.cta-action--advisor:hover {
  background: #d8b888;
  border-color: #d8b888;
}
.cta-action--whatsapp {
  background: transparent;
  border: 1px solid var(--kamo-panel-border-cta);
  color: var(--kamo-fg);
}
.cta-action--whatsapp:hover {
  border-color: var(--kamo-gold-soft);
  color: var(--kamo-gold-text);
}
/* Success-state WhatsApp continuation is the single primary action — gold-filled,
   not the ghost variant used in the hero CTA pair. */
.cta-action--whatsapp.cta-action--go {
  background: var(--kamo-gold);
  border-color: var(--kamo-gold);
  color: var(--kamo-bg-deep);
}
.cta-action--whatsapp.cta-action--go:hover {
  background: #d8b888;
  border-color: #d8b888;
  color: var(--kamo-bg-deep);
}
.cta-action:focus-visible {
  outline: 2px solid var(--kamo-gold);
  outline-offset: 2px;
}

/* ============================================================================
   Phase 1 — Mobile accessibility (≤720px)
   WCAG-oriented pass over the core flows (bottom nav, explore panel, property
   detail, map scrubber): touch targets ≥44px tall, body ≥15px, labels ≥12px,
   and muted text nudged from --kamo-fg-mute (fails AA) to --kamo-fg-dim.
   Appended last so it wins by source order. Gold stays the brand accent.
   ============================================================================ */
@media (max-width: 720px) {
  /* — Reading prose floor: 15px — */
  .kamo-body,
  .property-detail__desc,
  .kamo-document-main p {
    font-size: 15px;
    line-height: 1.6;
  }

  /* — Bottom nav: tight 40px targets, 12px legible labels, AA contrast — */
  .kamo-app-shell__mobile-nav {
    gap: 2px;
  }
  .kamo-app-shell__mobile-nav a,
  .kamo-app-shell__mobile-nav button {
    font-size: 12px;
    letter-spacing: normal;
    padding: 4px 4px;
    min-height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    white-space: nowrap;
    /* Bar is midnight glass in both themes — keep the light-on-dark text */
    color: rgba(243, 239, 232, 0.72);
  }
  .kamo-app-shell__mobile-nav a.is-active {
    color: #d3b07f;
  }

  /* — Explore panel: label legibility + clearer sheet grip — */
  .listings-panel__pill {
    font-size: 12px;
    letter-spacing: var(--track-body);
  }
  .listings-panel__sheet-title {
    font-size: 12px;
  }
  .listings-panel__sheet-chevron {
    font-size: 13px;
    color: var(--kamo-fg-dim);
  }
  .listings-panel__back {
    font-size: 12px;
    color: var(--kamo-fg-dim);
  }
  .listings-panel__sheet-grip {
    width: 48px;
    height: 5px;
    margin-bottom: 10px;
  }
  .listings-panel--sheet .listings-panel__sheet-handle {
    min-height: 44px;
  }
  .listings-panel__card-market {
    font-size: 9px; /* decorative overlay tag — kept compact, has scrim */
  }

  /* — Property detail: stat + plan label floors, AA on sub text — */
  .kamo-stat-cell__label {
    font-size: 12px;
  }
  .kamo-stat-cell__sub {
    font-size: 12px;
    color: var(--kamo-fg-dim);
  }
  .property-detail__plan-notes {
    font-size: 12px;
  }
  /* Sticky enquire bar was hidden on mobile by a later source-order rule
     (.ks-sticky-enquire { display:none } at ~L3623 overriding
     the @media display:flex). Restore it and guarantee a 48px CTA. The button
     carries no .kamo-btn class, so target the element directly. */
  .ks-sticky-enquire {
    display: flex;
  }
  .ks-sticky-enquire button,
  .ks-sticky-enquire .kamo-btn {
    flex: 1;
    min-height: 48px;
    justify-content: center;
    touch-action: manipulation;
  }

  /* — Map timeline scrubber: thin visual, ≥44px-tall hit area —
     box-sizing:content-box so padding adds to (not eats) the bar; the wider
     row is bounded by the small stage count so it won't overflow 375px. */
  .scrub-dots {
    gap: 4px;
  }
  .scrub-dot {
    box-sizing: content-box;
    width: 18px;
    height: 2px;
    padding: 21px 8px;
    background-clip: content-box;
  }
  .scrub-dot.is-active {
    width: 28px;
  }
}

/* ============================================================================
   Concierge-first homepage
   The bottom-left CTA panel is now the lead: a buyer-side headline + a single
   "Tell us what you're looking for" prompt, then WhatsApp / Browse as secondary,
   then the email capture. Markets-in-focus is demoted to a quiet navigator.
   Appended last so these win by source order over the base .cta-* rules.
   ============================================================================ */
.cta-block--concierge {
  gap: 10px;
}
.concierge-headline {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: clamp(26px, 3.4vw, 34px);
  line-height: 1.04;
  letter-spacing: var(--track-tight);
  color: var(--kamo-fg);
  margin: 2px 0 0;
  text-wrap: balance;
}
.cta-actions--concierge {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 12px 0 12px;
}
.cta-actions--concierge .cta-action {
  min-height: 46px;
}
/* Primary prompt — full width, reads like a concierge bar (label left, arrow right). */
.cta-action--prompt {
  grid-column: 1 / -1;
  justify-content: space-between;
  gap: 16px;
  padding: 13px 18px;
  font-size: 11px;
  letter-spacing: var(--track-wide);
  text-align: left;
}
.cta-action--prompt svg {
  transition: transform var(--dur-fast) var(--ease-standard);
}
.cta-action--prompt:hover svg {
  transform: translateX(3px);
}
/* Tertiary — quiet ghost link to /explore (inventory stays secondary). */
.cta-action--browse {
  background: transparent;
  border: 1px solid var(--kamo-panel-border-cta);
  color: var(--kamo-fg);
}
.cta-action--browse:hover {
  border-color: var(--kamo-gold-soft);
  color: var(--kamo-gold-text);
}

/* ============================================================================
   Closing enquiry band — three differentiated client paths + a set-apart
   WhatsApp channel. Scoped to .kamo-home__closing so the concierge band and the
   global ghost/prompt buttons elsewhere are untouched.
   ============================================================================ */
/* Buy / Invest = the primary buyer path: a quiet soft-gold lead (resets the
   concierge band's grid-column / space-between / max-width artifacts). */
.kamo-home__closing .cta-action--prompt {
  grid-column: auto;
  justify-content: center;
  text-align: center;
  gap: 8px;
  max-width: none;
  padding: 12px 22px;
  font-size: 10px;
  letter-spacing: var(--track-wide);
  background: var(--kamo-gold-faint);
  border: 1px solid var(--kamo-gold-soft);
  color: var(--kamo-gold-text);
}
.kamo-home__closing .cta-action--prompt:hover {
  background: var(--kamo-gold);
  border-color: var(--kamo-gold);
  color: var(--kamo-bg-deep);
}
/* Sell / List + Developer / Partner = secondary paths: a half-step back from the
   gold lead, sharing a gold hover language so the three read as one set. */
.kamo-home__closing .cta-action--browse {
  color: var(--kamo-fg-dim);
  border-color: var(--kamo-rule);
}
.kamo-home__closing .cta-action--browse:hover {
  color: var(--kamo-gold-text);
  border-color: var(--kamo-gold-soft);
}
/* Hairline that sets WhatsApp (a contact channel) apart from the three paths. */
.kamo-home__closing-rule {
  align-self: stretch;
  width: 1px;
  min-height: 24px;
  background: var(--kamo-rule);
  margin: 0 2px;
}
@media (max-width: 720px) {
  .kamo-home__closing-actions {
    gap: 10px;
  }
  .kamo-home__closing-actions .cta-action {
    flex: 1 1 100%;
    min-height: 46px;
    padding: 13px 18px;
  }
  .kamo-home__closing-rule {
    display: none;
  }
}

/* Demote Markets-in-focus: it's a navigator now, not the headline. */
.manifest-name {
  font-size: 19px;
}

/* Mobile concierge-first: the richer prompt panel + the 4-row markets list can't
   both fit the band on a phone, and inventory is intentionally secondary here.
   So hide the verbose Markets-in-focus list and let the map (with its tappable
   city pins) be the quiet backdrop above the concierge panel; markets stay
   reachable via the pins and "Browse properties". Reset the top inset so the map
   fills from under the logo, and grow the bottom band to the real panel height. */
@media (max-width: 960px) {
  .kamo-root--network .manifest-slot {
    display: none;
  }
  .kamo-root--network {
    --network-cta-stack-h: 372px;
    --map-inset-top: var(--network-logo-clear);
  }
}
@media (max-height: 740px) and (min-width: 721px) {
  .kamo-root--network {
    --network-cta-stack-h: 236px;
  }
}

/* ===== Homepage mobile bottom reserve ===================================
   The single bottom chrome on phones is now the tab bar (the old sticky CTA
   bar was retired — the persistent tab bar carries Enquire + Properties, and
   the WhatsApp FAB floats above it). Reserve just the tab-bar height so the
   footer's legal row clears it. */
@media (max-width: 719px) {
  .kamo-home {
    padding-bottom: var(--mobile-nav-h);
  }
}

/* ===== Property detail — "More like this" (similar properties) =========== */
.property-detail__similar {
  max-width: 1100px;
  margin: 0 auto;
  padding: 0 clamp(24px, 5vw, 64px) clamp(40px, 6vw, 64px);
}

/* ============================================================================
   QUIET LUXURY DESIGN SYSTEM — v2
   Scroll reveal · cinematic hero · editorial sections
============================================================================ */

/* ── Scroll reveal ─────────────────────────────────────────────────────── */
[data-sr] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.9s var(--ease-emphasised), transform 0.9s var(--ease-emphasised);
}
[data-sr].sr-visible {
  opacity: 1;
  transform: translateY(0);
}
[data-sr="left"]            { transform: translateX(-28px); }
[data-sr="left"].sr-visible { transform: translateX(0); }
[data-sr="right"]            { transform: translateX(28px); }
[data-sr="right"].sr-visible { transform: translateX(0); }
[data-sr-delay="1"] { transition-delay: 0.08s; }
[data-sr-delay="2"] { transition-delay: 0.16s; }
[data-sr-delay="3"] { transition-delay: 0.24s; }
[data-sr-delay="4"] { transition-delay: 0.32s; }
[data-sr-delay="5"] { transition-delay: 0.40s; }

@media (prefers-reduced-motion: reduce) {
  [data-sr] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}

/* ── Nav scroll state ──────────────────────────────────────────────────── */
/* Over the cinematic hero the homepage toolbar is TRANSPARENT (both themes) —
   the dark photo carries it. Once scrolled, it gains a midnight glass bg. */
.kamo-app-shell__header.kamo-home-header-overlay {
  background: transparent;
  border-bottom-color: transparent;
  box-shadow: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  transition: background 320ms var(--ease-standard),
              border-color 320ms var(--ease-standard),
              -webkit-backdrop-filter 320ms var(--ease-standard),
              backdrop-filter 320ms var(--ease-standard);
}
/* Links read on the dark hero in BOTH themes */
.kamo-home-header-overlay .kamo-app-shell__nav a,
.kamo-home-header-overlay .kamo-app-shell__enquiry {
  color: rgba(243, 239, 232, 0.82);
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.35);
}
.kamo-home-header-overlay .kamo-app-shell__nav a:hover,
.kamo-home-header-overlay .kamo-app-shell__nav a.is-active {
  color: #d3b07f;
}
.kamo-home-header-overlay .kamo-app-shell__enquiry {
  color: #d3b07f;
  border-color: rgba(211, 176, 127, 0.55);
}
.kamo-home-header-overlay .kamo-app-shell__enquiry:hover {
  background: rgba(211, 176, 127, 0.14);
}
/* Bright-gold logo reads on the dark hero — undo the light-skin bronze filter */
[data-theme="light"] .kamo-home-header-overlay .kamo-app-shell__logo img {
  filter: none;
}
.kamo-app-shell__header.kamo-home-header-overlay.is-scrolled {
  background: rgba(7, 9, 13, 0.82);
  border-bottom-color: rgba(243, 239, 232, 0.08);
  -webkit-backdrop-filter: blur(18px);
  backdrop-filter: blur(18px);
}
@media (max-width: 720px) {
  /* Phones: OPAQUE, no glass. iOS Safari renders backdrop-filter unreliably on
     fixed bars — when the blur drops, the 0.82 wash reads as plain transparency
     and page text bleeds through the header and the status-bar band above it
     (owner's iPhone, 2026-07-12 — the dark-theme twin of the light-theme lesson
     documented below). The glass look stays desktop-only. */
  .kamo-app-shell__header.kamo-home-header-overlay.is-scrolled {
    background: #0a0c10;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}
/* Light skin: the fixed mobile chrome is SOLID and the EXACT page colour, not
   translucent glass. The old dark glass read as a muddy band over the linen
   content; a near-white linen panel (0.96) was worse — a whiter shade than the
   page (#faf7f1 vs #f1ede3) with a blur that smears content through it, so both
   bars looked like off-colour see-through strips. Fix: paint them in the page's
   own --kamo-bg (#f1ede3), fully opaque, no blur, and lift them off the content
   with a soft shadow instead of a colour difference. Over the dark hero the
   header stays transparent (unchanged); dark theme keeps its midnight glass. */
[data-theme="light"] .kamo-app-shell__header.kamo-home-header-overlay.is-scrolled {
  background: var(--kamo-bg);
  border-bottom-color: var(--kamo-panel-border);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  box-shadow: 0 8px 24px rgba(26, 22, 18, 0.07);
}
[data-theme="light"] .kamo-home-header-overlay.is-scrolled .kamo-app-shell__logo img {
  /* bronze the bright-gold hero logo back down for contrast on the linen bar */
  filter: brightness(0.78) saturate(1.15);
}
[data-theme="light"] .kamo-home-header-overlay.is-scrolled .lang-toggle.top-utility-panel,
[data-theme="light"] .kamo-home-header-overlay.is-scrolled .theme-toggle.top-utility-panel {
  background: rgba(26, 22, 18, 0.04);
  border-color: var(--kamo-panel-border);
  color: var(--kamo-fg-dim);
}
/* The nav links + Enquire pill carry the over-hero skin (near-white with a
   dark text-shadow — see "Links read on the dark hero in BOTH themes" above),
   which is invisible on the linen scrolled bar; drop them to the light skin's
   ink/bronze register alongside the logo + utility toggles restyled above. */
[data-theme="light"] .kamo-home-header-overlay.is-scrolled .kamo-app-shell__nav a,
[data-theme="light"] .kamo-home-header-overlay.is-scrolled .kamo-app-shell__enquiry {
  color: var(--kamo-fg-dim);
  text-shadow: none;
}
[data-theme="light"] .kamo-home-header-overlay.is-scrolled .kamo-app-shell__nav a:hover,
[data-theme="light"] .kamo-home-header-overlay.is-scrolled .kamo-app-shell__nav a.is-active {
  color: var(--kamo-gold-text);
}
[data-theme="light"] .kamo-home-header-overlay.is-scrolled .kamo-app-shell__enquiry {
  color: var(--kamo-gold-text);
  border-color: var(--kamo-gold-soft);
}
[data-theme="light"] .kamo-home-header-overlay.is-scrolled .kamo-app-shell__enquiry:hover {
  background: var(--kamo-gold-faint);
}
/* The underline-draw hardcodes hero gold (#d3b07f, below) — too faint on
   linen; use the light skin's deeper bronze token instead. */
[data-theme="light"] .kamo-home-header-overlay.is-scrolled .kamo-app-shell__nav a:not(.is-active)::after {
  background: var(--kamo-gold);
}
@media (max-width: 720px) {
  [data-theme="light"] .kamo-app-shell__mobile-nav {
    background: var(--kamo-bg);
    border-top-color: var(--kamo-panel-border);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    box-shadow: 0 -8px 24px rgba(26, 22, 18, 0.07);
  }
  [data-theme="light"] .kamo-app-shell__mobile-nav a,
  [data-theme="light"] .kamo-app-shell__mobile-nav button {
    color: var(--kamo-fg-dim);
  }
  [data-theme="light"] .kamo-app-shell__mobile-nav a.is-active {
    color: var(--kamo-gold-text);
  }
  /* iOS Safari draws its floating bottom address bar OVER page content that
     sits below the tab bar (bottom:0 = top of Safari's bar), and that bar is
     translucent — so a dark content section behind it bleeds through and looks
     muddy. We can't paint under Safari's chrome, but we can extend a solid
     page-colour fill downward past the tab bar so Safari's bar tints against
     the linen surface instead of whatever content is scrolled to the edge.
     Off-screen on browsers without a bottom bar; harmless there. */
  .kamo-app-shell__mobile-nav::after {
    content: '';
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    height: 140px;
    /* inherit, not var(--kamo-bg): follow the bar's CURRENT skin exactly
       (midnight over the hero / past-hero linen in light theme), so the fill
       can never mismatch the bar it extends. */
    background: inherit;
    pointer-events: none;
  }
  /* The header never got the matching UPWARD slab — during Safari's chrome
     collapse (and its fixed-element lag mid-scroll) iOS exposes a band ABOVE
     the fixed header in the status-bar zone, and page text rendered through it
     (owner's iPhone, 2026-07-12, homepage-only since only the homepage uses
     fixed overlay chrome). Extend the header's own skin past the top edge:
     transparent over the hero (video shows, as designed), opaque past it. */
  .kamo-app-shell__header.kamo-home-header-overlay::before {
    content: '';
    position: absolute;
    bottom: 100%;
    left: 0;
    right: 0;
    height: 140px;
    background: inherit;
    pointer-events: none;
  }
}
/* Ghost the language + theme utility pills over the hero (both themes) */
.kamo-home-header-overlay .lang-toggle.top-utility-panel,
.kamo-home-header-overlay .theme-toggle.top-utility-panel {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(243, 239, 232, 0.28);
  color: rgba(243, 239, 232, 0.85);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
.kamo-home-header-overlay .lang-toggle.top-utility-panel:hover,
.kamo-home-header-overlay .theme-toggle.top-utility-panel:hover {
  border-color: rgba(211, 176, 127, 0.6);
  color: #d3b07f;
}

/* ── Cinematic hero ────────────────────────────────────────────────────── */
.home-hero--cinematic {
  min-height: 100svh;
  padding: 0 !important;
  display: block;
}

/* Multi-layer scrim for depth over video */
.home-hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(175deg, rgba(7,9,13,0.72) 0%, rgba(7,9,13,0.12) 45%, rgba(7,9,13,0.62) 100%);
  pointer-events: none;
}

/* Suppress the default ::before scrim — we use .home-hero__scrim instead */
.home-hero--cinematic.home-hero--photo::before {
  display: none;
}

.home-hero__inner--cinematic {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  /* --consent-h: live height of the pending cookie banner (see consent.tsx) —
     keeps the CTA cluster above it on short viewports; 0 once answered. */
  padding: clamp(88px, 14vh, 144px) clamp(28px, 5.5vw, 92px)
    calc(clamp(44px, 7vh, 76px) + var(--consent-h, 0px));
  min-height: 100svh;
  max-width: none;
  margin: 0;
  width: 100%;
}

/* Eyebrow row */
.home-hero__eyebrow-row {
  display: flex;
  align-items: center;
  gap: 20px;
}

.home-hero__eyebrow-text {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: var(--track-widest);
  text-transform: uppercase;
  color: var(--kamo-gold);
  /* No nowrap: localized eyebrows run long (DE) and must wrap, not overflow */
  flex-shrink: 1;
  min-width: 0;
}

.home-hero__eyebrow-rule {
  flex: 1;
  height: 1px;
  background: linear-gradient(to right, rgba(201,165,116,0.5), transparent);
}

/* Headline block */
.home-hero__headline-block {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0;
}

.home-hero__headline--cinematic {
  font-family: var(--font-serif);
  font-weight: 300;
  /* Owner 2026-07-12: the 10vw/152px scale read billboard, not editorial —
     the 7-word headline wants ~2 lines at a calmer size. */
  font-size: clamp(44px, 6.8vw, 100px);
  /* Prata carries more contrast and taller extenders than the old face:
     0.94 leading collided descender-into-cap on multi-line headlines, and
     -0.015em tracking read cramped. Air, not drama. */
  line-height: 1.04;
  letter-spacing: -0.008em;
  color: #f3efe8;
  text-shadow: 0 4px 48px rgba(0,0,0,0.28);
  margin: 0 0 clamp(20px, 3vh, 36px);
  max-width: none;
  text-wrap: balance;
}

.home-hero__sub--cinematic {
  max-width: 44ch;
  font-family: var(--font-sans);
  font-weight: 300;
  font-size: clamp(15px, 1.4vw, 18px);
  line-height: 1.72;
  color: rgba(243,239,232,0.78);
  text-shadow: 0 1px 14px rgba(0,0,0,0.28);
  margin: 0;
}

/* Bottom bar */
.home-hero__bottom-bar {
  display: flex;
  /* row-reverse: CTAs sit bottom-LEFT under the left-aligned headline (action
     tied to the pitch), and the decorative scroll cue moves to the right — which
     also keeps the tertiary "Browse properties" link clear of the corner FAB.
     The ≤720px rule below switches this to a stacked column. */
  flex-direction: row-reverse;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  padding-top: 28px;
  border-top: 1px solid rgba(243,239,232,0.16);
}

/* Scroll cue */
.home-hero__scroll-cue {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
}

.home-hero__scroll-line {
  display: block;
  width: 1px;
  height: 52px;
  background: linear-gradient(to bottom, #c9a574, transparent);
  transform-origin: top;
  animation: heroPulse 2.6s ease-in-out infinite;
}

@keyframes heroPulse {
  0%   { opacity: 0; transform: scaleY(0); }
  25%  { opacity: 1; }
  75%  { opacity: 1; transform: scaleY(1); }
  100% { opacity: 0; transform: scaleY(1); }
}

@media (prefers-reduced-motion: reduce) {
  .home-hero__scroll-line { animation: none; opacity: 0.5; transform: none; }
}

.home-hero__scroll-word {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: rgba(243,239,232,0.45);
}

/* CTA row */
.home-hero__cta-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: flex-start;
}

/* Quiet reassurance line under the hero CTAs — risk reversal + effort reducer,
   stated plainly. Light on the always-dark hero scrim; no urgency, no colour. */
.home-hero__reassure {
  margin: 14px 0 0;
  font-family: var(--font-sans);
  font-size: 12px;
  letter-spacing: 0.01em;
  line-height: 1.5;
  color: rgba(240, 235, 225, 0.6);
  max-width: 46ch;
}

/* Hero buttons */
.khero-btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 13px 26px;
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: 0;
  cursor: pointer;
  transition: background 260ms var(--ease-emphasised),
              border-color 260ms var(--ease-emphasised),
              color 260ms var(--ease-emphasised),
              transform 260ms var(--ease-emphasised);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
.khero-btn--gold {
  background: #c9a574;
  border-color: #c9a574;
  color: #1a1005;
}
.khero-btn--gold:hover {
  background: #d8b888;
  border-color: #d8b888;
  transform: translateY(-2px);
}
.khero-btn--ghost {
  background: rgba(255,255,255,0.07);
  border-color: rgba(243,239,232,0.36);
  color: #f3efe8;
}
.khero-btn--ghost:hover {
  background: rgba(255,255,255,0.13);
  border-color: rgba(201,165,116,0.65);
  color: #c9a574;
  transform: translateY(-2px);
}
.khero-btn__arrow {
  display: inline-block;
  transition: transform 240ms var(--ease-emphasised);
}
.khero-btn--gold:hover .khero-btn__arrow {
  transform: translateX(4px);
}

/* Tertiary text-link in the CTA row — quiet, not a third ghost button. Sits
   inline with the two buttons: matches the row's gap via margin-left instead
   of fighting flex alignment with alignSelf, and shares the buttons' vertical
   rhythm via line-height rather than a stray center-alignment override. */
.home-hero__browse-link {
  display: inline-flex;
  align-items: center;
  margin-left: 4px;
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: #c9a574;
  text-decoration: none;
  line-height: 1;
  opacity: 0.85;
  transition: opacity 200ms;
}
.home-hero__browse-link:hover {
  opacity: 1;
}
@media (max-width: 720px) {
  .home-hero__browse-link {
    margin-left: 0;
    flex: 1 1 100%;
    justify-content: center;
    padding-top: 4px;
  }
}

@media (max-width: 720px) {
  /* Pan the hero still/video to its foot — on a tall phone the default centre
     crop shows mostly sky; anchoring the bottom keeps the pool/foreground in
     frame. (On phones this layer is the poster still; `shouldPlayHeroVideo`
     rides the poster, not the ~3MB loop.) */
  .home-hero--cinematic .home-hero__media { background-position: center bottom; }
  .home-hero--cinematic .home-hero__video { object-position: center bottom; }

  /* Stop the 100svh column from justifying content edge-to-edge: on a ~932px
     iPhone that flung the eyebrow to the very top and the CTAs/insights against
     the tab bar, with the headline marooned in the middle. Cluster the copy at
     the foot over the video (the cinematic intent) and clear both fixed bars. */
  .home-hero__inner--cinematic {
    justify-content: flex-end;
    gap: clamp(18px, 3vh, 30px);
    padding-top: calc(env(safe-area-inset-top, 0px) + clamp(72px, 11vh, 96px));
    /* + --consent-h: the banner floats above the tab bar; the CTAs clear both. */
    padding-bottom: calc(var(--mobile-nav-h) + var(--consent-h, 0px) + 16px);
  }
  /* Was flex:1 (centre-stretch) — that stretch is exactly what spread the hero. */
  .home-hero__headline-block {
    flex: 0 0 auto;
    /* Lift the message out of the lower third: the first glance on a phone
       carried no words at all (2026-07-24 audit). CTAs stay at the foot. */
    margin-bottom: clamp(20px, 7vh, 64px);
  }

  .home-hero__headline--cinematic {
    /* The 7-word headline needs a phone scale of its own: 13.5vw wrapped it
       into five cramped lines. ~9.5vw yields three to four balanced lines,
       and multi-line Prata wants positive leading and near-neutral tracking. */
    font-size: clamp(32px, 9.5vw, 52px);
    line-height: 1.1;
    letter-spacing: -0.004em;
    margin-bottom: clamp(14px, 2.2vh, 22px);
  }
  .home-hero__bottom-bar {
    flex-direction: column;
    align-items: flex-start;
    gap: 20px;
  }
  .home-hero__scroll-cue { display: none; }
  /* Stack the two co-primary CTAs full-width — clearer + larger tap targets on
     a phone than two cramped side-by-side buttons. WhatsApp (the quiet link)
     sits below them. */
  .home-hero__cta-row {
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    width: 100%;
    gap: 14px;
  }
  .khero-btn {
    width: 100%;
    justify-content: center;
    min-height: 48px;
    /* Keep the long primary label ("Start your property search today!") on
       ONE line at 375px: tighter tracking and padding, not a smaller button. */
    font-size: 10px;
    letter-spacing: 0.13em;
    padding-left: 14px;
    padding-right: 14px;
  }
}

/* ── Hero insights strip — quiet market-intelligence row at the fold ────── */

/* ── Section system ────────────────────────────────────────────────────── */
.ks-section--top-rule {
  border-top: 1px solid var(--kamo-rule);
}

.ks-section-head {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: clamp(22px, 3.5vw, 36px);
}

.ks-section-head--row {
  flex-direction: row;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
}

.ks-h2 {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: clamp(27px, 3vw, 42px);
  line-height: 1.08;
  color: var(--kamo-fg);
  margin: 0;
  text-wrap: balance;
}

.ks-lead {
  font-family: var(--font-sans);
  font-weight: 300;
  font-size: clamp(14px, 1.3vw, 16px);
  line-height: 1.7;
  color: var(--kamo-fg-dim);
  max-width: 52ch;
  margin: 0 0 22px;
}

.ks-disclaimer {
  margin: 16px 0 0;
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: var(--track-body);
  /* fg-dim (≈5:1), not fg-mute (≈2.8:1, fails AA) — this is small body text. */
  color: var(--kamo-fg-dim);
  line-height: 1.5;
}

.ks-guide-links {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.ks-text-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px; /* WCAG-safe tap target — these are sparse editorial links */
  /* Reset the UA button chrome so a <button class="ks-text-link"> (e.g. the
     saved-search / enquiry prompts) reads as a text link, not a beveled box. */
  border: 0;
  background: none;
  padding: 0;
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--kamo-gold-text);
  text-decoration: none;
  transition: opacity 200ms;
}
.ks-text-link:hover { opacity: 0.7; }

.ks-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

/* Section buttons */
.ks-btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 13px 26px;
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: 0;
  cursor: pointer;
  transition: background 240ms var(--ease-emphasised),
              border-color 240ms var(--ease-emphasised),
              color 240ms var(--ease-emphasised),
              transform 240ms var(--ease-emphasised);
}
.ks-btn--primary {
  background: var(--kamo-gold);
  border-color: var(--kamo-gold);
  color: #1a1005;
}
.ks-btn--primary:hover {
  background: #d8b888;
  border-color: #d8b888;
  transform: translateY(-2px);
}
.ks-btn--gold {
  background: var(--kamo-gold);
  border-color: var(--kamo-gold);
  color: #1a1005;
}
.ks-btn--gold:hover {
  background: #d8b888;
  border-color: #d8b888;
  transform: translateY(-2px);
}
/* Light theme's --kamo-gold (#8a6a3a, a deeper bronze for AA body-text
   elsewhere) is too dark to carry the near-black #1a1005 button label at
   AA — #1a1005 on #8a6a3a is ≈3.75:1, below the 4.5:1 the WCAG formula
   requires at 10.5px. Swap the resting-state label to the same warm cream
   used for text-on-dark elsewhere (#f3efe8) — #f3efe8 on #8a6a3a computes to
   ≈4.68:1 (AA pass) by the WCAG relative-luminance formula. The hover state
   already lightens the background to #d8b888 for #1a1005 (≈9.9:1), so hover
   keeps the dark ink instead of cream, which would fail against that lighter
   gold. Dark theme (--kamo-gold: #c9a574, a light gold) is untouched. */
[data-theme="light"] .ks-btn--primary,
[data-theme="light"] .ks-btn--gold {
  color: #f3efe8;
}
[data-theme="light"] .ks-btn--primary:hover,
[data-theme="light"] .ks-btn--gold:hover {
  color: #1a1005;
}
.ks-btn--ghost {
  background: transparent;
  border-color: var(--kamo-rule);
  color: var(--kamo-fg);
}
.ks-btn--ghost:hover {
  border-color: var(--kamo-gold-soft);
  color: var(--kamo-gold-text);
  transform: translateY(-2px);
}
.ks-btn--outline-light {
  background: rgba(243,239,232,0.06);
  border-color: rgba(243,239,232,0.25);
  color: rgba(243,239,232,0.85);
}
.ks-btn--outline-light:hover {
  background: rgba(243,239,232,0.12);
  border-color: rgba(201,165,116,0.6);
  color: #c9a574;
  transform: translateY(-2px);
}
.ks-btn__arrow {
  display: inline-block;
  transition: transform 220ms var(--ease-emphasised);
}
.ks-btn:hover .ks-btn__arrow,
.ks-btn:focus-visible .ks-btn__arrow { transform: translateX(4px); }
/* RTL: arrows point with the reading direction and the hover slide follows
   (2026-07-24 audit — every CTA arrow pointed backwards in Arabic).
   transform lists apply right-to-left: translate first, then the mirror. */
[dir='rtl'] .khero-btn__arrow,
[dir='rtl'] .ks-btn__arrow,
[dir='rtl'] .ks-text-cta__arrow { transform: scaleX(-1); }
[dir='rtl'] .khero-btn--gold:hover .khero-btn__arrow { transform: scaleX(-1) translateX(4px); }
[dir='rtl'] .ks-btn:hover .ks-btn__arrow,
[dir='rtl'] .ks-btn:focus-visible .ks-btn__arrow { transform: scaleX(-1) translateX(4px); }

/* ── Stat band ─────────────────────────────────────────────────────────── */
.ks-stat-band {
  border-top: 1px solid var(--kamo-rule);
  border-bottom: 1px solid var(--kamo-rule);
}

.ks-stat-band__inner {
  max-width: 1120px;
  margin: 0 auto;
  display: grid;
  /* 3 stats (owner cut the Reply chip 2026-07-24): 3-across until the 720px
     single-column stack — the wider cells keep every value on one line, so
     labels and subs sit level across the band. */
  grid-template-columns: repeat(3, 1fr);
}

.ks-stat-cell {
  padding: clamp(26px, 3.5vw, 44px) clamp(24px, 3.5vw, 48px);
  display: flex;
  flex-direction: column;
  gap: 8px;
  border-inline-end: 1px solid var(--kamo-rule);
}
.ks-stat-cell:last-child { border-inline-end: none; }

.ks-stat-cell__value {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: clamp(38px, 4.5vw, 64px);
  line-height: 1;
  color: var(--kamo-gold-text);
}

.ks-stat-cell__label {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-fg-dim);
}

.ks-stat-cell__sub {
  font-family: var(--font-sans);
  font-size: 12px;
  line-height: 1.5;
  color: var(--kamo-fg-dim);
}

@media (max-width: 720px) {
  .ks-stat-band__inner { grid-template-columns: 1fr; }
  .ks-stat-cell { border-inline-end: none; border-bottom: 1px solid var(--kamo-rule); }
  .ks-stat-cell:last-child { border-bottom: none; }
}

/* ── Process steps — numbered-card visual language shared with the buyer
       paths grid (small mono number over a serif title, not a giant display
       numeral); 4 steps: 4-across desktop / 2×2 tablet / 1-col mobile ──── */
.ks-process-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  border: 1px solid var(--kamo-rule);
}

.ks-process-step {
  padding: clamp(24px, 3vw, 38px) clamp(20px, 2.5vw, 32px);
  border-inline-end: 1px solid var(--kamo-rule);
  display: flex;
  flex-direction: column;
  gap: 12px;
  transition: background 240ms var(--ease-standard);
}
.ks-process-step:last-child { border-inline-end: none; }
.ks-process-step:hover { background: rgba(201,165,116,0.04); }

.ks-process-num {
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-gold-text);
  opacity: 0.8;
}

.ks-process-title {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: clamp(18px, 2vw, 24px);
  line-height: 1.2;
  color: var(--kamo-fg);
  margin: 0;
}

.ks-process-body {
  font-family: var(--font-sans);
  font-weight: 300;
  font-size: 13px;
  line-height: 1.72;
  color: var(--kamo-fg-dim);
  margin: 0;
}

@media (max-width: 960px) {
  .ks-process-grid { grid-template-columns: repeat(2, 1fr); }
  .ks-process-step { border-bottom: 1px solid var(--kamo-rule); }
  .ks-process-step:nth-child(2n) { border-inline-end: none; }
  .ks-process-step:nth-last-child(-n+2) { border-bottom: none; }
}
@media (max-width: 720px) {
  .ks-process-grid { grid-template-columns: 1fr; }
  .ks-process-step { border-inline-end: none; border-bottom: 1px solid var(--kamo-rule); }
  .ks-process-step:last-child { border-bottom: none; }
}

/* ── Market cards ──────────────────────────────────────────────────────── */
.ks-market-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  border: 1px solid var(--kamo-rule);
  overflow: hidden;
}

.ks-market-card {
  position: relative;
  height: clamp(320px, 34vw, 440px);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 24px 22px;
  border-inline-end: 1px solid var(--kamo-rule);
  border-radius: 0;
  background: var(--kamo-bg-deep);
  transition: none;
  text-decoration: none !important;
}
.ks-market-card:last-child { border-inline-end: none; }

.ks-market-card__photo {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  transition: transform 0.85s cubic-bezier(0.22,1,0.36,1);
  z-index: 0;
}
.ks-market-card:hover .ks-market-card__photo { transform: scale(1.07); }

.ks-market-card__overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(
    to top,
    rgba(7,9,13,0.92) 0%,
    rgba(7,9,13,0.45) 55%,
    rgba(7,9,13,0.18) 100%
  );
  transition: background 0.5s;
}
.ks-market-card:hover .ks-market-card__overlay {
  background: linear-gradient(
    to top,
    rgba(7,9,13,0.95) 0%,
    rgba(7,9,13,0.6) 55%,
    rgba(7,9,13,0.3) 100%
  );
}

.ks-market-card__content {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.ks-market-card__name {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: clamp(20px, 2.5vw, 32px);
  color: #f3efe8;
  line-height: 1.1;
  margin: 0;
}

.ks-market-card__region {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: rgba(243,239,232,0.5);
}

/* Hover-reveal block collapses to zero height (grid-rows trick) so the market
   names share one baseline across cards regardless of summary length. */
.ks-market-card__reveal {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.45s var(--ease-emphasised);
}
.ks-market-card:hover .ks-market-card__reveal,
.ks-market-card:focus-visible .ks-market-card__reveal {
  grid-template-rows: 1fr;
}
.ks-market-card__reveal-inner {
  overflow: hidden;
  min-height: 0;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.35s var(--ease-emphasised),
              transform 0.35s var(--ease-emphasised);
}
.ks-market-card:hover .ks-market-card__reveal-inner,
.ks-market-card:focus-visible .ks-market-card__reveal-inner {
  opacity: 1;
  transform: translateY(0);
}

.ks-market-card__summary {
  font-family: var(--font-sans);
  font-size: 12px;
  line-height: 1.6;
  color: rgba(243,239,232,0.7);
  margin: 6px 0 0;
}

.ks-market-card__stat {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid rgba(243,239,232,0.18);
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.ks-market-card__stat-val {
  font-family: var(--font-serif);
  font-size: 20px;
  color: #c9a574;
}

.ks-market-card__stat-lbl {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: rgba(243,239,232,0.45);
}

@media (max-width: 960px) {
  .ks-market-grid { grid-template-columns: repeat(2, 1fr); }
  .ks-market-card { height: 300px; border-bottom: 1px solid var(--kamo-rule); }
  .ks-market-card:nth-child(2n) { border-inline-end: none; }
  .ks-market-card:nth-last-child(-n+2) { border-bottom: none; }
  /* Touch: no hover — keep the reveal open */
  .ks-market-card__reveal { grid-template-rows: 1fr; }
  .ks-market-card__reveal-inner { opacity: 1; transform: none; }
}

@media (max-width: 720px) {
  /* Swipe rail (see .ks-paths-grid) — four stacked 240px market cards ran to
     1.4 screens for what is essentially a chooser. */
  .ks-market-grid {
    grid-auto-flow: column;
    grid-auto-columns: 72%;
    grid-template-columns: none;
    overflow-x: auto;
    /* Explicit: with only overflow-x set, overflow-y computes to auto too, so a
       sub-pixel vertical overflow made these rails grab vertical drags instead
       of letting them scroll the page (owner, 2026-07-25). */
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    gap: 12px;
    border: none;
    margin-inline: calc(-1 * var(--kamo-gutter, 20px));
    padding-inline: var(--kamo-gutter, 20px);
  }
  .ks-market-grid::-webkit-scrollbar { display: none; }
  /* min-height, not height: the reveal block stays open on touch, and Red Sea's
     summary + two-line stat overflowed a fixed 260px card — with overflow:hidden
     that clipped the market NAME off the top edge (owner, 2026-07-25). In a
     single-row rail every card stretches to the tallest one, so the shelf still
     lines up. */
  .ks-market-card {
    /* height:auto is required — the ≤960px block sets `height: 300px`, and a
       min-height can't override a different property. Without this the card
       stays fixed and long locales (DE) clip again. */
    height: auto;
    min-height: 260px;
    scroll-snap-align: start;
    border: 1px solid var(--kamo-rule);
    border-radius: var(--kamo-r-pad);
    overflow: hidden;
  }
  /* The desktop stat size wraps to two lines in a 72%-width card. */
  .ks-market-card__stat-val { font-size: 17px; }
  /* The desktop scrim is bottom-weighted because there the summary only appears
     on hover — at rest just the name sits at the foot of the card. On touch the
     reveal is always open, so text covers the full card and that gradient put a
     near-opaque band over the bottom half of the photo. Flatter and lighter:
     the photo reads across the whole card, the text still clears AA. */
  .ks-market-card__overlay {
    background: linear-gradient(
      to top,
      rgba(7,9,13,0.82) 0%,
      rgba(7,9,13,0.66) 55%,
      rgba(7,9,13,0.55) 100%
    );
  }
}

/* ── Featured grid ─────────────────────────────────────────────────────── */
.ks-featured-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: clamp(14px, 2vw, 22px);
}
@media (max-width: 720px) {
  /* Property shelves become a swipe carousel (see .ks-paths-grid). Four stacked
     cards ran to 1.6 screens each for the off-plan rail; swiping through homes
     is also simply the better phone gesture for browsing stock. */
  .ks-featured-grid {
    grid-auto-flow: column;
    grid-auto-columns: 74%;
    grid-template-columns: none;
    overflow-x: auto;
    /* Explicit: with only overflow-x set, overflow-y computes to auto too, so a
       sub-pixel vertical overflow made these rails grab vertical drags instead
       of letting them scroll the page (owner, 2026-07-25). */
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    margin-inline: calc(-1 * var(--kamo-gutter, 20px));
    padding-inline: var(--kamo-gutter, 20px);
  }
  .ks-featured-grid::-webkit-scrollbar { display: none; }
  .ks-featured-grid > * { scroll-snap-align: start; }
  .ks-featured-grid .listings-panel__card-media { height: 180px; }
}

/* ── Buyer paths ───────────────────────────────────────────────────────── */
.ks-paths-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  border: 1px solid var(--kamo-rule);
}

.ks-path-card {
  padding: clamp(24px, 3vw, 38px) clamp(20px, 2.5vw, 32px);
  border-inline-end: 1px solid var(--kamo-rule);
  border-bottom: 1px solid var(--kamo-rule);
  display: flex;
  flex-direction: column;
  gap: 12px;
  cursor: pointer;
  transition: background 240ms var(--ease-standard);
}
.ks-path-card:nth-child(2n) { border-inline-end: none; }
.ks-path-card:nth-last-child(-n+2) { border-bottom: none; }
.ks-path-card:hover { background: rgba(201,165,116,0.04); }

/* Full-bleed photo band on top of each router card (placeholder AI photography). */
.ks-path-media {
  margin: calc(-1 * clamp(24px, 3vw, 38px)) calc(-1 * clamp(20px, 2.5vw, 32px)) 8px;
  height: clamp(148px, 17vw, 188px);
  overflow: hidden;
}
.ks-path-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.ks-path-num {
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-gold-text);
  opacity: 0.8;
}

.ks-path-title {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: clamp(20px, 2.2vw, 28px);
  line-height: 1.15;
  color: var(--kamo-fg);
  margin: 0;
}

.ks-path-body {
  font-family: var(--font-sans);
  font-weight: 300;
  font-size: 13px;
  line-height: 1.72;
  color: var(--kamo-fg-dim);
  flex: 1;
}

.ks-path-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: auto;
  padding-top: 10px;
}

.ks-text-cta {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--kamo-gold-text);
  background: none;
  border: none;
  padding: 0;
  min-height: 44px; /* WCAG-safe tap target for the buyer-path / featured CTAs */
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  transition: gap 200ms var(--ease-emphasised);
  text-align: left;
}
.ks-text-cta:hover { gap: 14px; }

.ks-text-cta--dim {
  color: var(--kamo-fg-dim);
  letter-spacing: var(--track-body);
  text-transform: none;
}

.ks-text-cta__arrow {
  display: inline-block;
}

/* Desktop/tablet tightening (owner 2026-07-26: cards took too much vertical
   space above 720px). Scoped to a min-width query rather than edited in the
   base rule above so the mobile swipe rail (which inherits the base rule's
   padding/gap/title-size — it only overrides media height/margins itself)
   stays byte-for-byte unchanged.
   Stayed 2-across rather than going 4-up: .kamo-section caps at
   max-width:1120px regardless of viewport, so a wide breakpoint (1200px+)
   buys no extra room — a 4-up row always lands near ~250px per card. The
   German card 2 title ("Renditeorientiert investieren", 30 characters)
   would wrap to three cramped lines at that width, failing the "comfortably
   readable" bar. Tightening the existing 2-up grid gets the requested
   reduction without that risk. */
@media (min-width: 721px) {
  .ks-path-card {
    padding: clamp(18px, 2.2vw, 28px) clamp(16px, 2vw, 24px);
    gap: 10px;
  }
  .ks-path-media {
    margin: calc(-1 * clamp(18px, 2.2vw, 28px)) calc(-1 * clamp(16px, 2vw, 24px)) 8px;
    height: clamp(120px, 10vw, 150px);
  }
  .ks-path-title {
    font-size: clamp(18px, 1.8vw, 23px);
  }
}

@media (max-width: 720px) {
  /* Swipe rail, not a stack (2026-07-25). Stacked full-width cards made this
     one section 2.5 screens tall on a phone — the single largest block on the
     page, sitting between the visitor and the inventory. Side-by-side snapping
     cards keep all four paths (nothing removed) in roughly a third of the
     height, and the horizontal gesture reads as "there is more here". */
  .ks-paths-grid {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 78%;
    grid-template-columns: none;
    overflow-x: auto;
    /* Explicit: with only overflow-x set, overflow-y computes to auto too, so a
       sub-pixel vertical overflow made these rails grab vertical drags instead
       of letting them scroll the page (owner, 2026-07-25). */
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    border: none;
    gap: 12px;
    /* Bleed to the screen edges so the next card peeks past the margin. */
    margin-inline: calc(-1 * var(--kamo-gutter, 20px));
    padding-inline: var(--kamo-gutter, 20px);
  }
  .ks-paths-grid::-webkit-scrollbar { display: none; }
  .ks-path-card {
    scroll-snap-align: start;
    border: 1px solid var(--kamo-rule);
    border-radius: var(--kamo-r-pad);
    overflow: hidden;
  }
  /* nth-child border rules from the desktop grid don't apply to a rail. */
  .ks-path-card:nth-child(2n) { border-inline-end: 1px solid var(--kamo-rule); }
  .ks-path-card:nth-last-child(-n+2),
  .ks-path-card:last-child { border-bottom: 1px solid var(--kamo-rule); }
  .ks-path-media { height: 132px; margin-inline: 0; margin-top: 0; }
}

/* ── Team ──────────────────────────────────────────────────────────────── */
.ks-team-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border: 1px solid var(--kamo-rule);
}

.ks-team-card {
  padding: clamp(24px, 3vw, 38px) clamp(20px, 2.5vw, 32px);
  border-inline-end: 1px solid var(--kamo-rule);
  display: flex;
  flex-direction: column;
  gap: 0;
}
.ks-team-card:last-child { border-inline-end: none; }

.ks-team-initials {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: clamp(44px, 5.5vw, 68px);
  line-height: 1;
  color: var(--kamo-gold-text);
  opacity: 0.55;
  margin-bottom: 16px;
}

.ks-team-meta {
  margin-bottom: 20px;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.ks-team-name {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: clamp(19px, 2vw, 25px);
  color: var(--kamo-fg);
  line-height: 1.1;
  margin: 0;
}

.ks-team-title {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-fg-dim);
}

.ks-team-tagline {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-body);
  color: var(--kamo-gold-text);
  margin-top: 2px;
}

.ks-team-bio {
  font-family: var(--font-sans);
  font-weight: 300;
  font-size: 13px;
  line-height: 1.72;
  color: var(--kamo-fg-dim);
  margin: 0 0 16px;
  flex: 1;
}

.ks-team-lang {
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-fg-dim);
}

@media (max-width: 960px) {
  .ks-team-grid { grid-template-columns: 1fr; }
  .ks-team-card { border-inline-end: none; border-bottom: 1px solid var(--kamo-rule); }
  .ks-team-card:last-child { border-bottom: none; }
}

/* ── Client scenarios ──────────────────────────────────────────────────── */
.ks-scenarios-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border: 1px solid var(--kamo-rule);
}

.ks-scenario-card {
  padding: clamp(24px, 3vw, 38px) clamp(20px, 2.5vw, 32px);
  border-inline-end: 1px solid var(--kamo-rule);
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin: 0;
}
.ks-scenario-card:last-child { border-inline-end: none; }

.ks-scenario-quote {
  font-family: var(--font-serif);
  font-weight: 300;
  /* Upright, not italic — these are described client scenarios, not verbatim
     quotations, so they must not read as a real review. */
  font-size: clamp(15px, 1.4vw, 18px);
  line-height: 1.62;
  color: var(--kamo-fg);
  margin: 0;
  flex: 1;
}

.ks-scenario-attr {
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-fg-dim);
  padding-top: 16px;
  border-top: 1px solid var(--kamo-rule);
}

@media (max-width: 720px) {
  /* Swipe rail (see .ks-paths-grid). All three scenarios stay on the page. */
  .ks-scenarios-grid {
    grid-auto-flow: column;
    grid-auto-columns: 80%;
    grid-template-columns: none;
    overflow-x: auto;
    /* Explicit: with only overflow-x set, overflow-y computes to auto too, so a
       sub-pixel vertical overflow made these rails grab vertical drags instead
       of letting them scroll the page (owner, 2026-07-25). */
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    gap: 12px;
    border: none;
    margin-inline: calc(-1 * var(--kamo-gutter, 20px));
    padding-inline: var(--kamo-gutter, 20px);
  }
  .ks-scenarios-grid::-webkit-scrollbar { display: none; }
  .ks-scenario-card {
    scroll-snap-align: start;
    border: 1px solid var(--kamo-rule);
    border-radius: var(--kamo-r-pad);
  }
}

/* ── Closing CTA ───────────────────────────────────────────────────────── */
.ks-closing {
  background:
    linear-gradient(180deg, rgba(7,9,13,0.58), rgba(7,9,13,0.84)),
    url("/editorial/closing-cta.jpg") center 42% / cover no-repeat,
    #07090d !important;
  position: relative;
  overflow: hidden;
}

.ks-closing::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(80% 80% at 0% 100%, rgba(201,165,116,0.09), transparent 55%),
    radial-gradient(60% 60% at 100% 0%, rgba(201,165,116,0.05), transparent 50%);
  pointer-events: none;
}

.ks-closing__inner {
  position: relative;
  z-index: 1;
  max-width: 1120px;
  margin: 0 auto;
  padding: clamp(56px, 7.5vw, 96px) clamp(28px, 5.5vw, 92px);
}

.ks-closing__eyebrow {
  display: block;
  margin-bottom: 16px;
  color: var(--kamo-gold) !important;
}

.ks-closing__headline {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: clamp(36px, 5vw, 68px);
  line-height: 1.0;
  color: #f3efe8;
  margin: 0 0 clamp(16px, 2.5vw, 28px);
  text-wrap: balance;
}

.ks-closing__body {
  font-family: var(--font-serif);
  font-weight: 300;
  font-style: italic;
  font-size: clamp(15px, 1.4vw, 19px);
  line-height: 1.6;
  color: rgba(243,239,232,0.68);
  max-width: 52ch;
  margin: 0 0 clamp(28px, 4vw, 48px);
}

.ks-closing__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

@media (max-width: 640px) {
  .ks-closing__actions .ks-btn {
    flex: 1 1 auto;
    justify-content: center;
  }
}

/* ── Light mode overrides ──────────────────────────────────────────────── */
/* Market cards always render with dark overlay (photo-backed) */
[data-theme="light"] .ks-market-card__name,
[data-theme="light"] .ks-market-card__region { color: #f3efe8; }
/* Closing section always dark */
[data-theme="light"] .ks-closing {
  background:
    linear-gradient(180deg, rgba(7,9,13,0.58), rgba(7,9,13,0.84)),
    url("/editorial/closing-cta.jpg") center 42% / cover no-repeat,
    #07090d !important;
}

/* ── Hero entrance animations ──────────────────────────────────────────── */
@keyframes heroEyebrowIn {
  from { opacity: 0; transform: translateX(-16px); }
  to   { opacity: 1; transform: translateX(0); }
}
@keyframes heroHeadIn {
  from { opacity: 0; transform: translateY(32px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes heroSubIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes heroCtaIn {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes heroBarIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.home-hero__eyebrow-text {
  animation: heroEyebrowIn 0.8s var(--ease-emphasised) 0.2s both;
}
.home-hero__eyebrow-rule {
  animation: heroBarIn 1.2s ease 0.5s both;
}
.home-hero__headline--cinematic {
  animation: heroHeadIn 1.1s var(--ease-emphasised) 0.35s both;
}
.home-hero__sub--cinematic {
  animation: heroSubIn 0.9s ease 0.7s both;
}
.home-hero__bottom-bar {
  animation: heroCtaIn 0.8s var(--ease-emphasised) 0.85s both;
}

@media (prefers-reduced-motion: reduce) {
  .home-hero__eyebrow-text,
  .home-hero__eyebrow-rule,
  .home-hero__headline--cinematic,
  .home-hero__sub--cinematic,
  .home-hero__bottom-bar {
    animation: none;
  }
}

/* ── Featured grid — inherit the compact card styles from kamo-featured-grid ── */
.ks-featured-grid .listings-panel__card-wrap { height: 100%; }
.ks-featured-grid .listings-panel__card {
  height: 100%;
  border: 1px solid var(--kamo-panel-border);
  border-radius: var(--kamo-r-hair);
  background: var(--kamo-panel-bg);
}
.ks-featured-grid .listings-panel__card-media { height: 220px; }
.ks-featured-grid .listings-panel__card-media::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(7,9,13,0.65) 0%, transparent 55%);
}

/* ── Process step number — more dramatic display ───────────────────────── */
.ks-process-step:hover .ks-process-num {
  opacity: 1;
  color: var(--kamo-gold-text);
}

/* ── Subtle grain over sections for texture depth ─────────────────────── */
.kamo-home__sections::after {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  /* Below ALL fixed chrome (header 100 / FAB 102 / consent 130 / modal 1000):
     the film grain textures the page surface, never the controls on top of it. */
  z-index: 99;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1   0 0 0 0 1   0 0 0 0 1   0 0 0 0.032 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  opacity: 0.18;
}

/* ── Partner logos — spacing in editorial layout ───────────────────────── */
.kamo-partner-logos {
  margin-top: 8px;
}

/* ── Section rule line beneath the stat band ───────────────────────────── */
.ks-stat-band + .kamo-section {
  border-top: 1px solid var(--kamo-rule);
}

/* ── Closing section light-mode override for button colors ─────────────── */
[data-theme="light"] .ks-closing__headline { color: #f3efe8; }
[data-theme="light"] .ks-closing__body { color: rgba(243,239,232,0.68); }
[data-theme="light"] .ks-closing__eyebrow { color: #c9a574 !important; }

/* ============================================================================
   QUIET SIGNATURE LAYER — v3
   Word-mask headline · subtle parallax · clip reveals · wordmark moment.
   Restraint is the brief: nothing on the page performs for attention.
============================================================================ */

/* ── Gold selection — craft detail ─────────────────────────────────────── */
.kamo-home ::selection {
  background: rgba(201, 165, 116, 0.9);
  color: #0a0c10;
}

/* ── Word-mask headline reveal ─────────────────────────────────────────── */
/* The block-level fade is replaced by per-word rises out of overflow masks. */
.home-hero__headline--cinematic {
  animation: none;
}
.hh-w {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  /* The mask box follows the 0.94 line-height, which sits ABOVE glyph
     descenders — "gyp" in Egypt was clipped. Extend the mask floor and pull
     the layout back up so the type rhythm is unchanged. */
  padding-bottom: 0.16em;
  margin-bottom: -0.16em;
  /* Same problem at the ceiling: Prata's capital diacritics (the Â in KÂMO)
     rise above the 0.94 line box, so give the mask headroom too. */
  padding-top: 0.15em;
  margin-top: -0.15em;
}
@keyframes hhRise {
  from { transform: translateY(118%); }
  to   { transform: translateY(0); }
}
.hh-wi {
  display: inline-block;
  transform: translateY(118%);
  /* Minimal base delay — the headline is the LCP element, so every ms it
     stays masked is paid in core web vitals. */
  animation: hhRise 0.9s var(--ease-emphasised) calc(0.1s + var(--wi, 0) * 0.06s) forwards;
}
@media (prefers-reduced-motion: reduce) {
  .hh-wi { transform: none; animation: none; }
}

/* ── Hero parallax — transforms are driven from JS; promote the layers ──── */
.home-hero--cinematic .home-hero__media,
.home-hero__inner--cinematic {
  will-change: transform;
}

/* ── Market photo clip reveal ──────────────────────────────────────────── */
.ks-market-card[data-sr] .ks-market-card__photo {
  clip-path: inset(0 0 100% 0);
  transition: clip-path 1.05s var(--ease-emphasised),
              transform 0.85s cubic-bezier(0.22, 1, 0.36, 1);
}
.ks-market-card[data-sr].sr-visible .ks-market-card__photo {
  clip-path: inset(0 0 0 0);
}
@media (prefers-reduced-motion: reduce) {
  .ks-market-card[data-sr] .ks-market-card__photo {
    clip-path: none;
    transition: none;
  }
}

/* ── Nav underline draw ────────────────────────────────────────────────── */
.kamo-home-header-overlay .kamo-app-shell__nav a:not(.is-active)::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: -4px;
  height: 1px;
  background: #d3b07f;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.38s var(--ease-emphasised);
}
.kamo-home-header-overlay .kamo-app-shell__nav a:not(.is-active):hover::after {
  transform: scaleX(1);
  transform-origin: left;
}

/* ── Closing wordmark — architectural type moment ──────────────────────── */
.ks-closing__wordmark {
  position: absolute;
  inset-inline-end: -0.06em;
  bottom: -0.22em;
  z-index: 0;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: clamp(170px, 24vw, 400px);
  line-height: 1;
  color: transparent;
  -webkit-text-stroke: 1px rgba(201, 165, 116, 0.16);
  pointer-events: none;
  user-select: none;
}

/* Serif numerals stay tabular — steadier rhythm across the stat band */
.ks-stat-cell__value {
  font-variant-numeric: tabular-nums;
}

/* ── Slim section band (logo strips, quiet interstitials) ──────────────── */
.ks-section--slim {
  padding-top: clamp(28px, 3.5vw, 44px);
  padding-bottom: clamp(24px, 3vw, 40px);
}
.ks-slim-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 8px 24px;
  margin-bottom: 20px;
}
.ks-slim-line {
  font-family: var(--font-sans);
  font-weight: 300;
  font-size: 13px;
  line-height: 1.6;
  color: var(--kamo-fg-dim);
  margin: 0;
  max-width: 60ch;
}

/* ── Sub-block inside a section (e.g. scenarios under leadership) ──────── */
.ks-subblock {
  margin-top: clamp(28px, 4vw, 44px);
  padding-top: clamp(22px, 3vw, 32px);
  border-top: 1px solid var(--kamo-rule);
}

/* ============================================================================
   GUIDE PHOTO HERO — listing-backed pages (locations/developers/compounds)
   open on a full-bleed HEADLESS media band (title-below-photo model, Stage 3);
   the photograph (sourced from the page's own featured stock) fades in when
   ready. The text hero (breadcrumb/eyebrow/h1/…) sits immediately below, on
   page ground, using the standard .kamo-page-hero rules — no text renders
   inside this band, so it carries no type overrides of its own. Mounts (dark,
   min-height reserved below) as soon as the fetch is in flight OR resolved a
   cover, so the photo fading in never shifts the text hero (see
   ContentPageLayout.tsx); only when the fetch is CONFIRMED done with no cover
   does the band never mount — no empty dark placeholder forever.
============================================================================ */
.kamo-page-hero--photo {
  position: relative;
  max-width: none;
  margin: 0;
  background:
    radial-gradient(90% 80% at 8% 0%, rgba(201, 165, 116, 0.10), transparent 55%),
    #0a0c10;
  overflow: hidden;
}
.kamo-page-hero--photo.is-headless {
  min-height: clamp(280px, 36vh, 420px);
}
.kamo-page-hero__media {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  opacity: 0;
  transition: opacity 0.9s var(--ease-standard);
}
.kamo-page-hero__media.is-loaded {
  opacity: 1;
}
.kamo-page-hero__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(7, 9, 13, 0.88) 0%, rgba(7, 9, 13, 0.45) 55%, rgba(7, 9, 13, 0.3) 100%);
  pointer-events: none;
}

/* ============================================================================
   /EXPLORE — editorial portfolio treatment
   The map panel keeps its compact pills; the grid page gets the homepage's
   quiet language: hairline search, text filters with gold underlines,
   square photo-led cards.
============================================================================ */

/* Search — a hairline underline, not a grey box */
.explore-filters .explore-filters__search {
  max-width: 460px;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--kamo-rule);
  border-radius: 0;
  padding: 10px 2px;
  font-family: var(--font-sans);
  font-weight: 300;
  font-size: 15px;
  letter-spacing: var(--track-tight);
  color: var(--kamo-fg);
  transition: border-color var(--dur-base) var(--ease-standard);
}
.explore-filters .explore-filters__search:focus {
  outline: none;
  border-bottom-color: var(--kamo-gold);
}
.explore-filters .explore-filters__search::placeholder {
  color: var(--kamo-fg-mute);
}

/* Filters — quiet text buttons; the active state is a gold underline,
   not a filled pill. Scoped so the map panel's pills are untouched. */
.explore-filters .listings-panel__pill {
  padding: 5px 2px;
  margin-right: 14px;
  border: none;
  border-radius: 0;
  background: transparent;
  font-size: 10px;
  letter-spacing: var(--track-wide);
  color: var(--kamo-fg-dim);
  position: relative;
}
.explore-filters .listings-panel__pill::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: var(--kamo-gold);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.3s var(--ease-emphasised);
}
.explore-filters .listings-panel__pill:hover {
  color: var(--kamo-fg);
}
.explore-filters .listings-panel__pill.is-active {
  background: transparent;
  border: none;
  color: var(--kamo-gold-text);
}
.explore-filters .listings-panel__pill.is-active::after {
  transform: scaleX(1);
}

.explore-filters {
  gap: 14px;
  padding-bottom: 26px;
}
.explore-filters__label {
  width: 64px;
  color: var(--kamo-fg-mute);
}

/* Result count — quiet mono */
.explore-page__count {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--kamo-fg-dim);
}

/* Cards on the grid page + homepage featured: square corners, hairline border,
   flat ground — matching the ks-* editorial system. */
.kamo-featured-grid .listings-panel__card {
  border-radius: 0;
  border: 1px solid var(--kamo-rule);
  background: transparent;
  box-shadow: none;
}
.kamo-featured-grid .listings-panel__card-media {
  border-radius: 0;
}
/* Let titles breathe on the grid (was a tight single-line clamp) */
.kamo-featured-grid .listings-panel__card-title {
  white-space: normal;
}

/* ============================================================================
   ENQUIRY — the private-client moment. Hairline underline inputs, serif
   headline, gold focus. KamoInput renders .kamo-input (see KamoInput.tsx).
============================================================================ */

.kamo-input {
  appearance: none;
  width: 100%;
  box-sizing: border-box;
  outline: none;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--kamo-rule);
  border-radius: 0;
  padding: 10px 2px;
  font-family: var(--font-sans);
  font-weight: 300;
  font-size: 16px;
  letter-spacing: var(--track-tight);
  color: var(--kamo-fg);
  transition: border-color var(--dur-base) var(--ease-standard);
}
.kamo-input:focus {
  border-bottom-color: var(--kamo-gold);
}
.kamo-input::placeholder {
  color: var(--kamo-fg-mute);
}
.kamo-input--inline {
  padding: 12px 4px;
}

.enquiry-headline {
  margin: 2px 0 0;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: clamp(24px, 3vw, 32px);
  line-height: 1.1;
  color: var(--kamo-fg);
  text-wrap: balance;
}

.enquiry-reassurance {
  margin: 0 0 4px;
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 300;
  font-size: 14px;
  line-height: 1.5;
  color: var(--kamo-fg-dim);
}

/* Message textarea: hairline box (an underline reads wrong on multiline) */
.kamo-input--textarea {
  background: transparent;
  border: 1px solid var(--kamo-rule);
  border-radius: 0;
  padding: 10px 12px;
  resize: vertical;
  min-height: 72px;
  color: var(--kamo-fg);
  transition: border-color var(--dur-base) var(--ease-standard);
}
.kamo-input--textarea:focus {
  border-color: var(--kamo-gold-soft);
}

/* Selects share the underline language; small gold chevron replaces the UA arrow */
.kamo-input--select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 24px;
  cursor: pointer;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path d='M1 1l4 4 4-4' fill='none' stroke='%23c9a574' stroke-width='1.4'/></svg>");
  background-repeat: no-repeat;
  background-position: right 4px center;
}
/* RTL: the chevron is a background-image (no logical "background-position:
   inline-end" keyword exists), so it stays glued to the physical right while
   the text inside the <select> right-aligns under RTL too — same edge,
   overlapping. Move the reserved gutter + chevron to the physical left. */
[dir='rtl'] .kamo-input--select {
  padding-right: 8px;
  padding-left: 24px;
  background-position: left 4px center;
}
.kamo-input--select option {
  background: var(--kamo-bg);
  color: var(--kamo-fg);
}

/* Refined radio / checkbox — hairline ring, gold core when chosen */
.enquiry-radio input[type="radio"],
.enquiry-radio input[type="checkbox"],
.enquiry-consent input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 15px;
  height: 15px;
  margin: 2px 0 0;
  border: 1px solid var(--kamo-fg-mute);
  background: transparent;
  cursor: pointer;
  flex-shrink: 0;
  display: inline-grid;
  place-content: center;
  transition: border-color var(--dur-fast) var(--ease-standard);
}
.enquiry-radio input[type="radio"] {
  border-radius: 50%;
}
.enquiry-radio input[type="checkbox"],
.enquiry-consent input[type="checkbox"] {
  border-radius: 1px;
}
.enquiry-radio input:hover,
.enquiry-consent input:hover {
  border-color: var(--kamo-gold-soft);
}
.enquiry-radio input::before,
.enquiry-consent input::before {
  content: '';
  width: 7px;
  height: 7px;
  transform: scale(0);
  transition: transform var(--dur-fast) var(--ease-emphasised);
  background: var(--kamo-gold);
}
.enquiry-radio input[type="radio"]::before {
  border-radius: 50%;
}
.enquiry-radio input:checked,
.enquiry-consent input:checked {
  border-color: var(--kamo-gold);
}
.enquiry-radio input:checked::before,
.enquiry-consent input:checked::before {
  transform: scale(1);
}
.enquiry-radio input:focus-visible,
.enquiry-consent input:focus-visible {
  outline: 2px solid var(--kamo-gold);
  outline-offset: 2px;
}
/* Chosen option's label warms to full foreground */
.enquiry-radio:has(input:checked) span {
  color: var(--kamo-fg);
}



/* ── Homepage: the bottom nav is the single persistent bottom chrome —
      present from first paint (it used to slide in only past the hero). Over the
      dark hero it keeps the dark-glass skin even in the light theme; it turns
      linen via the site-wide [data-theme="light"] rule the moment the hero
      clears the bar (`kamo-nav-past-hero`, set ~one bar-height into the scroll —
      NOT `kamo-past-hero`, which waits a whole viewport and let light content
      bleed through the glass for the entire transition). ───────────────────── */
@media (max-width: 720px) {
  html.kamo-home-page[data-theme="light"]:not(.kamo-nav-past-hero) .kamo-app-shell__mobile-nav {
    /* OPAQUE (not glass): over the always-dark hero this reads the same, but it
       means that even if the linen flip is late/missed the bar can never let
       light page content bleed through it. */
    background: #0a0c10;
    border-top-color: rgba(243, 239, 232, 0.1);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    box-shadow: none;
  }
  html.kamo-home-page[data-theme="light"]:not(.kamo-nav-past-hero) .kamo-app-shell__mobile-nav a {
    color: rgba(243, 239, 232, 0.66);
  }
}

/* ── Listing price block: approximation note + inline currency selector ──── */
.price-display {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 6px 14px;
  margin-top: 8px;
}
.price-display .price-approx__note {
  margin: 0;
}
.kamo-input--select.currency-inline {
  width: auto;
  padding: 4px 22px 4px 2px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--kamo-fg-dim);
  border-bottom-color: var(--kamo-rule);
  flex-shrink: 0;
}
.kamo-input--select.currency-inline:hover {
  color: var(--kamo-gold-text);
}
/* RTL: mirror the chevron gutter (see the base .kamo-input--select override
   above) for this shorthand-padding variant too. */
[dir='rtl'] .kamo-input--select.currency-inline {
  padding: 4px 2px 4px 22px;
}

/* ── Payment-plan calculator ───────────────────────────────────────────── */
.pay-calc {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.pay-calc__unit {
  /* 16px so iOS Safari doesn't zoom the viewport on focus; padding keeps it
     visually compact. */
  font-size: 16px;
  width: 100%;
}
.pay-calc__row {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.pay-calc__row-label {
  font-family: var(--font-sans);
  font-weight: 300;
  font-size: 12px;
  letter-spacing: var(--track-body);
  color: var(--kamo-fg-dim);
}
.pay-calc__row-label strong {
  font-weight: 500;
  color: var(--kamo-fg);
}
.pay-calc__row input[type='range'] {
  width: 100%;
  accent-color: var(--kamo-gold);
  cursor: pointer;
  /* Comfortable vertical hit area for the thumb on touch (≥44px-friendly) without
     making the control visually bulky — the track stays slim, the row is tall. */
  -webkit-appearance: none;
  appearance: none;
  height: 44px;
  background: transparent;
}
/* WebKit/Blink: visible slim track + a 24px thumb that's easy to grab on mobile. */
.pay-calc__row input[type='range']::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 2px;
  background: var(--kamo-rule);
}
.pay-calc__row input[type='range']::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 24px;
  height: 24px;
  margin-top: -10px;
  border-radius: 50%;
  background: var(--kamo-gold);
  border: 2px solid var(--kamo-bg-deep);
  cursor: pointer;
}
/* Firefox: equivalent track + grab-friendly thumb. */
.pay-calc__row input[type='range']::-moz-range-track {
  height: 4px;
  border-radius: 2px;
  background: var(--kamo-rule);
}
.pay-calc__row input[type='range']::-moz-range-thumb {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--kamo-gold);
  border: 2px solid var(--kamo-bg-deep);
  cursor: pointer;
}
.pay-calc__out {
  border: 1px solid var(--kamo-rule);
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.pay-calc__out-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  font-family: var(--font-sans);
  font-weight: 300;
  font-size: 12px;
  color: var(--kamo-fg-dim);
}
.pay-calc__out-row strong {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: 17px;
  color: var(--kamo-gold-text);
  white-space: nowrap;
}
.pay-calc__wa {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--kamo-gold-text);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  /* ≥44px tap row for the WhatsApp action on mobile, kept visually compact. */
  min-height: 44px;
  /* The trailing arrow is plain text inside the link, so the whole label nudges
     right on hover — a restrained CSS-only affordance in lieu of a span to slide. */
  transition: opacity var(--dur-fast), transform 200ms var(--ease-emphasised);
}
.pay-calc__wa:hover {
  opacity: 0.75;
  transform: translateX(2px);
}
@media (prefers-reduced-motion: reduce) {
  .pay-calc__wa {
    transition: opacity var(--dur-fast);
  }
  .pay-calc__wa:hover {
    transform: none;
  }
}
.pay-calc__disclaimer {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: var(--track-body);
  line-height: 1.5;
  color: var(--kamo-fg-mute);
}

/* Sticky enquire bar fits the WhatsApp action beside the viewing CTA */
.ks-sticky-enquire__wa {
  flex: 0 0 auto;
}

/* ── Team: direct advisor line + reply promise ─────────────────────────── */
.ks-team-wa {
  margin-top: 12px;
}
/* .ks-reply-promise and .ks-story-pull below are unused as of the 2026-07-12
   homepage copy pass — the founder-story rewrite dropped the "even when it
   costs us the sale" honesty line and the "so they built the advisor..."
   pull-quote, and the story section now renders two stacked .ks-lead
   paragraphs instead. Left in place in case a future editorial pass wants
   the pull-quote treatment back. */
.ks-reply-promise {
  margin: 18px 0 0;
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 300;
  font-size: 14px;
  color: var(--kamo-fg-dim);
}

.ks-story-pull {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: clamp(23px, 2.8vw, 36px);
  line-height: 1.24;
  color: var(--kamo-fg);
  max-width: 24ch;
  margin: clamp(20px, 3vw, 32px) 0 0;
}

/* Wide editorial band under the founding story (placeholder AI photography). */
.ks-story-media {
  margin: clamp(28px, 4vw, 44px) 0 0;
  width: 100%;
  aspect-ratio: 24 / 9;
  overflow: hidden;
  border-radius: var(--kamo-r-hair);
}
.ks-story-media__caption {
  margin: 10px 0 0;
  font-family: var(--font-sans);
  font-size: 12px;
  color: var(--kamo-fg-dim);
}
.ks-story-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 45%;
  display: block;
}

/* ── Homepage founding-story team teaser (full bios on /about) ──────────── */
.ks-story-team {
  margin-top: clamp(30px, 4vw, 48px);
  display: flex;
  flex-direction: column;
  gap: 18px;
  align-items: flex-start;
}
.ks-story-team__label {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-fg-dim);
}
.ks-story-team__row {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(20px, 3vw, 40px);
}
.ks-story-partner {
  display: flex;
  align-items: center;
  gap: 12px;
}
/* Typographic name card linking to /about (2026-07-24: the avatar-fallback
   initials circle read as a missing photo, so it was retired). The name takes
   a step up in size and the hover borrows the text-link gold. */
.ks-story-partner--link {
  text-decoration: none;
  color: inherit;
}
.ks-story-partner--link .ks-story-partner__name {
  font-size: 19px;
}
.ks-story-partner--link:hover .ks-story-partner__name,
.ks-story-partner--link:focus-visible .ks-story-partner__name {
  color: var(--kamo-gold-text);
}
.ks-story-partner__meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.ks-story-partner__name {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: 16px;
  color: var(--kamo-fg);
}
.ks-story-partner__title {
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--kamo-fg-dim);
}

/* Founder credential signature under the name (mirrors the /about treatment) —
   proof with specificity: a named, verifiable career line, understated. */
.ks-story-partner__cred {
  margin-top: 3px;
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: var(--track-body);
  line-height: 1.45;
  color: var(--kamo-gold-text);
  max-width: 24ch;
}

/* ── Compare — side-by-side decision table ─────────────────────────────── */
.compare-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 4px;
}
.compare-grid {
  display: grid;
  border: 1px solid var(--kamo-rule);
  min-width: 560px;
}
.compare-corner {
  border-bottom: 1px solid var(--kamo-rule);
}
.compare-head {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px;
  border-inline-start: 1px solid var(--kamo-rule);
  border-bottom: 1px solid var(--kamo-rule);
  text-decoration: none;
}
.compare-head img,
.compare-head__ph {
  width: 100%;
  height: 110px;
  object-fit: cover;
  background: var(--kamo-gold-faint);
}
.compare-head__title {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: 15px;
  line-height: 1.3;
  color: var(--kamo-fg);
}
.compare-head:hover .compare-head__title {
  color: var(--kamo-gold-text);
}
.compare-label {
  padding: 12px 14px;
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
  color: var(--kamo-fg-mute);
  border-bottom: 1px solid var(--kamo-rule);
  display: flex;
  align-items: center;
}
.compare-cell {
  padding: 12px 14px;
  font-family: var(--font-sans);
  font-weight: 300;
  font-size: 13px;
  line-height: 1.55;
  color: var(--kamo-fg);
  border-inline-start: 1px solid var(--kamo-rule);
  border-bottom: 1px solid var(--kamo-rule);
}

/* ── Viewing scheduler row in the property enquiry form ────────────────── */
.enquiry-viewing {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 18px;
}
.enquiry-viewing__when {
  width: auto;
  font-size: 12px;
  padding-top: 6px;
  padding-bottom: 6px;
}

/* ── Launch alerts capture (guide pages) ───────────────────────────────── */
.launch-alerts {
  margin-top: 28px;
  padding-top: 20px;
  border-top: 1px solid var(--kamo-rule);
  max-width: 480px;
}
.launch-alerts__label {
  display: block;
  margin-bottom: 10px;
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 300;
  font-size: 15px;
  color: var(--kamo-fg-dim);
}
.launch-alerts__row {
  display: flex;
  gap: 10px;
  align-items: flex-end;
}
.launch-alerts__input {
  flex: 1;
}
.launch-alerts__error {
  margin: 8px 0 0;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--kamo-error);
}
.launch-alerts--done {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 300;
  font-size: 15px;
  color: var(--kamo-gold-text);
}

/* ── EGP/USD editorial chart ───────────────────────────────────────────── */
.egp-chart {
  margin: 28px 0 8px;
  max-width: 640px;
}
.egp-chart__caption { margin-bottom: 12px; }
.egp-chart svg { width: 100%; height: auto; display: block; }
.egp-chart__grid { stroke: var(--kamo-rule); stroke-width: 1; }
.egp-chart__line { fill: none; stroke: var(--kamo-gold); stroke-width: 1.6; }
.egp-chart__area { fill: var(--kamo-gold); opacity: 0.07; }
.egp-chart__dot { fill: var(--kamo-gold); }
/* Font sizes are in viewBox units (640 wide). At the mobile render width (~342px)
   the SVG scales ~0.53×, so 10px collapsed to ~5px (illegible). 17/19 units land
   ~9–10px effective on mobile and read fine on the ≤640px desktop chart. */
.egp-chart__tick { fill: var(--kamo-fg-mute); font-family: var(--font-mono); font-size: 17px; }
.egp-chart__mark { fill: var(--kamo-gold-text); font-family: var(--font-mono); font-size: 19px; }
.egp-chart__source {
  margin: 12px 0 0;
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: var(--track-body);
  line-height: 1.6;
  color: var(--kamo-fg-mute);
}

/* ============================================================================
   MOBILE AUDIT FIXES (iPhone 13 Pro pass)
============================================================================ */

/* M1 — Calculator footnotes are <p> inside .kamo-document-main, so the broad
   prose rules ([data-theme] .kamo-document-main p {16px}, mobile {15px}) inflate
   them into monospace "code blocks". Re-assert the quiet footnote size with
   3-class specificity so it wins in both themes and at every width. */
.property-detail .pay-calc .pay-calc__disclaimer {
  font-size: 9.5px;
  line-height: 1.5;
}
.property-detail__panel .property-detail__plan .property-detail__plan-notes {
  font-size: 11px;
  line-height: 1.55;
}

/* M5 — Inline currency <select> in the listing aside: 10px triggers iOS focus
   zoom and is a 22px tap target. Bump to 16px / >=44px on phones (desktop has
   no zoom issue, keep it compact there). */
@media (max-width: 720px) {
  .kamo-input--select.currency-inline {
    font-size: 16px;
    min-height: 44px;
    padding-top: 8px;
    padding-bottom: 8px;
  }
  /* Enquiry option rows: lift the custom radio/checkbox + row to a 44px target. */
  .enquiry-modal .enquiry-radio,
  .enquiry-block .enquiry-radio {
    min-height: 44px;
    align-items: center;
  }
  .enquiry-modal .enquiry-radio input[type="radio"],
  .enquiry-modal .enquiry-radio input[type="checkbox"],
  .enquiry-block .enquiry-radio input[type="radio"],
  .enquiry-block .enquiry-radio input[type="checkbox"] {
    width: 20px;
    height: 20px;
  }
  .enquiry-modal .enquiry-radio input::before,
  .enquiry-block .enquiry-radio input::before {
    width: 9px;
    height: 9px;
  }
  /* Language popover rows to a comfortable 44px tap target. */
  .lang-menu__item {
    min-height: 44px;
  }
}

/* M5 — Compare table: keep the row-label column in view while the value columns
   scroll horizontally, so you never lose which spec you're reading. Sticky
   uses a logical inset so the label column stays pinned to whichever edge the
   grid mirrors it to under RTL (the grid's own column order already mirrors
   for free — this only had to follow it). */
.compare-corner,
.compare-label {
  position: sticky;
  inset-inline-start: 0;
  z-index: 1;
  background: var(--kamo-bg);
}
.compare-label {
  box-shadow: 1px 0 0 var(--kamo-rule);
}
[dir='rtl'] .compare-label {
  box-shadow: -1px 0 0 var(--kamo-rule);
}

/* ── Mobile tab bar: primary CTA + press feedback ──────────────────────── */
@media (max-width: 720px) {
  /* "Enquire" is the conversion action, not a navigation tab — set it apart
     with a soft gold pill (quiet, matches the hero's gold CTA). */
  .kamo-app-shell__mobile-nav button {
    color: #d3b07f;
    background: rgba(201, 165, 116, 0.12);
    border: 1px solid rgba(201, 165, 116, 0.35);
    border-radius: 999px;
    padding-left: 14px;
    padding-right: 14px;
  }
  /* Light press feedback on every tab target. */
  .kamo-app-shell__mobile-nav a,
  .kamo-app-shell__mobile-nav button {
    transition: opacity 120ms ease, transform 120ms ease, color 160ms ease;
  }
  .kamo-app-shell__mobile-nav a:active,
  .kamo-app-shell__mobile-nav button:active {
    opacity: 0.55;
    transform: scale(0.96);
  }
  @media (prefers-reduced-motion: reduce) {
    .kamo-app-shell__mobile-nav a:active,
    .kamo-app-shell__mobile-nav button:active {
      transform: none;
    }
  }
}

/* ── Accessibility: skip link + editorial-button focus ring ──────────────────
   Added in the site-wide a11y pass. The skip link is the first focusable element
   in both shells; it stays off-screen until focused, then reveals as a quiet
   pill so keyboard/SR users can jump past the header straight to <main>. */
.kamo-skip-link {
  position: fixed;
  top: 8px;
  inset-inline-start: 8px;
  z-index: 1000;
  transform: translateY(-150%);
  padding: 10px 16px;
  border-radius: 999px;
  background: var(--kamo-bg);
  color: var(--kamo-gold-text);
  border: 1px solid var(--kamo-gold-soft);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: var(--track-wide, 0.08em);
  text-transform: uppercase;
  text-decoration: none;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.28);
  opacity: 0;
  transition: transform 0.18s ease, opacity 0.18s ease;
}
.kamo-skip-link:focus {
  transform: translateY(0);
  opacity: 1;
  outline: 2px solid var(--kamo-gold);
  outline-offset: 2px;
}
/* The skip target receives programmatic focus; it isn't an interactive control,
   so it should not paint a focus ring of its own. */
#main-content:focus {
  outline: none;
}
/* Editorial buttons had no keyboard focus indicator on the midnight sections. */
.ks-btn:focus-visible {
  outline: 2px solid var(--kamo-gold);
  outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
  .kamo-skip-link {
    transition: none;
  }
}

/* ── Watchlist compare-selection (per-card pick when >3 saved) ─────────────── */
.watchlist-card-wrap {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.watchlist-compare-hint {
  margin: 0 0 14px;
  font-size: 12px;
}
/* Inline pick control sits BELOW each card (not over the media) so it never
   covers the market label or the saved-heart. */
.watchlist-compare-pick {
  align-self: flex-start;
  appearance: none;
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: var(--track-wide, 0.08em);
  text-transform: uppercase;
  padding: 6px 12px;
  min-height: 30px;
  border-radius: 999px;
  border: 1px solid var(--kamo-gold-soft);
  background: transparent;
  color: var(--kamo-gold-text);
  transition: background var(--dur-fast, 0.2s) var(--ease-standard, ease),
    border-color var(--dur-fast, 0.2s) var(--ease-standard, ease);
}
.watchlist-compare-pick:hover {
  border-color: var(--kamo-gold);
}
.watchlist-compare-pick.is-on {
  background: rgba(201, 165, 116, 0.14);
  border-color: var(--kamo-gold);
}
.watchlist-compare-pick:focus-visible {
  outline: 2px solid var(--kamo-gold);
  outline-offset: 2px;
}

/* ── Property-detail buyer-side assurance (under the enquire CTA) ──────────── */
.property-detail__assurance {
  display: flex;
  flex-direction: column;
  gap: 5px;
  margin-top: 2px;
}
.property-detail__assurance p {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 10px;
  line-height: 1.5;
  letter-spacing: var(--track-body);
  color: var(--kamo-gold-text);
}
.property-detail__assurance .property-detail__assurance-advisor {
  margin-top: 2px;
  color: var(--kamo-fg-dim);
}

/* ── Off-plan price matrix (066 tables: payment_plans / unit_prices /
   project_fees) — ProjectPage's public plan menu + unit-type x plan grid +
   fees table, gated behind FEATURES.site_offplan_matrix AND data presence.
   Table shape mirrors .research-table: mono-uppercase heads, serif unit
   labels, horizontal scroll contained to the table wrap (never the page). */
.price-matrix-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--kamo-panel-border);
  border-radius: var(--kamo-r-hair);
  background: var(--kamo-panel-bg);
}

.price-matrix-table {
  width: 100%;
  min-width: 520px; /* narrow viewports scroll the wrap, never the page */
  border-collapse: collapse;
}

.price-matrix-table th {
  padding: 12px 16px;
  text-align: left;
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: 10px;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
  color: var(--kamo-fg-dim);
  border-bottom: 1px solid var(--kamo-rule);
  white-space: nowrap;
}

.price-matrix-table td {
  padding: 12px 16px;
  vertical-align: top;
  font-family: var(--font-sans);
  font-weight: 300;
  font-size: 13px;
  line-height: 1.5;
  color: var(--kamo-fg);
  border-bottom: 1px solid var(--kamo-panel-border);
  white-space: nowrap;
}

.price-matrix-table tbody tr:last-child td {
  border-bottom: none;
}

.price-matrix-table__unit {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: 14px;
  color: var(--kamo-fg);
}

.price-matrix-table__sub {
  margin-top: 2px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--track-body);
  color: var(--kamo-fg-mute);
  white-space: normal;
}

.price-matrix-table__cash {
  color: var(--kamo-gold-text);
}

/* Row-label column stays in view while price columns scroll — same sticky
   discipline as .compare-label (logical inset so it stays pinned to the
   correct edge under RTL, where the grid already mirrors column order). */
.price-matrix-table th:first-child,
.price-matrix-table td:first-child {
  position: sticky;
  inset-inline-start: 0;
  z-index: 1;
  background: var(--kamo-bg);
  box-shadow: 1px 0 0 var(--kamo-rule);
}
[dir='rtl'] .price-matrix-table th:first-child,
[dir='rtl'] .price-matrix-table td:first-child {
  box-shadow: -1px 0 0 var(--kamo-rule);
}

/* Payment-plan cards (PlanMenu) — a cash plan reads gold, matching the price
   matrix's Cash column treatment above. */
.price-plan-card--cash .price-plan-card__name {
  color: var(--kamo-gold-text);
}

/* Payment calculator (PaymentCalculator, ProjectPage.tsx) — the output
   panel's stated-figure rows (down payment / second payment / instalments).
   The headline price reuses .property-detail__price directly (same "From"
   price treatment as the rest of this page); this is the smaller sibling for
   the supporting figures, serif so they read as figures, not body copy. */
.payment-picker__value {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: 15px;
  line-height: 1.4;
  color: var(--kamo-fg);
}

/* ============================================================================
   Default property-page layouts (Stage / Dossier) — shared primitives
   ----------------------------------------------------------------------------
   The default layouts for /projects/:slug (Stage, src/pages/layouts/project/
   StageProject.tsx) and /properties/:slug (Dossier, src/pages/layouts/
   listing/DossierListing.tsx) — ported from the approved option-c-stage.html
   / option-d2-dossier-mesca.html prototypes. Shared building blocks first
   (rail, document panel, closing band), then the .ks-lay--stage /
   .ks-lay--dossier scopes below. Breakpoints: 720 (site mobile) / 960 (rail +
   two-column body collapse — 960 MUST stay numerically identical to
   useBothWaysSticky.ts's RAIL_STACK_QUERY, or the Dossier rail's JS and its
   own CSS `position: sticky`/`static` switch disagree on which band is
   "mobile").
   No cross-section adjacency selectors. All TOKENS (--kamo-bg-deep,
   --kamo-rule, --kamo-gold*, --kamo-panel-*, --header-h) — the prototypes'
   hard-coded hexes were stand-ins for exactly these, so both themes work
   without a single hard-coded colour below.
============================================================================ */
.ks-lay__breadcrumb {
  padding: 16px clamp(20px, 4vw, 56px);
  border-bottom: 1px solid var(--kamo-rule);
  color: var(--kamo-fg-dim);
}
.ks-lay__breadcrumb a {
  color: inherit;
  text-decoration: none;
}
.ks-lay__breadcrumb a:hover {
  color: var(--kamo-gold-text);
}

/* ----- Rail: Stage's quiet facts rail / Dossier's letterhead rail ----- */
.ks-lay__rail {
  position: sticky;
  top: calc(var(--header-h) + 24px);
  align-self: start;
  height: fit-content;
}
.ks-lay__rail-section {
  padding: 20px 0;
  border-top: 1px solid var(--kamo-rule);
}
.ks-lay__rail-section:first-child {
  border-top: none;
  padding-top: 0;
}
.ks-lay__rail-label {
  display: block;
  margin-bottom: 10px;
}
.ks-lay__rail-price {
  display: block;
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(26px, 2.4vw, 32px);
  color: var(--kamo-gold-text);
  line-height: 1.15;
}
.ks-lay__rail-facts {
  margin-top: 24px;
  border-top: 1px solid var(--kamo-line);
}
/* Base row: no border of its own — Stage nests rows inside
   `.ks-lay__rail-section` blocks, which already supply ONE hairline (their
   own border-top) between adjacent sections; a border on the row too used to
   double up with it (row's bottom hairline + the next block's top hairline,
   with padding on both sides) and read as an empty ruled band under a single
   short row like "Off-plan". The ruled-LIST look (a line between every row)
   is only correct for Dossier's flat `.ks-lay__rail-facts` stack below,
   where it's the sole source of internal dividers — scoped there instead of
   put back on the bare class. */
.ks-lay__rail-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  padding: 8px 0;
  font-size: 13.5px;
}
.ks-lay__rail-facts .ks-lay__rail-row {
  padding: 14px 0;
  border-bottom: 1px solid var(--kamo-rule);
}
.ks-lay__rail-row--price {
  display: block;
  padding-top: 0;
}
.ks-lay__rail-row-k {
  flex-shrink: 0;
}
.ks-lay__rail-row-v {
  color: var(--kamo-fg);
  text-align: end;
}
.ks-lay__rail-ctas {
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid var(--kamo-rule);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
}
.ks-lay__rail-ctas-eyebrow {
  display: block;
}
.ks-lay__pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 22px;
  border: 1px solid var(--kamo-gold-soft);
  border-radius: 999px;
  color: var(--kamo-gold-text);
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast);
}
.ks-lay__pill:hover {
  background: var(--kamo-gold);
  color: var(--kamo-bg-deep);
  border-color: var(--kamo-gold);
}
.ks-lay__whatsapp-link {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--kamo-fg-dim);
  text-decoration: none;
  border-bottom: 1px solid var(--kamo-rule);
  padding-bottom: 2px;
  transition: color var(--dur-fast), border-color var(--dur-fast);
}
.ks-lay__whatsapp-link:hover {
  color: var(--kamo-gold-text);
  border-color: var(--kamo-gold-soft);
}

/* ----- Document panel: Key facts / About / Yield / Downloads ----- */
.ks-lay__doc-page {
  background: var(--kamo-panel-bg);
  border: 1px solid var(--kamo-panel-border);
  padding: clamp(24px, 4vw, 44px);
  margin: 8px 0 48px;
  border-radius: var(--kamo-r-pad);
}
.ks-lay__doc-eyebrow {
  display: block;
  margin-bottom: 12px;
  color: var(--kamo-gold-text);
}
.ks-lay__doc-title {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(20px, 2.2vw, 26px);
  margin: 0 0 18px;
  color: var(--kamo-fg);
}
.ks-lay__doc-list {
  border-top: 1px solid var(--kamo-rule);
}
.ks-lay__doc-list-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  padding: 14px 0;
  border-bottom: 1px solid var(--kamo-rule);
}
.ks-lay__dl-label {
  flex-shrink: 0;
}
.ks-lay__dl-value {
  font-size: 14.5px;
  text-align: end;
  color: var(--kamo-fg);
}

/* ----- Closing band: the register-interest / enquiry section ----- */
.ks-lay__closing-band {
  border-top: 1px solid var(--kamo-rule);
  margin-top: 24px;
  padding: clamp(48px, 7vw, 80px) clamp(20px, 4vw, 56px);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.ks-lay__closing-band > .kamo-eyebrow {
  display: block;
  margin-bottom: 8px;
}
.ks-lay__closing-band form {
  text-align: start;
  width: 100%;
}

@media (max-width: 960px) {
  .ks-lay__rail {
    position: static;
    align-self: auto;
    height: auto;
  }
}

/* ----- .ks-sticky-enquire per-layout skin -----
   The bar itself is shell-owned (rendered once by PropertyDetail.tsx outside
   the layout switch — see that file's return); [data-layout] on the page
   root lets a layout tune it without ever risking a second copy. Only
   'dossier' exists this wave, so this IS effectively the bar's only skin —
   the selector stays scoped rather than bare so a later wave's other listing
   layouts can override without a specificity fight. */
[data-layout="dossier"] .ks-sticky-enquire__price {
  font-family: var(--font-serif);
  color: var(--kamo-gold-text);
}

/* ============================================================================
   Stage layout (.ks-lay--stage) — /projects/:slug default
============================================================================ */
/* Title strip — matches option-c-stage.html's compact scale (owner feedback,
   2026-08-05: the built strip had drifted to the site's full interior-page
   hero size — a ~44-64px h1 plus a "By <developer>" line — pushing the stage
   down to ~320-345px and leaving the first viewport mostly empty room. The
   mockup's own strip is breadcrumb + eyebrow + h1 (clamp(26px,3.4vw,38px)) +
   one-line region, ~135px tall, so the stage starts around ~230px at
   1440x900. `.kamo-h1`'s site-wide default (clamp(36px,4.5vw,60px) *
   --display-size-mult) is deliberately overridden here, scoped to this
   layout only — Dossier/Editorial/Lookbook keep the full-size interior h1.
   The developer credit itself no longer renders in this strip at all (see
   StageProject.tsx's rail "Developer" row + ProjectPage.tsx's hero-slot
   comment) — it moved out, it wasn't just shrunk. */
.ks-lay--stage .kamo-page-hero {
  padding-top: clamp(20px, 2vw, 28px);
  padding-bottom: 14px;
}
.ks-lay--stage .kamo-page-hero .seo-guide-breadcrumb {
  margin-bottom: 10px !important;
}
.ks-lay--stage .kamo-page-hero .kamo-eyebrow {
  margin-bottom: 8px;
}
.ks-lay--stage .kamo-page-hero .kamo-h1 {
  font-size: clamp(26px, 3.4vw, 38px);
  line-height: 1.15;
  margin: 0 0 8px;
}
.ks-lay--stage .kamo-page-hero .kamo-body--compact {
  margin-top: 6px !important;
}

.ks-stage-section {
  max-width: 1320px;
  margin: 0 auto;
  padding: 0 clamp(20px, 4vw, 32px);
}
.ks-stage {
  position: relative;
  height: 78vh;
  min-height: 420px;
  background: var(--kamo-bg-deep);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.ks-stage__img {
  /* HARD CONSTRAINT: no photo is ever cropped — contain, not cover.
     `width/height: 100%` (not `auto`) is load-bearing here, not
     interchangeable with the more common `max-width:100%; height:auto`
     pattern: that pattern only ever SHRINKS an oversized image down to fit —
     it never grows a small one up to fill the box, since `auto` just falls
     back to the image's own intrinsic pixel size whenever that's already
     under the max. Most of this stage's source photos/renders are well
     under the ~78vh room's pixel size at typical desktop widths, so with
     `auto` they rendered at their native (small) size, centered, with the
     room's own leftover space reading as a huge dark "border" on every side
     — even for a photo whose ASPECT RATIO matched the room closely (owner
     feedback, 2026-08-05: "photo border too big"). `width/height: 100%`
     makes the img element always fill the room's box; `object-fit: contain`
     then does the real letterboxing work — scaling (up OR down) to the
     largest size that fits without cropping, centering the remainder. A
     mismatched-aspect-ratio photo still legitimately letterboxes (that part
     is fine, deliberate) — but a well-matched one now runs edge-to-edge. */
  width: 100%;
  height: 100%;
  object-fit: contain;
  transition: opacity 150ms ease;
}
.ks-stage__arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  color: var(--kamo-fg-dim);
  font-size: 22px;
  font-family: var(--font-serif);
  cursor: pointer;
  transition: color var(--dur-fast);
}
.ks-stage__arrow:hover {
  color: var(--kamo-gold);
}
.ks-stage__arrow--prev {
  inset-inline-start: 8px;
}
.ks-stage__arrow--next {
  inset-inline-end: 8px;
}

.ks-stage__caption-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 4px;
  border-bottom: 1px solid var(--kamo-rule);
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
}
.ks-stage__caption {
  color: var(--kamo-fg-dim);
}
.ks-stage__counter {
  color: var(--kamo-fg);
}

.ks-stage__filmstrip {
  display: flex;
  gap: 10px;
  padding: 14px 4px 26px;
  overflow-x: auto;
  scrollbar-width: thin;
}
.ks-stage__film-btn {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  height: 72px;
  flex: 0 0 auto;
  display: block;
  opacity: 0.55;
  border-bottom: 2px solid transparent;
  transition: opacity var(--dur-fast), border-color var(--dur-fast);
}
.ks-stage__film-btn img {
  /* True aspect ratio filmstrip thumbs — never cropped. */
  display: block;
  height: 72px;
  width: auto;
}
.ks-stage__film-btn.is-active {
  opacity: 1;
  border-bottom-color: var(--kamo-gold);
}
.ks-stage__film-btn:hover {
  opacity: 0.85;
}

.ks-stage__mobile-gallery {
  display: none;
}

.ks-stage__body {
  max-width: 1320px;
  margin: 0 auto;
  padding: 8px clamp(20px, 4vw, 32px) 0;
  display: grid;
  grid-template-columns: 1.82fr 1fr;
  gap: 70px;
}
.ks-stage__main {
  padding: 44px 0 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
/* The reused priceSection/priceMatrix/fees/calculator/faq/compoundEditorial
   slots are each their own `.kamo-section` — a page-level primitive with its
   OWN generous max-width + horizontal padding, designed for a full-bleed
   page section, not a lane already narrowed to ~62% by the two-column grid
   above. Left stock, that padding stacked on top of the column's own width
   constraint and starved the unit-type card grid (repeat(auto-fill,
   minmax(240px,1fr))) down to a single narrow column with dead space before
   the rail. The reading column already gets its outside margin from
   `.ks-stage__body`'s own padding — content here should use the full column
   width, not re-inset a second time. */
.ks-stage__main .kamo-section {
  max-width: none;
  padding-left: 0;
  padding-right: 0;
  /* `.kamo-section`'s own `margin: 0 auto` is a page-level centering rule;
     `.ks-stage__main` is a column flexbox, where auto CROSS-axis margins on
     a flex item suppress the container's default `align-items: stretch` —
     the section was shrinking to its content's natural width and centering
     inside the column instead of filling it (this, not the padding alone,
     is what was starving the unit-type card grid down to one narrow,
     off-center column). */
  margin-left: 0;
  margin-right: 0;
}
.ks-stage__rail {
  padding: 44px 0 0;
}
.ks-stage__disclosure {
  font-family: var(--font-sans);
  font-size: 12px;
  font-style: italic;
  color: var(--kamo-fg-dim);
  margin: 8px 0 0;
}

.ks-lay--stage .ks-lay__closing-band {
  margin-top: 48px;
}

@media (max-width: 960px) {
  .ks-stage__body {
    grid-template-columns: 1fr;
    gap: 0;
  }
  .ks-stage__rail {
    order: 2;
    border-top: 1px solid var(--kamo-rule);
    margin-top: 24px;
    padding-top: 24px;
  }
  .ks-stage__main {
    order: 1;
  }
}

@media (max-width: 720px) {
  /* No horizontal scroll at 390px (hard constraint): the JS stage/filmstrip
     hides in favour of the native scroll-snap swipe gallery below — the ONE
     legitimate sideways-scroll exception. */
  .ks-stage-section {
    display: none;
  }
  .ks-stage__mobile-gallery {
    display: flex;
    gap: 10px;
    padding: 0 clamp(16px, 4vw, 24px);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: clamp(16px, 4vw, 24px);
    -webkit-overflow-scrolling: touch;
    /* Swipe affordance, part 1 of 3 (owner feedback, 2026-08-05: "scrolls
       vertically, and not obviously a slideshow"). `pan-x` tells the browser
       a horizontal gesture STARTED on this track is this track's own to
       handle — it stops being reinterpreted as page scroll partway through
       the gesture (the owner's actual complaint: a swipe meant to change
       photos was winning as a vertical page-scroll instead). It deliberately
       does NOT also list `pan-y`: a vertical swipe that starts ON the track
       still needs to fall through and scroll the PAGE (there is no vertical
       content inside this track to scroll instead), and `touch-action` only
       ever grants MORE native gestures, never blocks the ones you omit from
       working entirely — omitting `pan-y` here doesn't disable vertical
       scrolling, it just means a vertical gesture on the track is left for
       the page to interpret, same as it always was. Verified both ways
       (horizontal intent stays on the track; vertical intent starting ON the
       track still scrolls the page). `overscroll-behavior-x: contain` stops
       an edge swipe (first/last slide) from bleeding into the browser's own
       back/forward navigation gesture. */
    touch-action: pan-x;
    overscroll-behavior-x: contain;
    /* Each slide keeps its OWN photo's height (see .ks-stage__mobile-slide
       below). Without this, flex's default `stretch` gave every slide the
       height of the tallest one, and the shorter photos paid for it in dead
       black band — measured at 390: a 2.04-ratio photo letterboxed 61px
       inside a 229px box. */
    align-items: flex-start;
    /* Swipe affordance, part 2 of 3 — a thin native scrollbar, restyled as a
       quiet progress hairline rather than hidden outright: unlike a JS
       "active dot" tracker (main-thread work on every scroll frame), the
       browser already computes the thumb's position/width from real scroll
       progress for free, so this is a genuine progress indicator, not a
       simulated one, for zero added script. */
    scrollbar-width: thin;
    scrollbar-color: var(--kamo-gold-soft) transparent;
  }
  .ks-stage__mobile-gallery::-webkit-scrollbar {
    height: 2px;
  }
  .ks-stage__mobile-gallery::-webkit-scrollbar-track {
    background: var(--kamo-rule);
  }
  .ks-stage__mobile-gallery::-webkit-scrollbar-thumb {
    background: var(--kamo-gold-soft);
  }
  .ks-stage__mobile-slide {
    position: relative; /* anchors .ks-stage__mobile-counter */
    /* Swipe affordance, part 3 of 3 — ~12% of the next slide stays visible
       at the trailing edge (88vw, not 100vw) so the track reads as a
       horizontal filmstrip on sight, before any gesture, rather than a
       single static photo that merely happens to be swipeable. */
    flex: 0 0 88vw;
    scroll-snap-align: start;
    margin: 0;
    /* NO aspect-ratio on the figure. It used to carry `3 / 2`, which was
       wrong twice over (owner-reported, 2026-08-05 — "photos not formatted
       properly"): the box also contains the figcaption, so the figure was
       never actually the ratio it declared (measured 343×261 for a 343×229
       reservation), and every real photo — they run 1.78–2.04, not 1.5 —
       letterboxed 36–61px of dead black inside it. The reservation belongs
       on the img alone, below. */
  }
  .ks-stage__mobile-slide img {
    display: block;
    width: 100%;
    /* `auto 16 / 9` keeps the CLS reservation the old rule was there for,
       while the `auto` keyword hands the box back to the image's OWN natural
       ratio the moment it is known. Reserved before load, true proportion
       after: no band, no crop. The fallback is 16/9 rather than the old 3/2
       because per-photo pixel dimensions still aren't captured anywhere in
       the pipeline, so this stays a DOCUMENTED DEFAULT — but 3/2 was a bad
       one: the gallery's real photos measure 1.78–2.04 at 390, so 3/2
       reserved ~36px too much per slide and the track visibly shrank as the
       lazy slides loaded. `object-fit: contain` stays as the never-crop
       guarantee for the one case the ratio can still be overridden —
       max-height below. */
    height: auto;
    aspect-ratio: auto 16 / 9;
    /* A portrait photo at 88vw would otherwise run past the fold and turn the
       filmstrip into a vertical scroll; contain letterboxes it sideways
       instead, which is the honest read for a rare off-format shot. */
    max-height: 72vh;
    object-fit: contain;
    background: var(--kamo-bg-deep);
  }
  /* Counter overlay — see the JSX's own comment (StageProject.tsx /
     StageListing.tsx) for why this needs no scroll-position JS: every slide
     renders its OWN index, so whichever slide is in view already reads as
     "current". A soft top-down scrim keeps mono caps legible over a bright
     sky/wall without a hard chip breaking the quiet register. */
  .ks-stage__mobile-counter {
    position: absolute;
    inset-block-start: 0;
    inset-inline: 0;
    padding: 10px clamp(16px, 4vw, 24px) 28px;
    background: linear-gradient(180deg, rgba(7, 9, 13, 0.5), transparent);
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: var(--track-wide);
    text-transform: uppercase;
    color: var(--kamo-fg);
  }
  .ks-stage__mobile-slide figcaption {
    padding: 10px clamp(16px, 4vw, 24px);
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: var(--track-wide);
    text-transform: uppercase;
    color: var(--kamo-fg-dim);
  }
  .ks-stage__body {
    padding-top: 8px;
  }
  .ks-stage__main,
  .ks-stage__rail {
    padding-top: 28px;
  }

  /* Typography pass (owner feedback, 2026-08-05): the site-wide mono-label
     token (--track-label, 0.2em) reads as over-tracked at this width — the
     mobile-gallery figcaption above already uses the tighter --track-wide
     (0.12em) and reads fine, so bring the rest of the title strip's/rail's
     mono labels down to the same neighbourhood here rather than touching
     --track-label itself (a site-wide token used far outside this layout).
     The h1's own tracking (--track-display, 0.015em) is already close to
     flush; zero it out at this size instead of leaving a fractional-pixel
     gap between glyphs that does nothing but soften the serif's edges. */
  .ks-lay--stage .kamo-label,
  .ks-lay--stage .kamo-eyebrow {
    letter-spacing: var(--track-wide);
  }
  .ks-lay--stage .kamo-page-hero .kamo-h1 {
    letter-spacing: 0;
  }
}

/* ============================================================================
   Dossier layout (.ks-lay--dossier) — /properties/:slug default
============================================================================ */
.ks-dossier__main {
  display: grid;
  grid-template-columns: 38% 58%;
  column-gap: 4%;
  align-items: start;
  max-width: 1440px;
  margin: 0 auto;
  padding: 0 clamp(20px, 4vw, 56px);
}
.ks-dossier__rail {
  padding: 40px 0 48px;
  display: flex;
  flex-direction: column;
}
/* The rail's two pieces — `-lede` (title + price essentials) and `-body`
   (everything else: remaining facts, CTAs, badges, foot) — stack in this
   same order inside `.ks-dossier__rail` at desktop (no visual change from
   the single flat block this used to be); the mobile media query below is
   what actually separates them, reparenting both around the photo record. */
.ks-dossier__rail-body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
}
.ks-dossier__rail-top {
  margin-bottom: 4px;
}
.ks-dossier__eyebrow {
  display: block;
  margin-bottom: 16px;
}
.ks-dossier__title {
  margin: 0 0 10px;
}
.ks-dossier__region {
  color: var(--kamo-fg-dim);
  font-style: italic;
  font-size: 15px;
  margin: 8px 0 0;
}
.ks-dossier__rail-foot {
  margin-top: auto;
  padding-top: 32px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.ks-dossier__resale-tag {
  display: block;
  color: var(--kamo-gold-text);
}

/* No `object-fit: cover` anywhere in this section (hard constraint) — every
   plate is the image's own natural ratio, uncropped. */
.ks-record {
  padding: 40px 0 48px;
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.ks-record__plate {
  margin: 0 0 8px;
}
.ks-record__plate img {
  width: 100%;
  /* Same reservation-then-true-proportion rule as .ks-stage__mobile-slide img
     above, and moved off the figure for the same reason: a fixed 3/2 box
     letterboxed every real photo (they run 1.78–2.04) in dead black, which on
     an 8-photo record is most of a viewport of nothing. `auto` keeps the
     pre-load CLS reservation and yields to the photo's own ratio after; 16/9
     is the closer documented default for the same measured photography. */
  height: auto;
  aspect-ratio: auto 16 / 9;
  object-fit: contain;
  display: block;
  background: var(--kamo-bg-deep);
}
.ks-record__caption-row {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 10px 0;
  margin-bottom: 40px;
  color: var(--kamo-fg-dim);
}
.ks-record__cap-no {
  color: var(--kamo-gold-text);
  flex-shrink: 0;
}
.ks-record__cap-rule {
  flex: 1 1 auto;
  height: 1px;
  background: var(--kamo-gold-soft);
}

@media (max-width: 960px) {
  /* Mobile photo position (owner feedback, 2026-08-05): the rail used to be
     ONE flat block ahead of `.ks-record` in DOM order, so single-column
     mobile stacked the ENTIRE letterhead — title, price, facts, CTAs,
     badges, watchlist — before a single photo appeared, sometimes more than
     a full viewport down. `.ks-dossier__main` becomes a flex column here,
     and the rail (`display: contents` — its own box disappears, but the
     node stays mounted for useBothWaysSticky's ref, inert at this breakpoint
     anyway since the hook disables itself here too) lets its two pieces act
     as `.ks-dossier__main`'s own direct flex children, so `order` can slot
     the record between them: title + price essentials, then the photo
     record immediately (first photo within the first viewport), then the
     rest (key facts/CTAs/badges/watchlist/FAQ panels — the advisor CTA
     itself still renders here since it lives in `-body`, but the STICKY
     bottom bar already covers that need above the fold). CSS-only
     responsive repositioning (slots.ts rule ii) — the DOM nodes are
     identical at every breakpoint, only their visual order changes. */
  .ks-dossier__main {
    display: flex;
    flex-direction: column;
    /* The desktop grid rule sets `align-items: start` (keeps the rail from
       stretching to the record's full height). In THIS flex column that
       inherited `start` means "size each child to its own content width and
       left-align" — so the record sized to the price-matrix table's
       min-content (~620px on a 9-unit grid), overflowed to the right, and
       got clipped by the body's `overflow-x: clip` (owner: "photos and
       charts cut off on the right on mobile", 2026-08-06). `stretch` pins
       every child to the column's 390px; the wide matrix then scrolls inside
       its own `.price-matrix-wrap` (overflow-x: auto) instead of dragging the
       whole record — and every photo plate — off-screen with it. */
    align-items: stretch;
  }
  /* Flex items default to `min-width: auto`, which refuses to shrink below a
     child's min-content — without these, `align-items: stretch` alone still
     loses to the matrix table's intrinsic width and the record re-expands. */
  .ks-record,
  .ks-lay__doc-page {
    min-width: 0;
  }
  .ks-dossier__rail {
    display: contents;
  }
  .ks-dossier__rail-lede {
    order: 1;
    /* 24px, not the title-strip's 28px — matches the 8px-multiple rhythm
       the rest of this reordered stack already uses (record's 8/32,
       rail-body's 24) instead of introducing a one-off value. */
    padding: 24px 0 0;
  }
  .ks-record {
    order: 2;
    padding: 8px 0 32px;
  }
  .ks-dossier__rail-body {
    order: 3;
    padding: 0 0 24px;
  }
  .ks-record__caption-row {
    margin-bottom: 32px;
  }
}

@media (max-width: 720px) {
  /* Typography pass (owner feedback, 2026-08-05) — mirrors Stage's own
     mobile block above. */
  .ks-lay--dossier .kamo-label,
  .ks-lay--dossier .kamo-eyebrow {
    letter-spacing: var(--track-wide);
  }
  .ks-lay--dossier .ks-dossier__title {
    letter-spacing: 0;
    /* A slightly smaller floor than the site-wide .kamo-h1 clamp (36px),
       so a long compound title (e.g. a resale listing's
       "<unit> — <bedrooms>, <compound>" pattern) wraps to fewer lines at
       this width instead of running four-plus deep; line-height (1.08,
       inherited from .kamo-h1) already sits inside the owner's requested
       ~1.05-1.1 band. */
    font-size: calc(clamp(28px, 8.2vw, 33px) * var(--display-size-mult));
  }
}

/* ----- Stage / Dossier: sticky-bar skin now shared by every listing layout
   that resolves to 'stage' too (StageListing joined 'dossier' this wave) —
   see the [data-layout] comment above .ks-sticky-enquire__price. ----- */
[data-layout="stage"] .ks-sticky-enquire__price {
  font-family: var(--font-serif);
  color: var(--kamo-gold-text);
}

/* ============================================================================
   Lookbook layout (.ks-lay--lookbook) — /projects/:slug and /properties/:slug
   ----------------------------------------------------------------------------
   Full-viewport photo "plates" (option-a-lookbook.html), shared verbatim by
   LookbookProject.tsx and LookbookListing.tsx — nothing in this scope is
   family-specific, so there is no [data-layout] fork inside it (contrast the
   Stage/Dossier sticky-bar skin above, which genuinely is). Breakpoint: 760px
   (this layout's own — the prototype's plates need more headroom than the
   site's 720px mobile line before they degrade to natural-ratio stacking).
============================================================================ */
.ks-lay--lookbook {
  position: relative;
}

.ks-lookbook__title-spread {
  min-height: 86vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: clamp(48px, 8vw, 96px) clamp(20px, 4vw, 56px);
}
.ks-lookbook__title {
  text-align: center;
  max-width: 18ch;
}
.ks-lookbook__region {
  font-style: italic;
  color: var(--kamo-fg-dim);
  font-size: 15px;
  margin: 0 0 48px;
}
.ks-lookbook__fact-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  border-top: 1px solid var(--kamo-rule);
  border-bottom: 1px solid var(--kamo-rule);
  width: 100%;
  max-width: 760px;
}
.ks-lookbook__fact {
  flex: 1 1 160px;
  padding: 22px 18px;
  border-left: 1px solid var(--kamo-rule);
}
.ks-lookbook__fact:first-child {
  border-left: none;
}
.ks-lookbook__fact-label {
  display: block;
  margin-bottom: 10px;
}
.ks-lookbook__fact-value {
  display: block;
  font-family: var(--font-serif);
  font-size: clamp(17px, 2vw, 22px);
  color: var(--kamo-fg);
}

.ks-lookbook__plate {
  min-height: 88vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 64px 6vw;
  opacity: 0;
  transform: translateY(12px);
  transition: opacity var(--dur-slow) ease, transform var(--dur-slow) ease;
}
.ks-lookbook__plate.is-in-view {
  opacity: 1;
  transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  .ks-lookbook__plate,
  .ks-lookbook__interlude {
    transition: none;
    opacity: 1;
    transform: none;
  }
}
.ks-lookbook__plate-stage {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  margin-bottom: 30px;
}
.ks-lookbook__plate-img {
  /* HARD CONSTRAINT: no photo is ever cropped — contain, not cover. */
  max-height: 68vh;
  width: auto;
  max-width: 100%;
  height: auto;
  object-fit: contain;
}
.ks-lookbook__plate-caption {
  width: 100%;
  max-width: 900px;
  display: flex;
  align-items: baseline;
  gap: 18px;
}
.ks-lookbook__plate--right .ks-lookbook__plate-caption {
  flex-direction: row-reverse;
  text-align: right;
}
.ks-lookbook__plate-rule {
  flex: 1 1 auto;
  height: 1px;
  background: linear-gradient(to right, var(--kamo-gold-soft), transparent);
}
.ks-lookbook__plate--right .ks-lookbook__plate-rule {
  background: linear-gradient(to left, var(--kamo-gold-soft), transparent);
}
.ks-lookbook__plate-num {
  color: var(--kamo-gold-text);
  white-space: nowrap;
}
.ks-lookbook__plate-cap {
  white-space: nowrap;
}

.ks-lookbook__interlude {
  padding: clamp(56px, 9vw, 110px) clamp(20px, 4vw, 56px);
  display: flex;
  flex-direction: column;
  align-items: center;
  opacity: 0;
  transform: translateY(12px);
  transition: opacity var(--dur-slow) ease, transform var(--dur-slow) ease;
}
.ks-lookbook__interlude.is-in-view {
  opacity: 1;
  transform: translateY(0);
}
.ks-lookbook__interlude-inner {
  width: 100%;
  max-width: 900px;
}
.ks-lookbook__disclosure {
  text-align: center;
  max-width: 44ch;
  margin: 20px auto 0;
}
.ks-lookbook__ratecard,
.ks-lookbook__faq {
  width: 100%;
  max-width: 900px;
}
/* The reused priceSection/priceMatrix/fees/calculator/faq/editorialBody
   slots each carry `.kamo-section`'s own page-level max-width + centering —
   inside an already max-width-capped interlude that stacks a second
   constraint and re-centers, same fix as `.ks-stage__main .kamo-section`
   above. */
.ks-lookbook__ratecard .kamo-section,
.ks-lookbook__faq .kamo-section,
.ks-lookbook__interlude-inner .kamo-section {
  max-width: none;
  margin-left: 0;
  margin-right: 0;
  padding-left: 0;
  padding-right: 0;
}

.ks-lookbook__closing {
  border-top: 1px solid var(--kamo-rule);
}
.ks-lookbook__closing-ctas {
  display: flex;
  align-items: center;
  gap: 24px;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: 8px;
}
.ks-lookbook__closing-extra {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: 20px;
}
.ks-lookbook__wa-footer {
  text-align: center;
  padding: 0 20px 40px;
}

.ks-lookbook__progress {
  position: fixed;
  bottom: 22px;
  right: 28px;
  background: var(--kamo-panel-bg-strong);
  padding: 6px 10px;
  border: 1px solid var(--kamo-rule);
  border-radius: var(--kamo-r-hair);
  z-index: 40;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--dur-base) ease;
}
.ks-lookbook__progress.is-visible {
  opacity: 1;
}

@media (max-width: 760px) {
  .ks-lookbook__title-spread {
    min-height: auto;
    padding: 56px 20px;
  }
  .ks-lookbook__fact-row {
    flex-direction: column;
  }
  .ks-lookbook__fact {
    border-left: none;
    border-top: 1px solid var(--kamo-rule);
  }
  .ks-lookbook__fact:first-child {
    border-top: none;
  }
  .ks-lookbook__plate {
    min-height: auto;
    padding: 48px 20px;
  }
  .ks-lookbook__plate-img {
    max-height: none;
    width: 100%;
    height: auto;
  }
  .ks-lookbook__plate-caption,
  .ks-lookbook__plate--right .ks-lookbook__plate-caption {
    flex-direction: column;
    align-items: flex-start;
    text-align: left;
    gap: 8px;
  }
  .ks-lookbook__plate-rule {
    display: none;
  }
  /* The caption title is `white-space: nowrap` for the desktop one-line
     "title —————— Nº" rule composition. At this breakpoint the caption
     stacks (column) and the rule is hidden, so nowrap has no purpose and a
     long resale title ("<unit> — <bedrooms>, <compound>") ran ~419px wide in
     a 350px column and was clipped by the body's `overflow-x: clip` (part of
     the owner's "cut off on the right" report, 2026-08-06). Let it wrap. */
  .ks-lookbook__plate-cap {
    white-space: normal;
  }
  .ks-lookbook__interlude {
    padding: 56px 20px;
  }
  .ks-lookbook__progress {
    bottom: 12px;
    right: 12px;
    font-size: 9.5px;
  }
}

/* ============================================================================
   Editorial layout (.ks-lay--editorial) — /projects/:slug and
   /properties/:slug
   ----------------------------------------------------------------------------
   Magazine feature (option-b-editorial.html), shared verbatim by
   EditorialProject.tsx and EditorialListing.tsx — same no-[data-layout]-fork
   posture as Lookbook above. Breakpoints: 900 / 640 (this layout's own,
   matching the prototype's two-step image-grid collapse).
============================================================================ */
.ks-editorial__wrap {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 clamp(20px, 4vw, 56px);
}

.ks-editorial__masthead {
  padding: clamp(24px, 3.4vw, 40px) 0 0;
}
.ks-editorial__title {
  text-align: left;
  max-width: none;
}
.ks-editorial__rule {
  border: none;
  border-top: 1px solid var(--kamo-rule);
  margin: 0 0 40px;
}
.ks-editorial__intro-row {
  padding-bottom: 40px;
}
.ks-editorial__fact-table {
  border-top: 1px solid var(--kamo-rule);
  max-width: 620px;
}
.ks-editorial__fact-row {
  display: flex;
  justify-content: space-between;
  gap: 20px;
  padding: 14px 0;
  border-bottom: 1px solid var(--kamo-rule);
}
.ks-editorial__fact-value {
  text-align: right;
  color: var(--kamo-fg);
}

.ks-editorial__lead {
  margin: 0 0 70px;
}
.ks-editorial__lead img {
  width: 100%;
  height: auto;
  /* Natural aspect ratio, never cropped — the Editorial's own "no fixed
     stage" posture (contrast Stage/Lookbook's object-fit: contain box). */
  display: block;
}
.ks-editorial__cap-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  padding-top: 12px;
  border-top: 1px solid var(--kamo-rule);
  margin-top: 14px;
}
.ks-editorial__cap-fig {
  color: var(--kamo-gold-text);
  flex-shrink: 0;
}
.ks-editorial__cap-text {
  text-align: right;
}

.ks-editorial__flow {
  padding-bottom: 16px;
}
.ks-editorial__twoup {
  display: flex;
  gap: 44px;
  align-items: flex-start;
  margin-bottom: 70px;
}
.ks-editorial__col-a {
  flex: 0 0 58%;
  max-width: 58%;
}
.ks-editorial__col-b {
  flex: 0 0 38%;
  max-width: 38%;
  margin-top: 56px;
}
.ks-editorial__twoup img,
.ks-editorial__full img {
  width: 100%;
  height: auto;
  display: block;
}
.ks-editorial__twoup figure,
.ks-editorial__full {
  margin: 0 0 70px;
}
.ks-editorial__twoup figure {
  margin: 0;
}

.ks-editorial__ratecard-band {
  background: var(--kamo-panel-bg);
  border-top: 1px solid var(--kamo-rule);
  border-bottom: 1px solid var(--kamo-rule);
  padding: clamp(48px, 6vw, 76px) 0;
  margin: 0 0 8px;
}
.ks-editorial__ratecard-band .kamo-section {
  max-width: none;
  margin-left: 0;
  margin-right: 0;
  padding-left: 0;
  padding-right: 0;
}
.ks-editorial__disclosure {
  margin-top: 24px;
  max-width: 640px;
}

.ks-editorial__faq {
  padding: clamp(48px, 6vw, 80px) 0;
}
.ks-editorial__faq .kamo-section {
  max-width: none;
  margin-left: 0;
  margin-right: 0;
  padding-left: 0;
  padding-right: 0;
}

.ks-editorial__closing-ctas {
  display: flex;
  align-items: center;
  gap: 24px;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: 8px;
}
.ks-editorial__closing-extra {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: 20px;
}

@media (max-width: 900px) {
  .ks-editorial__intro-row {
    padding-bottom: 30px;
  }
  .ks-editorial__twoup {
    flex-direction: column;
    gap: 28px;
  }
  .ks-editorial__col-a,
  .ks-editorial__col-b {
    flex: none;
    max-width: 100%;
    margin-top: 0;
  }
}

@media (max-width: 640px) {
  .ks-editorial__title {
    font-size: clamp(30px, 9vw, 44px);
  }
  .ks-editorial__rule {
    margin-bottom: 30px;
  }
  .ks-editorial__lead,
  .ks-editorial__twoup,
  .ks-editorial__full {
    margin-bottom: 48px;
  }
  .ks-editorial__cap-row {
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
  }
  .ks-editorial__cap-text {
    text-align: left;
  }
  .ks-editorial__fact-row {
    flex-wrap: wrap;
  }
}
