/* ============================================================
   Natya theme — component styles.
   (1) Per-page <helmet> <style> blocks from the .dc.html sources, preserved
       byte-for-byte. (2) style-hover / style-active attributes compiled into
       real CSS rules (mirroring what support.js generated), keyed by class.
   Enqueued AFTER natya_responsive.css so it overrides the design system, just
   as the inline helmets did in the reference.
   ============================================================ */

:root {
  --blue-natya: #1C5FA7;
}

/* ---------- site_header.dc.html helmet ---------- */
.nh-burger { display: none; color: var(--ink-900); }
@media (max-width: 1200px) and (min-width: 980px) {
  .nh-desktop-nav { gap: 20px !important; }
  .nh-desktop-nav a { font-size: 14px !important; }
}
@media (max-width: 979px) {
  .nh-topnav { display: none !important; }
  .nh-topbar-inner { justify-content: center !important; }
  .nh-desktop-nav { display: none !important; }
  .nh-book-desktop { display: none !important; }
  .nh-subnav { display: none !important; }
  .nh-burger { display: inline-flex !important; }
  .nh-main-inner { height: 64px !important; padding: 0 20px !important; }
  .nh-logo img { height: 42px !important; }
}
@media (max-width: 460px) {
  .nh-topbar-inner { padding-left: 16px !important; padding-right: 16px !important; }
  .nh-topinfo { gap: 14px !important; }
  .nh-email { display: none !important; }
}
@media (min-width: 980px) {
  .nh-drawer { display: none !important; }
}

/* ============================================================
 * Header skin + overlay-over-banner mode (site_header_v2.php)
 * Client direction: on any page that opens with a banner the navbar sits ON the
 * image instead of above it, then settles to an 80% frosted bar once scrolling
 * starts. The mode is read straight from the DOM — a header whose siblings
 * include a banner — so no template has to opt in; the templates with no banner
 * at all (room, activity, gallery, plain pages, 404) keep the solid header, as
 * do browsers without :has().
 *
 * --nh-head-h is how far the banner is pulled up, so it must track the row
 * count: two rows normally, three where the property subnav is rendered (which
 * is itself hidden below 980px, hence the flat mobile value).
 * ============================================================ */
:root { --nh-head-h: 94px; --nh-rule-inset: 32px; }
:root:has(.nh-subnav) { --nh-head-h: 140px; }
@media (max-width: 979px) {
  :root, :root:has(.nh-subnav) { --nh-head-h: 98px; --nh-rule-inset: 20px; }
}

.nh-header { box-shadow: 0 1px 0 rgba(29,32,38,0.06); transition: box-shadow 0.32s var(--ease-out); }
/* The scrolled row's backdrop-filter makes .nh-topbar a stacking context, which
   traps .nh-lang-menu inside it — so the row itself has to outrank .nh-drawer (70). */
.nh-topbar { background: var(--blue-natya); color: rgba(250,247,242,0.75); position: relative; z-index: 80; }
.nh-mainbar { background: var(--sand-50); border-bottom: 1px solid var(--sand-200); }
.nh-subnav { background: var(--sand-100); border-bottom: 1px solid var(--sand-200); }
/* Each frosted row keeps its own compositor layer. Without one, the row's
   backdrop-filter is rasterised tile by tile against a box whose height is
   animating (.is-nav-small), and a dropped frame paints half the bar tinted
   and half still see-through — the smear that reads as a glitch while the
   navbar shrinks or grows. translateZ(0) promotes the layer so the blur is
   sampled once per frame, whole; the drawer is a sibling of these rows, not a
   descendant, so the new containing block strands no position:fixed child.
   backface-visibility stops Safari re-sampling the layer mid-transition. */
.nh-topbar, .nh-mainbar, .nh-subnav {
  transform: translateZ(0);
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  will-change: backdrop-filter;
}
.nh-dest { color: var(--ink-900); }
.nh-dest.is-active { color: var(--blue-600); }
.nh-subnav-back, .nh-subnav-link { color: var(--stone-600); }
.nh-subnav-link.is-active { color: var(--orange-600); }
.nh-subnav-maps { color: var(--blue-600); }

/* A three-row header over a 300px section banner would leave the copy pinned to
   its underside, so those banners grow by the height they lost. */
.nh-header:has(~ .r-hero) ~ .r-hero { min-height: calc(300px + var(--nh-head-h)); }
/* Same for the 70vh property banner on a short (landscape) viewport, where the
   navbar would otherwise eat the room its copy stack needs. */
.nh-header:has(~ .ubud-hero) ~ .ubud-hero { min-height: calc(340px + var(--nh-head-h)); }

/* Reserve the navbar's height inside the banner so its copy can never ride up
   behind the nav on a short viewport. The media and scrim layers are inset:0
   absolutes, which resolve against the padding box — they still bleed full. */
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) ~ :is(.home-hero, .ubud-hero, .r-hero, .natya-hero) {
  box-sizing: border-box;
  padding-top: var(--nh-head-h);
}

/* --- at the top of the page: transparent over the banner --- */
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) {
  /* Pull the banner up under the header; sticky keeps it pinned as before. */
  margin-bottom: calc(var(--nh-head-h) * -1);
  box-shadow: none;
}
/* Scrim so the light nav text survives a bright banner. z-index:-1 keeps it
   behind the rows but inside the header's own stacking context. */
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero)::before {
  content: "";
  position: absolute;
  inset: 0 0 -48px 0;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(12,33,56,0.55) 0%, rgba(12,33,56,0.26) 58%, rgba(12,33,56,0) 100%);
  transition: opacity 0.32s var(--ease-out);
}
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-topbar,
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-mainbar,
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-subnav {
  background-color: transparent;
  border-bottom-color: transparent;
  transition: background-color 0.32s var(--ease-out), border-color 0.32s var(--ease-out);
}
/* Dividers between the rows, inset to the content gutter (not full bleed). */
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-topbar-inner,
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero):has(.nh-subnav) .nh-main-inner { position: relative; }
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-topbar-inner::after,
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero):has(.nh-subnav) .nh-main-inner::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: var(--nh-rule-inset);
  right: var(--nh-rule-inset);
  height: 1px;
  background: rgba(250,247,242,0.34);
  transition: opacity 0.32s var(--ease-out);
}
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-topinfo a,
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-topnav a,
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-lang > summary,
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-subnav a,
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-prop-nav a { text-shadow: 0 1px 6px rgba(12,33,56,0.5); }
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-dest,
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-burger,
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-subnav-maps { color: #fff; }
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-subnav-back,
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-subnav-link { color: rgba(255,255,255,0.88); }
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-dest.is-active,
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-subnav-link.is-active { color: var(--orange-300); }
/* Blue monogram would sink into the photo — paint it white while transparent. */
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-logo img {
  filter: brightness(0) invert(1);
  transition: filter 0.32s var(--ease-out);
}

/* --- once scrolled: frosted bar, normal colours back --- */
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero).is-scrolled { box-shadow: 0 1px 0 rgba(29,32,38,0.06); }
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero).is-scrolled::before { opacity: 0; }
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero).is-scrolled .nh-topbar-inner::after,
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero).is-scrolled .nh-main-inner::after { opacity: 0; }
/* The blur sits on the rows, never on <header>: backdrop-filter would make the
   header a containing block and strand the position:fixed mobile drawer. */
/* 50% tint (client direction, second pass — the 65% bar still read as a dark
   slab once scrolled), carried by a heavier blur: flattening the photo into a
   colour field is what keeps the nav text legible at this alpha. The brightness
   nudges push each row's backdrop AWAY from its own text colour — darker behind
   the topbar's light type, lighter behind the nav rows' ink type, and the ink
   rows are pushed harder now that less tint is doing the work. */
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero).is-scrolled .nh-topbar {
  background-color: rgba(28,95,167,0.5); /* fallback for no color-mix() */
  background-color: color-mix(in srgb, var(--blue-natya) 50%, transparent);
  -webkit-backdrop-filter: blur(24px) saturate(1.05) brightness(0.88);
  backdrop-filter: blur(24px) saturate(1.05) brightness(0.88);
}
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero).is-scrolled .nh-mainbar {
  background-color: rgba(250,247,242,0.5); /* fallback for no color-mix() */
  background-color: color-mix(in srgb, var(--sand-50) 50%, transparent);
  border-bottom-color: rgba(236,228,214,0.5);
  border-bottom-color: color-mix(in srgb, var(--sand-200) 50%, transparent);
  -webkit-backdrop-filter: blur(24px) saturate(1.05) brightness(1.14);
  backdrop-filter: blur(24px) saturate(1.05) brightness(1.14);
}
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero).is-scrolled .nh-subnav {
  background-color: rgba(244,239,230,0.5); /* fallback for no color-mix() */
  background-color: color-mix(in srgb, var(--sand-100) 50%, transparent);
  border-bottom-color: rgba(236,228,214,0.5);
  border-bottom-color: color-mix(in srgb, var(--sand-200) 50%, transparent);
  -webkit-backdrop-filter: blur(24px) saturate(1.05) brightness(1.14);
  backdrop-filter: blur(24px) saturate(1.05) brightness(1.14);
}
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero).is-scrolled .nh-topinfo a,
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero).is-scrolled .nh-topnav a,
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero).is-scrolled .nh-lang > summary,
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero).is-scrolled .nh-subnav a { text-shadow: none; }
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero).is-scrolled .nh-dest,
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero).is-scrolled .nh-burger { color: var(--ink-900); }
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero).is-scrolled .nh-subnav-back,
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero).is-scrolled .nh-subnav-link { color: var(--stone-600); }
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero).is-scrolled .nh-dest.is-active { color: var(--blue-600); }
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero).is-scrolled .nh-subnav-link.is-active { color: var(--orange-600); }
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero).is-scrolled .nh-subnav-maps { color: var(--blue-600); }
.nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero).is-scrolled .nh-logo img { filter: none; }

/* --- the nav row compacts once the page is moving (client feedback) ---
   Row heights and link sizes are inline on the template (transcribed DOM), so
   the shrunk state has to out-shout them with !important. The transitions live
   here because those wrappers carry no inline ones; the links already animate
   off their own inline `transition: all`. Both rows are covered: the main bar
   on every page, and the third bar on the pages that still render one. */
.nh-main-inner, .nh-subnav-inner { transition: height 0.28s var(--ease-out); will-change: height; }
.nh-logo img { transition: height 0.28s var(--ease-out); }
.nh-header.is-nav-small .nh-main-inner { height: 48px !important; }
.nh-header.is-nav-small .nh-logo img { height: 32px !important; }
.nh-header.is-nav-small .nh-dest { font-size: 13px !important; padding-block: 4px !important; }
.nh-header.is-nav-small .nh-subnav-inner { height: 34px !important; }
.nh-header.is-nav-small .nh-subnav-back,
.nh-header.is-nav-small .nh-subnav-link,
.nh-header.is-nav-small .nh-subnav-maps { font-size: 13.5px !important; }
.nh-header.is-nav-small .nh-subnav-maps svg,
.nh-header.is-nav-small .nh-subnav-maps i { width: 14px !important; height: 14px !important; }

/* "Leave this destination" and "move around inside it" are different jobs, so
   the back link keeps the far side of the row to itself — beside the logo,
   where it sat when it had a bar of its own — and the section links stay
   grouped on the other side. Logical property: it mirrors itself in RTL. */
.nh-prop-nav { flex: 1 1 auto; }
.nh-prop-nav .nh-subnav-back { margin-inline-end: auto; }

/* Inside a destination the main row carries the section links, so it holds far
   more than six destination names — the gap tightens before the row would wrap
   on the narrower desktops. Below 980px this nav is display:none and the drawer
   takes over, so nothing here needs a phone case. */
@media (max-width: 1240px) {
  .nh-prop-nav { gap: 16px !important; }
  .nh-prop-nav a { font-size: 14px !important; }
}
@media (max-width: 1080px) {
  .nh-prop-nav { gap: 12px !important; }
  .nh-prop-nav a { font-size: 13px !important; }
}

/* --- mobile drawer open: back to the plain solid header ---
   The drawer is an opaque white sheet starting under the navbar, so a
   see-through navbar above it reads as a glitch. Wins over .is-scrolled by
   the extra body class, hence it must stay below that block. */
body.natya-drawer-open .nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) { box-shadow: 0 1px 0 rgba(29,32,38,0.06); }
body.natya-drawer-open .nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero)::before { opacity: 0; }
body.natya-drawer-open .nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-topbar-inner::after,
body.natya-drawer-open .nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-main-inner::after { opacity: 0; }
body.natya-drawer-open .nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-topbar {
  background-color: var(--blue-natya);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
body.natya-drawer-open .nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-mainbar {
  background-color: var(--sand-50);
  border-bottom-color: var(--sand-200);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
body.natya-drawer-open .nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-subnav {
  background-color: var(--sand-100);
  border-bottom-color: var(--sand-200);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
body.natya-drawer-open .nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-topinfo a,
body.natya-drawer-open .nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-topnav a,
body.natya-drawer-open .nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-lang > summary,
body.natya-drawer-open .nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-subnav a { text-shadow: none; }
body.natya-drawer-open .nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-dest,
body.natya-drawer-open .nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-burger { color: var(--ink-900); }
body.natya-drawer-open .nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-subnav-back,
body.natya-drawer-open .nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-subnav-link { color: var(--stone-600); }
body.natya-drawer-open .nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-dest.is-active { color: var(--blue-600); }
body.natya-drawer-open .nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-subnav-link.is-active { color: var(--orange-600); }
body.natya-drawer-open .nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-subnav-maps { color: var(--blue-600); }
body.natya-drawer-open .nh-header:has(~ .home-hero, ~ .ubud-hero, ~ .r-hero, ~ .natya-hero) .nh-logo img { filter: none; }

.nh-drawer {
  position: fixed; top: 98px; left: 0; right: 0; bottom: 0; z-index: 70;
  background: #fff; overflow-y: auto; -webkit-overflow-scrolling: touch;
  opacity: 0; transform: translateY(-14px); pointer-events: none;
}
.nh-drawer[data-anim="in"] { opacity: 1; transform: translateY(0); pointer-events: auto; }
.nh-drawer-pattern {
  position: absolute; inset: 0; pointer-events: none; z-index: 0; overflow: hidden;
  -webkit-mask-image: radial-gradient(125% 90% at 100% 100%, #000 0%, transparent 65%);
  mask-image: radial-gradient(125% 90% at 100% 100%, #000 0%, transparent 65%);
}
.nh-drawer-pattern::before {
  content: ""; position: absolute; inset: 0; opacity: 0.14;
  background: var(--blue-700);
  -webkit-mask-image: url('patterns/natya-pattern.png');
  mask-image: url('patterns/natya-pattern.png');
  -webkit-mask-size: 340px; mask-size: 340px;
  -webkit-mask-repeat: repeat; mask-repeat: repeat;
}
.nh-drawer-inner {
  position: relative; z-index: 1;
  min-height: 100%; box-sizing: border-box; padding: 22px 20px 30px;
  display: flex; flex-direction: column;
  opacity: 0; transform: translateY(16px);
}
.nh-drawer[data-anim="in"] .nh-drawer-inner { opacity: 1; transform: translateY(0); }

/* ---------- site_footer.dc.html helmet ---------- */
.footer-bottom { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
/* V2 footer contact: the rows never run wider than the WhatsApp button under
   them. A property address is a full postal line and would otherwise stretch
   across the whole column while the button stayed short. One width drives both
   — the rows cap at it, the button takes it as a floor — so a longer
   translation widens the button instead of letting the text overhang it.
   224px is the button's own intrinsic width at 11px/0.18em plus its icon,
   gap, padding and border; box-sizing is border-box site-wide. */
.nf-contact { --nf-contact-w: 224px; }
.nf-contact .nf-contact-rows { max-width: var(--nf-contact-w); }
.nf-contact .nh-wa-btn { min-width: var(--nf-contact-w); justify-content: center; }
/* V2 footer on mobile: the desktop left-brand / right-contact split collapses
   into one centered stack (inline align/text-align on the columns needs !important). */
@media (max-width: 860px) {
  .nf-brand { align-items: center !important; text-align: center; }
  .nf-brand img { height: 96px !important; }
  .nf-contact { align-items: center !important; text-align: center !important; width: 100%; border-top: 1px solid var(--sand-200); padding-top: 28px; }
  .nf-contact .nh-wa-btn { align-self: center !important; }
}
@media (max-width: 700px) {
  .footer-bottom { flex-direction: column; align-items: center; text-align: center; gap: 14px; }
}

/* ---------- booking_dock.dc.html helmet ---------- */
.bk-mobile { display: none; }
@media (max-width: 760px) {
  .bk-bar { display: none !important; }
  .bk-mobile { display: block !important; }
  /* In flow, directly under the row that opened it (initOneDock moves it there),
     framed like the panel rows it sits between — the borderless full-bleed block
     read as a stray white rectangle once the card started overlaying the page.
     Spacing comes from the panel's own flex gap. */
  .bk-pop { position: static !important; transform: none !important; width: 100% !important; left: auto !important; right: auto !important; box-shadow: none !important; border: 1px solid var(--sand-200) !important; border-radius: 10px !important; margin-top: 0 !important; }
  /* A static dock (home hero) expanded on a phone becomes a bottom sheet — see
     the reasoning in initOneDock(). !important throughout beats the positioning
     the template renders inline for the static mode. */
  [data-natya-dock-wrap].is-sheet {
    position: fixed !important; inset-inline: 0 !important; bottom: 0 !important; top: auto !important;
    display: block !important; padding: 0 !important; z-index: 90;
    /* Parked off the bottom until .is-in; the same transition carries it back
       out on dismissal, which is what the one-shot keyframe could not do. */
    transform: translateY(100%);
    transition: transform 320ms cubic-bezier(0.22, 1, 0.36, 1);
    will-change: transform;
  }
  [data-natya-dock-wrap].is-sheet.is-in { transform: translateY(0); }
  /* Following eBay's bottom-sheet guidance: the sheet rests at about half the
     screen and slides to full height when an open field needs the room, its own
     content scrolling once there. Safe to animate now that fields are steps —
     no row moves under the finger either way.

     These two are the fallbacks. sizeSheet() replaces --nh-sheet-h with a
     measured pixel value on open, on every step and on resize, because a
     proportion of a small handset can come out shorter than the fields
     themselves — 55vh of a 568px screen is 312px, and the rows need more. */
  [data-natya-dock-wrap].is-sheet > div {
    --nh-sheet-h: 55vh;
    position: static !important; width: 100% !important; max-width: none !important;
    max-height: 92vh; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
  }
  [data-natya-dock-wrap].is-sheet.is-step > div { --nh-sheet-h: 80vh; }
  /* dvh where it exists: on iOS `vh` is the height with the browser chrome
     hidden, so 92vh reaches under the toolbar and the foot of the sheet — the
     Book button — is cut off. The vh lines above stay as the fallback. */
  @supports (height: 100dvh) {
    [data-natya-dock-wrap].is-sheet > div { --nh-sheet-h: 55dvh; max-height: 92dvh; }
    [data-natya-dock-wrap].is-sheet.is-step > div { --nh-sheet-h: 80dvh; }
  }
  /* The height is set on the white box, not the scroll wrapper: growing the
     wrapper alone would leave the extra space transparent and show the scrim
     through the bottom of the sheet. */
  [data-natya-dock-wrap].is-sheet .bk-mobile {
    border-radius: 20px 20px 0 0 !important; border-bottom: 0 !important;
    display: flex; flex-direction: column; height: var(--nh-sheet-h);
    transition: height 320ms cubic-bezier(0.22, 1, 0.36, 1);
  }
  [data-natya-dock-wrap].is-sheet [data-dock-mobile-panel] { flex: 1; min-height: 0; }
  /* Grab handle. Drawn as a pseudo-element, but sat in a strip tall enough to
     be the 48px drag target Material asks for — the swipe listener takes the
     whole top of the sheet, so the strip is the target. */
  [data-natya-dock-wrap].is-sheet .bk-mobile::before {
    content: ""; display: block; flex: none; width: 38px; height: 4px;
    margin: clamp(12px, 2.4vh, 22px) auto clamp(4px, 1vh, 8px);
    border-radius: 999px; background: var(--sand-300);
  }

  /* ---- Vertical rhythm, scaled to the screen rather than stepped at a
     breakpoint. The reference spacing is the upper bound and is what a normal
     phone gets; a 568px handset lands a hair under it, and only the calendar —
     six rows of day cells, the one thing that genuinely cannot fit — gives up
     real height. A hard compact breakpoint did fit, but it packed the fields
     against each other and lost the composure the design opens with.
     !important throughout: these override the inline styles transcribed 1:1
     from the reference DOM. ---- */
  [data-natya-dock-wrap].is-sheet .bk-mobile > div:first-child {
    padding-block: clamp(5px, 1.3vh, 9px) !important;
  }
  /* The header needs air beneath it before the fields start. The template gives
     the first row a 10px top margin for this, which the margin reset below
     removes — so the panel's own top padding carries it instead, and it scales
     like the rest of the rhythm. */
  [data-natya-dock-wrap].is-sheet [data-dock-mobile-panel] {
    padding-top: clamp(12px, 2.6vh, 18px) !important;
    padding-bottom: clamp(10px, 2.2vh, 14px) !important;
    gap: clamp(6px, 1.4vh, 8px) !important;
  }
  [data-natya-dock-wrap].is-sheet [data-dock-toggle] {
    padding-block: clamp(9px, 2vh, 13px) !important; margin-top: 0 !important;
  }
  [data-natya-dock-wrap].is-sheet [data-dock-pop="property"] button {
    padding-block: clamp(9px, 2vh, 13px) !important;
  }
  [data-natya-dock-wrap].is-sheet [data-dock-pop="dates"] {
    padding: clamp(10px, 2.2vh, 18px) 10px clamp(8px, 1.8vh, 16px) !important;
  }
  [data-natya-dock-wrap].is-sheet [data-dock-cal-grid] button {
    height: clamp(30px, 5.2vh, 38px) !important;
  }
  [data-natya-dock-wrap].is-sheet [data-dock-pop="guests"] > div {
    padding-block: clamp(11px, 2.4vh, 16px) !important;
  }
  /* Close control, in the header row beside the summary. */
  .bk-mobile .bk-sheet-close {
    flex: none; align-items: center; justify-content: center;
    width: 36px; height: 36px; padding: 0; cursor: pointer;
    background: transparent; border: 1px solid var(--sand-200); border-radius: 10px;
    color: var(--stone-500);
  }
  /* The Book CTA, moved to the foot of the sheet, spans it and stays there
     whichever step is showing. */
  .bk-mobile .bk-book-block {
    width: 100%; justify-content: center; margin-top: auto;
    padding: clamp(12px, 2.6vh, 16px) 20px !important;
  }
  /* An open field takes the sheet's whole middle, scrolling only if it must. */
  [data-natya-dock-wrap].is-sheet.is-step .bk-pop {
    flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    border: 0 !important; border-radius: 0 !important;
  }
  /* A field row stepped aside. A class, so the row keeps the inline
     `display: flex` the template gave it when it comes back. */
  .bk-mobile .bk-row-hidden { display: none !important; }
  [data-natya-dock-wrap].is-sheet .is-swap {
    animation: nh-step-in 220ms cubic-bezier(0.22, 1, 0.36, 1) both;
  }
  /* Back row: the way out of a step, and the name of the step you are in. */
  .bk-step-head { align-items: center; gap: 8px; padding: 4px 2px 2px; }
  .bk-step-back {
    flex: none; display: inline-flex; align-items: center; justify-content: center;
    width: 36px; height: 36px; padding: 0; cursor: pointer;
    background: transparent; border: 1px solid var(--sand-200); border-radius: 10px;
    color: var(--blue-600);
  }
  .bk-step-title {
    font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.12em;
    font-weight: var(--fw-semibold); color: var(--stone-500);
  }
}
.nh-dock-scrim {
  position: fixed; inset: 0; z-index: 89; background: rgba(12, 33, 56, 0.45);
  opacity: 0; transition: opacity 300ms ease;
}
.nh-dock-scrim.is-on { opacity: 1; }
/* Each step arrives on its own rather than appearing fully formed, so the eye
   is told which part of the sheet changed. initOneDock re-triggers it. */
@keyframes nh-step-in {
  from { opacity: 0; transform: translateY(7px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  [data-natya-dock-wrap].is-sheet,
  [data-natya-dock-wrap].is-sheet .bk-mobile { transition: none; }
  .nh-dock-scrim { transition: none; }
}

/* ---------- room_gallery.dc.html helmet ---------- */
.rg-collage { position: relative; display: grid; grid-template-columns: 2fr 1fr; gap: 18px; height: 520px; }
.rg-side { display: grid; grid-template-rows: 251px 251px; gap: 18px; height: 520px; }
.rg-tile { position: relative; border-radius: var(--radius-lg); overflow: hidden; cursor: pointer; box-shadow: var(--shadow-md); background: var(--sand-200); }
.rg-tile-main { height: 520px; }
.rg-side .rg-tile { height: 251px; }
.rg-tile img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 0.7s cubic-bezier(0.16,1,0.3,1); }
.rg-tile:hover img { transform: scale(1.05); }
.rg-tile::after { content: ""; position: absolute; inset: 0; background: rgba(12,33,56,0); transition: background 0.3s ease; }
.rg-tile:hover::after { background: rgba(12,33,56,0.12); }
@media (max-width: 860px) {
  .rg-collage { grid-template-columns: 1fr; height: auto; }
  .rg-side { grid-template-columns: 1fr 1fr; grid-template-rows: none; }
  .rg-tile-main { height: 300px; }
  .rg-side .rg-tile { height: 150px; }
}
@media (max-width: 520px) {
  .rg-side { display: none; }
  .rg-tile-main { height: 260px; }
}
/* Lightbox on narrow screens: the fixed 48px arrows + 84vw image row is wider
   than the viewport, so overlay the arrows on the image edges instead. */
@media (max-width: 560px) {
  [data-rg-modal] [data-rg-prev],
  [data-rg-modal] [data-rg-next] { position: absolute !important; z-index: 2; width: 42px !important; height: 42px !important; background: rgba(8,18,32,0.55) !important; }
  [data-rg-modal] [data-rg-prev] { left: 4px; }
  [data-rg-modal] [data-rg-next] { right: 4px; }
  [data-rg-modal] img[data-rg-active] { max-width: 100% !important; }
}
.rg-thumb { flex: 0 0 auto; width: 84px; height: 58px; border-radius: 8px; overflow: hidden; cursor: pointer; border: 2px solid transparent; opacity: 0.55; transition: opacity 0.2s ease, border-color 0.2s ease; padding: 0; background: none; }
.rg-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.rg-thumb[data-active="1"] { opacity: 1; border-color: var(--orange-500); }
.rg-thumb:hover { opacity: 1; }
.rg-strip::-webkit-scrollbar { height: 0; }
.natya-rail::-webkit-scrollbar { display: none; }

/* ============================================================
   Compiled style-hover / style-active rules (→ generated classes)
   ============================================================ */

/* link hovers */
.nh-h-orange300:hover { color: var(--orange-300) !important; }
.nh-h-orange500:hover { color: var(--orange-500) !important; }
.nh-h-orange600:hover { color: var(--orange-600) !important; }

/* destinations row */
.nh-dest:hover { color: var(--orange-600) !important; border-bottom-color: var(--orange-500) !important; }

/* orange CTA buttons (Book Now + page CTAs share the same hover/active) */
.nh-book:hover,
.nh-cta-orange:hover { background: var(--orange-600) !important; transform: translateY(-1px) !important; box-shadow: 0 14px 34px rgba(238,127,49,0.34) !important; }
.nh-book:active,
.nh-cta-orange:active { transform: translateY(0) !important; background: var(--orange-700) !important; box-shadow: none !important; }

/* outline View on Maps button (property header + drawer) */
.nh-maps:hover { background: var(--blue-600) !important; color: #fff !important; transform: translateY(-1px) !important; }
.nh-maps:active { transform: translateY(0) !important; background: var(--blue-natya) !important; border-color: var(--blue-natya) !important; }

/* burger */
.nh-burger:hover { background: var(--sand-100) !important; color: var(--orange-600) !important; }
.nh-burger:active { background: var(--sand-200) !important; }

/* footer WhatsApp button */
.nh-wa-btn:hover { background: var(--orange-500) !important; color: #fff !important; }

/* footer round social buttons: fill orange, icon goes white */
.nh-social-btn { transition: background var(--dur-base) var(--ease-in-out), border-color var(--dur-base) var(--ease-in-out), color var(--dur-base) var(--ease-in-out) !important; }
.nh-social-btn:hover { background: var(--orange-500) !important; border-color: var(--orange-500) !important; color: #fff !important; }

/* carousel arrows */
.nh-carousel-arrow:hover { background: rgba(12,33,56,0.74) !important; }

/* room gallery controls */
.rg-viewall:hover { transform: translateY(-2px) !important; box-shadow: 0 14px 32px rgba(12,33,56,0.28) !important; }
.rg-ctl:hover { background: rgba(255,255,255,0.28) !important; }

/* booking dock interactions */
[data-dock-toggle]:hover { background: var(--sand-50) !important; }
[data-dock-book]:hover { background: var(--orange-600) !important; box-shadow: 0 12px 28px rgba(238,127,49,0.4) !important; }
[data-dock-book]:active { background: var(--orange-700) !important; box-shadow: none !important; }
[data-dock-property-option]:hover { background: var(--sand-50) !important; }
[data-dock-cal-prev]:hover,
[data-dock-cal-next]:hover { background: var(--sand-50) !important; }
.bk-step-plus:hover { background: var(--blue-600) !important; color: #fff !important; }
[data-dock-guests-done]:hover { background: var(--blue-700) !important; }

/* outline pill (View Details / View All on cards) */
.nh-pill-outline:hover { background: #fff !important; color: var(--ink-900) !important; border-color: #fff !important; }

/* generic card shadow lift */
.nh-card-lift:hover { box-shadow: var(--shadow-lg) !important; }

/* text link underline hover used on dark sections */
.nh-h-orange500-link:hover { color: var(--orange-500) !important; }

/* ============================================================
   MOBILE FIXES (C1–C4). These max-width:768px blocks sit AFTER
   all desktop base hero rules (burger base above; .ubud-hero /
   .home-hero bases are template-inline and beaten by !important).
   ============================================================ */

/* C1 — burger :hover sticks after a tap on touch devices. Doubled
   class raises specificity over the .nh-burger:hover base above. */
@media (hover: none) {
  .nh-burger.nh-burger:hover { background: transparent !important; color: var(--ink-900) !important; }
}

/* C4(b) — gallery lightbox overlays: kill page rubber-banding /
   pull-to-refresh behind the open photo (covers all 3 overlays). */
[data-ng-modal], [data-rg-modal] { touch-action: none; overscroll-behavior: contain; }

/* C2 — Ubud property hero on mobile */
@media (max-width: 768px) {
  .ubud-hero { aspect-ratio: auto !important; height: auto !important; min-height: 82vh !important; max-height: none !important; }
  .ubud-hero > .ubud-hero-media { object-fit: cover !important; }
  .ubud-hero-content { min-height: 82vh !important; height: auto !important; justify-content: center !important; align-items: center !important; text-align: center !important; padding: 24px 22px !important; gap: 9px !important; }
  .ubud-hero-content .ubud-hero-eyebrow { font-size: 11px !important; }
  .ubud-hero-content h1 { font-size: 34px !important; }
  .ubud-hero-content p { font-size: 17px !important; }
  .ubud-hero-cta { flex-wrap: wrap !important; gap: 10px !important; margin-top: 12px !important; }
  .ubud-hero-cta a { padding: 12px 18px !important; font-size: 11px !important; flex: 1 1 auto; text-align: center; white-space: nowrap; }
}

/* C3 — Index / brand-home hero on mobile */
@media (max-width: 768px) {
  .home-hero { height: auto !important; min-height: 100vh !important; min-height: 100svh !important; }
  .home-hero-content { justify-content: center !important; padding: 84px 22px 40px !important; gap: 16px !important; }
  .home-hero-logo { height: 168px !important; }
  .home-hero-content h1 { font-size: 34px !important; }
  .home-hero-content p { font-size: 17px !important; }
}

/* Brand-home "Our Collection" — layer 2: per-swap blur-fade of the active text
   block. Re-triggered from JS (initCollection) by toggling .is-playing. The
   block's entrance on scroll is the outer .reveal wrapper (layer 4). */
.collection-fade.is-playing { animation: collection-cf 650ms var(--ease-out) both; }
@keyframes collection-cf { from { opacity: 0; filter: blur(8px); } to { opacity: 1; filter: blur(0); } }
@media (prefers-reduced-motion: reduce) {
  .collection-fade.is-playing { animation: none; }
}

/* Brand-home "Our Collection" — layer 3: the rail cards' active-state tween.
   This lives here rather than inline on the card, because an inline `transition`
   would override the entrance animation's sibling rules and leave the hover
   state fighting it. Kept to height and box-shadow only: the entrance owns
   opacity and transform (layer 4), so the two never clobber each other. */
.collection-card {
  transition: height 460ms var(--ease-out), box-shadow 460ms var(--ease-out);
}

/* Brand-home "Our Collection" — layer 4: the rail cards' entrance.
   A keyframe armed once by initCollectionReveal(), not the shared .reveal
   observer. Two reasons the old scroll-driven fade-up read as "the cards follow
   the scroll": it moved them along the Y axis, the same axis the page moves on
   (and under Lenis smooth scroll the eye cannot tell the two apart), and it
   fired as the rail crossed the viewport's bottom edge — while the section's own
   frame was still widening around it. An X-axis keyframe on its own clock has
   neither problem: once armed it runs to completion at the same speed however
   fast the reader scrolls. Delays come from --card-delay, set per card in JS
   (the stagger is capped on the mobile rail, see initCollectionReveal).
   PHP renders the final state, so no-JS is safe; under reduced motion JS never
   arms the cards, and the rules below are the belt to that braces. */
.collection-card.is-armed { opacity: 0; }
.collection-card.is-in {
  animation: collection-card-in 950ms cubic-bezier(0.16, 1, 0.3, 1) var(--card-delay, 0ms) both;
}
@keyframes collection-card-in {
  from { opacity: 0; transform: translateX(40px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .collection-card.is-armed { opacity: 1; }
  .collection-card.is-in { animation: none; }
}

/* Hero "Explore Collection" chevron — gentle bounce hint. */
.nh-scroll { transition: opacity var(--dur-fast) var(--ease-out); }
.nh-scroll:hover { opacity: 0.82; }
.nh-scroll-chevron { animation: nh-scroll-bounce 1.8s ease-in-out infinite; }
@keyframes nh-scroll-bounce {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(6px); }
}
@media (prefers-reduced-motion: reduce) {
  .nh-scroll-chevron { animation: none; }
}

/* Site-wide floating WhatsApp button (bottom-right, above the booking dock).
   Hidden until the booking dock reveals — JS (initDock) toggles .is-visible so
   the button rises together with the dock and hides whenever the dock hides. */
.natya-wa-float {
  position: fixed;
  right: 24px;
  bottom: 88px;
  z-index: 55;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  filter: drop-shadow(0 6px 16px rgba(12,33,56,0.28));
  opacity: 0;
  transform: translateY(30px) scale(0.4);
  pointer-events: none;
  /* Bouncy pop-in on reveal; quick fade+shrink on hide. */
  transition:
    transform 0.55s cubic-bezier(0.34, 1.56, 0.64, 1),
    opacity 0.3s var(--ease-out),
    filter var(--dur-fast) var(--ease-out);
}
.natya-wa-float.is-visible {
  opacity: 1;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}
.natya-wa-float.is-visible:hover {
  transform: translateY(-3px) scale(1);
  filter: drop-shadow(0 10px 22px rgba(12,33,56,0.34));
}
.natya-wa-float img { width: 100%; height: 100%; display: block; }
@media (max-width: 768px) {
  .natya-wa-float { right: 16px; bottom: 80px; width: 52px; height: 52px; }
}

/* Promo popup (bottom-left). Revealed by initPromo (assets/natya-ui.js) after a
   delay; hidden by default via [hidden]. Sits above the booking dock (z 50).
   Entrance is a slow rise + scale with a blur clearing (same vocabulary as
   .collection-fade); exit keeps the short base transition so the close button
   feels immediate. */
.natya-promo {
  position: fixed;
  left: 24px;
  bottom: 88px; /* level with .natya-wa-float; clears the floating booking dock */
  z-index: 58;
  width: 264px;
  max-width: calc(100vw - 48px);
  opacity: 0;
  transform: translateY(28px) scale(0.96);
  filter: blur(6px);
  transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out), filter var(--dur-base) var(--ease-out);
  pointer-events: none;
}
.natya-promo.is-open {
  opacity: 1;
  transform: translateY(0) scale(1);
  filter: blur(0);
  transition: opacity var(--dur-reveal) var(--ease-out), transform var(--dur-reveal) var(--ease-out), filter var(--dur-reveal) var(--ease-out);
  pointer-events: auto;
}
/* Hide the promo popup while the mobile drawer is open (body.natya-drawer-open,
   set in initDrawer → setMenu) so it never overlaps the open menu. */
body.natya-drawer-open .natya-promo {
  opacity: 0;
  pointer-events: none;
  transform: translateY(28px) scale(0.96);
  filter: blur(6px);
}
@media (prefers-reduced-motion: reduce) {
  .natya-promo {
    transform: none;
    filter: none;
    transition: opacity var(--dur-fast) var(--ease-out);
  }
}
/* Offer slider inside the promo card (2+ offers): translateX track driven by
   initPromoSlider (assets/natya-ui.js), dots + chevrons row under the body. */
.natya-promo__viewport { overflow: hidden; touch-action: pan-y; }
.natya-promo__track {
  display: flex;
  align-items: stretch;
  transition: transform var(--dur-slow) var(--ease-out);
}
.natya-promo__slide { flex: 0 0 100%; min-width: 100%; }
.natya-promo__nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 0 16px 12px;
}
.natya-promo__arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-circle, 50%);
  background: transparent;
  color: var(--ink-500, #667085);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out);
}
.natya-promo__arrow:hover { color: var(--ink-900, #1d2026); background: rgba(29,32,38,0.06); }
.natya-promo__arrow i { width: 16px; height: 16px; }
.natya-promo__dots { display: flex; align-items: center; gap: 6px; }
.natya-promo__dot {
  width: 6px;
  height: 6px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: var(--border-subtle, #eadfce);
  cursor: pointer;
  transition: width var(--dur-base) var(--ease-out), background var(--dur-base) var(--ease-out);
}
.natya-promo__dot[data-active="1"] { width: 18px; background: var(--orange-500, #ee7b30); }
@media (prefers-reduced-motion: reduce) {
  .natya-promo__track { transition: none; }
}
.natya-promo__card {
  position: relative;
  overflow: hidden;
  background: var(--surface-card, #fff);
  border: 1px solid var(--border-subtle, #eadfce);
  border-radius: var(--radius-lg, 14px);
  box-shadow: var(--shadow-lg, 0 18px 40px rgba(29,32,38,0.13));
}
.natya-promo__close {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-circle, 50%);
  background: rgba(255,255,255,0.9);
  color: var(--ink-900, #1d2026);
  cursor: pointer;
  box-shadow: var(--shadow-sm, 0 4px 12px rgba(29,32,38,0.1));
  transition: background var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.natya-promo__close:hover { background: #fff; transform: scale(1.06); }
.natya-promo__close i { width: 18px; height: 18px; }
.natya-promo__media {
  aspect-ratio: 21 / 10;
  background: var(--sand-100, #f3ece1);
}
.natya-promo__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.natya-promo__body { padding: 14px 16px 16px; }
.natya-promo__eyebrow {
  margin: 0 0 6px;
  font-family: var(--font-body, sans-serif);
  font-size: 11px;
  font-weight: var(--fw-semibold, 600);
  letter-spacing: var(--tracking-widest, 0.12em);
  text-transform: uppercase;
  color: var(--orange-600, #d9661f);
}
.natya-promo__title {
  margin: 0 0 6px;
  font-family: var(--font-display, serif);
  font-size: 17px;
  line-height: 1.2;
  font-weight: var(--fw-semibold, 600);
  color: var(--ink-900, #1d2026);
}
.natya-promo__price {
  margin: 0 0 8px;
  font-family: var(--font-body, sans-serif);
  font-size: 15px;
  font-weight: var(--fw-semibold, 600);
  color: var(--orange-500, #ee7f31);
}
.natya-promo__text {
  margin: 0 0 12px;
  font-family: var(--font-body, sans-serif);
  font-size: 13px;
  line-height: 1.5;
  color: var(--stone-600, #57606a);
}
.natya-promo__actions { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.natya-promo__cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 8px 16px;
  border-radius: var(--radius-pill, 999px);
  background: var(--blue-600, #1c5fa7);
  color: #fff;
  font-family: var(--font-body, sans-serif);
  font-size: 13px;
  font-weight: var(--fw-semibold, 600);
  text-decoration: none;
  transition: background var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.natya-promo__cta:hover { background: var(--orange-500, #ee7f31); transform: translateY(-2px); }
.natya-promo__link {
  font-family: var(--font-body, sans-serif);
  font-size: 13px;
  font-weight: var(--fw-medium, 500);
  color: var(--blue-600, #1c5fa7);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur-fast) var(--ease-out);
}
.natya-promo__link:hover { border-bottom-color: currentColor; }
@media (max-width: 768px) {
  .natya-promo { left: 12px; bottom: 80px; max-width: calc(100vw - 88px); }
}
@media (prefers-reduced-motion: reduce) {
  .natya-promo { transition: opacity var(--dur-base) linear; transform: none; }
  .natya-promo.is-open { transform: none; }
  .natya-promo__cta:hover, .natya-promo__close:hover { transform: none; }
}

/* ============================================================
 * Sticky-reveal footer
 * DOM (header.php + footer.php): .natya-page > [ .natya-main , footer ]
 * .natya-main is the opaque "curtain" over the footer; as it scrolls past its
 * end, the footer — pinned sticky at the viewport bottom — is revealed like a
 * curtain opening. Native scroll (Lenis removed for perf — see functions.php).
 * ============================================================ */
.natya-main {
  position: relative;
  z-index: 2;
  /* Solid bg so the sticky footer stays hidden behind the content until reveal.
     Matches .natya-page (--sand-50); override per-page if a section bleeds. */
  background: var(--sand-50);
}
.natya-page > footer {
  position: sticky !important; /* beats footer_v2.php inline position:relative */
  bottom: 0 !important;
  z-index: 0 !important;
}
/* The footer must fit the viewport to fully reveal. No margin trick needed: the
   footer sits in normal flow after .natya-main, so its own height reserves the
   space.
   When the footer is TALLER than the viewport the reveal backfires: pinned at
   bottom: 0 its top edge sits above the viewport and, since scrolling can never
   push a sticky element past its normal position, that top strip (the stacked
   logo) is unreachable — it reads as a cropped logo. Below the mobile stack
   breakpoint, and on short viewports where the desktop footer also overflows,
   drop back to normal flow so the whole footer scrolls into view. */
@media (max-width: 860px), (max-height: 760px) {
  .natya-page > footer {
    position: relative !important;
    bottom: auto !important;
    z-index: 2 !important; /* above .natya-main: no curtain to hide behind */
  }
}

/* ============================================================
 * Newsletter band (template-parts/site_newsletter.php)
 * Full-width brand-blue CTA at the top of the footer: headline + blurb (left),
 * AJAX email form (right). Native form (assets/natya-newsletter.js), no plugin.
 * Splits to one centered column on mobile.
 * ============================================================ */
.nh-newsletter {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  background: var(--blue-600);
  color: #fff;
}
/* Batik accent layer: the shared Natya pattern (same PNG the mobile drawer uses)
   painted white through a mask, kept faint so the headline stays legible. */
.nh-newsletter::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: #fff;
  opacity: 0.07;
  /* Pattern masked by a right→left fade: batik solid on the right, dissolving
     toward the left. Two mask layers intersected (pattern ∩ gradient). */
  -webkit-mask-image: url('patterns/natya-pattern.png'), linear-gradient(to left, #000 0%, #000 20%, transparent 60%);
  mask-image: url('patterns/natya-pattern.png'), linear-gradient(to left, #000 0%, #000 20%, transparent 60%);
  -webkit-mask-repeat: repeat, no-repeat;
  mask-repeat: repeat, no-repeat;
  -webkit-mask-size: 300px, 100% 100%;
  mask-size: 300px, 100% 100%;
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
}
.nh-newsletter__inner {
  position: relative;
  z-index: 1;
  max-width: 1320px;
  margin: 0 auto;
  padding: 44px 32px;
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: 48px;
  align-items: center;
}
.nh-newsletter__text {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.nh-newsletter__eyebrow {
  text-transform: uppercase;
  letter-spacing: var(--tracking-wider);
  font-size: 11.5px;
  font-weight: var(--fw-semibold);
  color: var(--orange-300);
}
.nh-newsletter__title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 32px;
  line-height: 1.1;
  color: #fff;
}
.nh-newsletter__blurb {
  margin: 0;
  font-size: 15px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.82);
  max-width: 440px;
}
.nh-newsletter-form {
  width: 100%;
  max-width: 460px;
  justify-self: end;
}
.nh-newsletter-fields {
  display: flex;
  gap: 10px;
  align-items: stretch;
  flex-wrap: nowrap;
}
.nh-newsletter-form input[type="email"] {
  flex: 1 1 auto;
  min-width: 0;
  padding: 13px 16px;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  background: #fff;
  color: var(--ink-900);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.4;
  transition: box-shadow var(--dur-fast) var(--ease-out);
}
.nh-newsletter-form input[type="email"]::placeholder {
  color: var(--stone-500);
}
.nh-newsletter-form input[type="email"]:focus {
  outline: none;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.45);
}
.nh-newsletter-form button[type="submit"] {
  flex: 0 0 auto;
  white-space: nowrap;
  border: 1px solid var(--orange-500);
  background: var(--orange-500);
  color: #fff;
  text-transform: uppercase;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-wider);
  padding: 14px 26px;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.nh-newsletter-form button[type="submit"]:hover {
  background: var(--orange-600);
  border-color: var(--orange-600);
}
.nh-newsletter-form button[type="submit"]:disabled {
  opacity: 0.6;
  cursor: default;
}
/* AJAX response message (success / error) — light for contrast on blue */
.nh-newsletter-msg {
  margin-top: 10px;
  font-size: 13px;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.9);
}
.nh-newsletter-msg:empty { margin-top: 0; }
.nh-newsletter-msg.is-error { color: #ffd9d2; }

@media (max-width: 860px) {
  .nh-newsletter__inner {
    grid-template-columns: 1fr;
    gap: 22px;
    padding: 36px 24px;
    text-align: center;
  }
  .nh-newsletter__text { align-items: center; }
  .nh-newsletter__blurb { max-width: 100%; }
  .nh-newsletter-form { justify-self: stretch; max-width: 100%; margin: 0 auto; }
}
@media (max-width: 480px) {
  .nh-newsletter-fields { flex-direction: column; align-items: stretch; }
  .nh-newsletter-form button[type="submit"] { width: 100%; }
}

/* Language dropdown (topbar, beside Contact) — native <details> chevron toggle. */
.nh-lang { position: relative; }
.nh-lang > summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; gap: 5px;
  padding-left: 16px; margin-left: -12px; border-left: 1px solid rgba(250,247,242,0.22);
  color: rgba(250,247,242,0.8); font-size: 11.5px; font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-wider); user-select: none;
  transition: color var(--dur-fast) var(--ease-out);
}
.nh-lang > summary::-webkit-details-marker { display: none; }
.nh-lang > summary:hover { color: var(--orange-300); }
.nh-lang-chev { transition: transform 0.2s var(--ease-out); }
.nh-lang[open] .nh-lang-chev { transform: rotate(180deg); }
/* z-index beats .nh-drawer (70): the topbar stays tappable above the open drawer. */
.nh-lang-menu {
  position: absolute; top: calc(100% + 7px); right: 0; z-index: 80;
  display: flex; flex-direction: column; min-width: 68px; padding: 4px;
  background: var(--blue-natya); border: 1px solid rgba(250,247,242,0.14);
  border-radius: var(--radius-md); box-shadow: 0 8px 24px rgba(29,32,38,0.28);
}
/* Options are links to Polylang's own per-language URLs. The button resets stay:
   the menu grows to the plugin's language names, which are full words. */
.nh-lang-opt {
  padding: 8px 14px; text-decoration: none; border-radius: 4px;
  background: transparent; border: 0; cursor: pointer;
  font-family: var(--font-body); text-align: left; width: 100%;
  color: rgba(250,247,242,0.75); font-size: 11.5px; font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-wider);
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.nh-lang-opt:hover { background: rgba(250,247,242,0.08); color: var(--orange-300); }
.nh-lang-opt.is-active { color: var(--orange-300); }

/* Ambient-music mute toggle. Markup from natya_ambient_music(); behaviour in
   natya-ui.js (initAmbientMusic), which parks it in the hero's bottom-left
   corner (.is-in-hero) and leaves it there — it scrolls away with the banner
   instead of following the viewport. Templates with no banner keep the fixed
   rules below, same corner. Either way syncMusicClearance() adds .is-raised only
   when something actually covers it. data-state swaps volume-2 / volume-x. */
.natya-music__audio { display: none; }
.natya-music {
  position: fixed;
  left: 24px;
  bottom: 88px; /* mirrors .natya-wa-float; clears the floating booking dock */
  z-index: 56;
  /* Hidden until initAmbientMusic() reveals it — bouncy pop-in, matching the
     other floating controls. */
  opacity: 0;
  transform: translateY(30px) scale(0.4);
  pointer-events: none;
  transition:
    transform 0.55s cubic-bezier(0.34, 1.56, 0.64, 1),
    opacity 0.3s var(--ease-out);
}
.natya-music.is-in-hero {
  position: absolute;
  left: 32px;
  bottom: 32px;
  z-index: 6; /* above the hero scrim/tint overlays */
}
/* Only when the corner is genuinely taken — hero copy that reaches into it, or
   the promo popup / dock floats parked over it (syncMusicClearance in
   natya-ui.js). Inside a hero the toggle climbs to its top-left; on a banner-less
   page the same function sets an inline `bottom` that clears the overlap. */
.natya-music.is-in-hero.is-raised { top: 32px; bottom: auto; }
/* Overlay header: the banner starts under the navbar, so the raised corner has
   to begin below it (.nh-overlay-header is set by initHeaderScroll). */
.nh-overlay-header .natya-music.is-in-hero.is-raised { top: calc(var(--nh-head-h) + 20px); }
.natya-music.is-visible {
  opacity: 1;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}
.natya-music__btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; padding: 0;
  border: 1px solid rgba(28,95,167,0.16);
  border-radius: var(--radius-circle);
  background: rgba(250,247,242,0.92);
  color: var(--blue-600);
  cursor: pointer;
  backdrop-filter: blur(6px);
  box-shadow: 0 6px 16px rgba(12,33,56,0.18);
  transition:
    transform var(--dur-fast) var(--ease-out),
    color var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out),
    box-shadow var(--dur-fast) var(--ease-out);
}
.natya-music.is-visible .natya-music__btn:hover {
  transform: translateY(-3px);
  color: var(--orange-500);
  border-color: rgba(238,127,49,0.4);
  box-shadow: 0 10px 22px rgba(12,33,56,0.24);
}
.natya-music__btn:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 3px; }
/* natya_icons.js sizes the injected svg from the placeholder's computed box;
   the hidden icon measures 0, so pin both explicitly. */
.natya-music__icon { width: 20px; height: 20px; }
.natya-music__icon svg { width: 20px; height: 20px; }
.natya-music[data-state="playing"] .natya-music__icon--off,
.natya-music[data-state="muted"] .natya-music__icon--on { display: none !important; }
/* Soft pulse while the track is audible, so the control reads as "on". */
.natya-music[data-state="playing"] .natya-music__btn {
  animation: natya-music-pulse 2.8s var(--ease-out) infinite;
}
@keyframes natya-music-pulse {
  0%, 100% { box-shadow: 0 6px 16px rgba(12,33,56,0.18), 0 0 0 0 rgba(238,127,49,0.28); }
  50%      { box-shadow: 0 6px 16px rgba(12,33,56,0.18), 0 0 0 7px rgba(238,127,49,0); }
}
@media (max-width: 768px) {
  .natya-music { left: 16px; bottom: 80px; }
  .natya-music.is-in-hero { left: 16px; bottom: 20px; }
  .natya-music.is-in-hero.is-raised { top: 16px; bottom: auto; }
  .natya-music__btn { width: 40px; height: 40px; }
  .natya-music__icon, .natya-music__icon svg { width: 18px; height: 18px; }
}
@media (prefers-reduced-motion: reduce) {
  .natya-music[data-state="playing"] .natya-music__btn { animation: none; }
  .natya-music.is-visible .natya-music__btn:hover { transform: none; }
  .natya-music { transition: opacity var(--dur-base) linear; transform: none; }
  .natya-music.is-visible { transform: none; }
}

/* ============================================================
   Masonry gallery + lightbox (natya_render_masonry / natya_render_gallery)
   Shared by the Dining section and every standalone venue body — the rules
   lived in property-dining.php's inline <style> until both needed them.
   ============================================================ */
.ng-masonry { column-count: 3; column-gap: 16px; }
@media (max-width: 900px) { .ng-masonry { column-count: 2; column-gap: 14px; } }
@media (max-width: 460px) { .ng-masonry { column-count: 2; column-gap: 10px; } }
.ng-item { break-inside: avoid; margin-bottom: 16px; border-radius: var(--radius-lg); overflow: hidden; cursor: pointer; position: relative; box-shadow: var(--shadow-sm); }
.ng-item img { width: 100%; display: block; transition: transform 700ms cubic-bezier(0.16,1,0.3,1); }
.ng-item::after { content: ""; position: absolute; inset: 0; background: rgba(12,33,56,0); transition: background 300ms ease; pointer-events: none; }
.ng-item:hover img { transform: scale(1.05); }
.ng-item:hover::after { background: rgba(12,33,56,0.12); }
@media (prefers-reduced-motion: reduce) { .ng-item img { transition: none; } }
@keyframes ngFade { from { opacity: 0; } to { opacity: 1; } }
.ng-ctl:hover { background: rgba(255,255,255,0.28) !important; }

/* ============================================================
 * Map attribution behind an "i" (property-explore-map.php)
 * The OpenStreetMap credit is required by ODbL, but the printed chip is loud on
 * a map this size, so it moves behind a labelled toggle — the pattern the OSMF
 * attribution guidelines allow for interactive maps. Reachable in one click,
 * which is the whole obligation; Leaflet's own attribution bar is switched off
 * in the template. The button is deliberately unobtrusive but never invisible.
 * ============================================================ */
/* Leaflet's own .leaflet-control margin is 10px on every side; 8px sits the
   button closer to the corner without touching the map's edge. */
.natya-attr { display: flex; align-items: flex-end; gap: 6px; margin: 8px !important; }
.natya-attr [hidden] { display: none !important; }
.natya-attr-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; padding: 0;
  border: 1px solid rgba(28,95,167,0.18);
  border-radius: var(--radius-circle);
  background: rgba(250,247,242,0.86);
  color: var(--stone-500);
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(12,33,56,0.14);
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out);
}
.natya-attr-btn:hover { background: #fff; color: var(--blue-600); border-color: rgba(28,95,167,0.4); }
.natya-attr-btn:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.natya-attr-btn[aria-expanded="true"] { background: #fff; color: var(--blue-600); border-color: rgba(28,95,167,0.4); }
.natya-attr-panel {
  background: rgba(255,255,255,0.94);
  color: var(--stone-500);
  font-family: var(--font-body);
  font-size: 10px;
  line-height: 1.5;
  white-space: nowrap;
  padding: 3px 8px;
  border-radius: var(--radius-sm);
  box-shadow: 0 2px 6px rgba(12,33,56,0.14);
}
.natya-attr-panel a { color: var(--blue-600); text-decoration: underline; }
/* Side by side would push the panel off a phone-width map, so it stacks above. */
@media (max-width: 560px) {
  .natya-attr { flex-direction: column; align-items: flex-end; gap: 5px; }
  .natya-attr-panel { white-space: normal; max-width: 62vw; text-align: right; }
}
