/* ============================================
   Lettiva V2 Site Interactions — Shared CSS
   Companion styles for site-v2-interactions.js
   ============================================ */

/* --- Base --- */
/* Prevent horizontal page scroll from overflowing buttons/content.
   overflow-x: clip (not hidden) avoids the fixed-positioning containment
   side-effect that overflow-x: hidden creates in some browsers. */
html, body {
  overflow-x: clip;
  max-width: 100%;
}

/* --- Scroll Reveal ---
   Only applied when .animations-ready is on <html> (added by JS).
   Without JS, all content is fully visible (progressive enhancement). */
.animations-ready [data-reveal] {
  opacity: 0;
  will-change: opacity, transform;
  transition: opacity 0.6s cubic-bezier(0.22, 1, 0.36, 1),
              transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}

.animations-ready [data-reveal="fade-up"] {
  transform: translateY(30px);
}

.animations-ready [data-reveal="fade-in"] {
  transform: none;
}

.animations-ready [data-reveal="slide-left"] {
  transform: translateX(-40px);
}

.animations-ready [data-reveal="slide-right"] {
  transform: translateX(40px);
}

.animations-ready [data-reveal="scale-up"] {
  transform: scale(0.95);
}

[data-reveal].revealed {
  opacity: 1;
  transform: none;
}

/* --- Stagger Reveal ---
   AI agents sometimes write [data-reveal-stagger] > * { opacity: 0 } to
   hide children for a staggered entrance. Our JS adds .revealed to each
   child when the parent enters the viewport. This rule provides a safety
   net so .revealed always wins, even if the agent forgot the reveal state. */
[data-reveal-stagger] > *.revealed {
  opacity: 1 !important;
  transform: none !important;
}

/* --- Lightbox --- */
.lightbox-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0);
  backdrop-filter: blur(0);
  opacity: 0;
  visibility: hidden;
  transition: background 0.35s ease, backdrop-filter 0.35s ease, opacity 0.35s ease, visibility 0.35s ease;
}

.lightbox-overlay.active {
  background: rgba(0, 0, 0, 0.92);
  backdrop-filter: blur(8px);
  opacity: 1;
  visibility: visible;
}

.lightbox-image-wrapper {
  position: relative;
  max-width: 90vw;
  max-height: 85vh;
  display: flex;
  align-items: center;
  justify-content: center;
  transform: scale(0.92);
  opacity: 0;
  transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.35s ease;
}

.lightbox-overlay.active .lightbox-image-wrapper {
  transform: scale(1);
  opacity: 1;
}

.lightbox-image-wrapper img {
  max-width: 90vw;
  max-height: 85vh;
  object-fit: contain;
  border-radius: 4px;
  user-select: none;
  -webkit-user-drag: none;
}

.lightbox-close {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 10000;
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 50%;
  color: #fff;
  font-size: 20px;
  cursor: pointer;
  transition: background 0.2s ease, transform 0.2s ease;
  line-height: 1;
}

.lightbox-close:hover {
  background: rgba(255, 255, 255, 0.2);
  transform: scale(1.1);
}

.lightbox-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 10000;
  width: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 50%;
  color: #fff;
  font-size: 22px;
  cursor: pointer;
  transition: background 0.2s ease, transform 0.2s ease;
  line-height: 1;
}

.lightbox-nav:hover {
  background: rgba(255, 255, 255, 0.2);
  transform: translateY(-50%) scale(1.1);
}

.lightbox-nav--prev {
  left: 16px;
}

.lightbox-nav--next {
  right: 16px;
}

.lightbox-counter {
  position: absolute;
  bottom: 16px;
  left: 50%;
  transform: translateX(-50%);
  color: rgba(255, 255, 255, 0.7);
  font-size: 14px;
  font-family: inherit;
  user-select: none;
}

/* Cursor hint on lightbox-enabled images */
[data-lightbox] img,
img[data-lightbox] {
  cursor: zoom-in;
}

/* --- Accordion --- */
.accordion-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 1rem 0;
  background: none;
  border: none;
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
  font: inherit;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
  color: inherit;
  transition: color 0.2s ease;
}

.accordion-trigger:hover {
  opacity: 0.8;
}

.accordion-trigger::after {
  content: '+';
  flex-shrink: 0;
  margin-left: 1rem;
  font-size: 1.25em;
  font-weight: 300;
  transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}

.accordion-trigger[aria-expanded="true"]::after {
  content: '\2212'; /* minus sign */
  transform: rotate(180deg);
}

.accordion-content {
  overflow: hidden;
  max-height: 0;
  opacity: 0;
  transition: max-height 0.4s cubic-bezier(0.22, 1, 0.36, 1),
              opacity 0.3s ease,
              padding 0.3s ease;
  padding: 0;
}

.accordion-content.open {
  opacity: 1;
  padding-bottom: 1rem;
}

/* --- Carousel --- */
.carousel-wrapper {
  position: relative;
  overflow: hidden;
}

.carousel-track {
  position: relative;
  min-height: 100px;
}

.carousel-slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.5s ease, visibility 0.5s ease;
}

.carousel-slide.active {
  position: relative;
  opacity: 1;
  visibility: visible;
}

.carousel-dots {
  display: flex;
  justify-content: center;
  gap: 8px;
  margin-top: 1.25rem;
  padding: 0;
  list-style: none;
}

.carousel-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.15);
  cursor: pointer;
  padding: 0;
  transition: background 0.25s ease, transform 0.25s ease;
}

.carousel-dot:hover {
  background: rgba(0, 0, 0, 0.3);
}

.carousel-dot.active {
  background: rgba(0, 0, 0, 0.6);
  transform: scale(1.2);
}

/* --- Sticky Nav --- */
[data-sticky-nav] {
  transition: background-color 0.35s cubic-bezier(0.4, 0, 0.2, 1),
              background 0.35s cubic-bezier(0.4, 0, 0.2, 1),
              box-shadow 0.35s cubic-bezier(0.4, 0, 0.2, 1),
              border-color 0.35s cubic-bezier(0.4, 0, 0.2, 1),
              backdrop-filter 0.35s cubic-bezier(0.4, 0, 0.2, 1),
              padding 0.35s cubic-bezier(0.4, 0, 0.2, 1);
}

/* Nav background fallback: provides a sensible default for sites where the
   agent-generated CSS omits a nav background entirely. Wrapped in :where()
   so specificity is 0-0-0 — any site-specific #site-nav rule wins regardless
   of source order (this <link> stylesheet loads after inline <style> blocks).
   build-shared-layout.ts already sets background: var(--color-background)
   on new sites; this is a safety net for older agent-generated sites. */
:where(#site-nav),
:where([data-sticky-nav]) {
  background: var(--color-background);
}

[data-sticky-nav].nav-scrolled {
  background: color-mix(in srgb, var(--color-background) 80%, transparent) !important;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  box-shadow: 0 1px 0 color-mix(in srgb, var(--color-primary) 6%, transparent);
}

/* --- Active Page Indicator --- */
/* Animated underline for nav links (safety net for pre-existing sites
   generated before build-shared-layout added these rules). */
.nav-links a {
  position: relative;
}

.nav-links a::after {
  content: '';
  position: absolute;
  bottom: -4px; left: 0;
  width: 0; height: 2px;
  background: var(--color-accent);
  transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.nav-links a:hover::after { width: 100%; }
.nav-links a[aria-current="page"] { color: var(--color-accent); }
.nav-links a[aria-current="page"]::after { width: 100%; }

.mobile-menu-links a[aria-current="page"] { color: var(--color-accent); }

/* --- Mobile Menu --- */

/* Ensure nav sits above hero / page content so the hamburger is always tappable */
[data-sticky-nav] {
  z-index: 100;
}

/* Prevent double-tap-to-zoom on interactive elements */
[data-mobile-menu-toggle],
[data-lightbox] img,
img[data-lightbox] {
  touch-action: manipulation;
}

.mobile-menu-open {
  overflow: hidden;
}

/* Hide mobile menu from document flow before JS adds .mobile-menu-panel.
   Without this, the menu links render in normal flow on initial paint and
   cause horizontal overflow (body.scrollWidth > viewport width).
   Once JS runs initMobileMenu(), .mobile-menu-panel is added and this
   rule no longer applies — the element becomes a fixed-positioned panel. */
[data-mobile-menu]:not(.mobile-menu-panel) {
  display: none;
}

[data-mobile-menu] {
  transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1),
              opacity 0.35s ease,
              visibility 0.35s ease;
}

/* Default: hidden off-screen right for mobile menu panels */
@media (max-width: 768px) {
  [data-mobile-menu].mobile-menu-panel {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: auto; /* Override inset: 0 from buildSharedLayout — anchor to right edge */
    width: min(320px, 85vw);
    z-index: 9990;
    transform: translateX(100%);
    opacity: 0;
    visibility: hidden;
    overflow-y: auto;
  }

  [data-mobile-menu].mobile-menu-panel.menu-open {
    transform: translateX(0);
    opacity: 1;
    visibility: visible;
  }
}

/* Agent CSS correction: agent sometimes generates
   [data-mobile-menu].mobile-menu-panel { opacity: 1 } as the open state.
   But mobile-menu-panel is a PERMANENT setup class added at DOMContentLoaded —
   using it as an open trigger makes the panel always-visible after JS init.
   The JS always uses .menu-open for the toggled open state.
   Force our rules to win over agent CSS with !important. */
@media (max-width: 768px) {
  [data-mobile-menu].mobile-menu-panel:not(.menu-open) {
    opacity: 0 !important;
    visibility: hidden !important;
    pointer-events: none !important;
    transform: translateX(100%) !important;
  }

  [data-mobile-menu].mobile-menu-panel.menu-open {
    opacity: 1 !important;
    visibility: visible !important;
    pointer-events: auto !important;
    transform: translateX(0) !important;
  }
}

/* Body overlay when mobile menu is open */
.mobile-menu-backdrop {
  position: fixed;
  inset: 0;
  z-index: 9989;
  background: rgba(0, 0, 0, 0);
  visibility: hidden;
  transition: background 0.35s ease, visibility 0.35s ease;
}

.mobile-menu-backdrop.active {
  background: rgba(0, 0, 0, 0.5);
  visibility: visible;
}

/* --- Mobile Menu Close Button --- */
/* Make the X button prominent and tappable (44px minimum touch target) */
.mobile-menu-close,
[data-mobile-menu] [data-mobile-menu-toggle][aria-label*="Close"] {
  min-width: 44px;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.75rem;
  cursor: pointer;
  touch-action: manipulation;
}

/* --- Mobile Menu "More" Section --- */
/* Improve the visual treatment of the overflow section in mobile nav */
.mobile-menu-divider {
  height: 1px !important;
  background: rgba(0, 0, 0, 0.1) !important;
  margin: 1rem 0 0.5rem !important;
}

.mobile-menu-heading {
  font-size: 0.7rem !important;
  font-weight: 700 !important;
  text-transform: uppercase !important;
  letter-spacing: 0.12em !important;
  color: rgba(0, 0, 0, 0.35) !important;
  padding-bottom: 0.25rem !important;
}

/* Overflow links are slightly smaller than primary nav links */
.mobile-menu-heading ~ li a {
  font-size: 1.15rem !important;
  font-weight: 500 !important;
  color: rgba(0, 0, 0, 0.55) !important;
}

.mobile-menu-heading ~ li a:hover {
  color: var(--color-accent) !important;
}

/* --- Lightbox Mobile Improvements --- */
@media (max-width: 768px) {
  .lightbox-close {
    width: 48px;
    height: 48px;
    font-size: 24px;
    top: 12px;
    right: 12px;
    background: rgba(255, 255, 255, 0.25);
  }

  .lightbox-nav {
    width: 40px;
    height: 40px;
  }

  .lightbox-nav--prev { left: 8px; }
  .lightbox-nav--next { right: 8px; }
}

/* --- Back to Top --- */
[data-back-to-top] {
  position: fixed;
  bottom: 2rem;
  right: 2rem;
  z-index: 999;
  opacity: 0;
  visibility: hidden;
  transform: translateY(12px);
  transition: opacity 0.3s ease, visibility 0.3s ease, transform 0.3s ease;
}

[data-back-to-top].visible {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

[data-back-to-top]:hover {
  transform: translateY(-2px);
}

/* --- Empty Section Guards --- */
/* Hide sections whose React island returns null (no data in DB).
   The agent writes static headings + data-component placeholder; when the
   component has no data, it returns null — leaving an orphan section heading.
   CSS :has() checks whether the rendered component class is present in the DOM.
   Supported: Chrome 105+, Firefox 121+, Safari 15.4+

   IMPORTANT: The class names here MUST match what each React wrapper actually
   renders. If you change a wrapper's output class, update the guard here too.
   Validated by: public/site-v2-interactions.test.ts */
/* Empty section guards: hide wrapper sections when the data-connected React
   component returns emptySection() (a hidden div with data-component-empty).
   When a component has no data, it returns <div data-component-empty style="display:none"/>.
   When it HAS data, it renders real content (sections, grids, etc.).
   We detect "empty" by checking for the data-component-empty attribute. */
section:has([data-component-empty]) { display: none; }

/* --- Mobile Responsive Overrides --- */

/* Buttons: allow text to wrap on narrow screens.
   Generated .btn CSS always sets white-space:nowrap, which causes overflow
   when button text is long (e.g. "Celebrating Something Special?"). */
@media (max-width: 768px) {
  .btn, a.btn, button.btn {
    white-space: normal;
    max-width: 100%;
  }
}

/* Inline-style grids: collapse multi-column grids to 1 column on mobile.
   The agent sometimes uses inline style="grid-template-columns:repeat(N,1fr)"
   instead of the .grid-N helper classes, which bypasses class-based media queries.
   Covers 2-, 3- and 4-column variants. */
@media (max-width: 768px) {
  [style*="grid-template-columns:repeat(3"],
  [style*="grid-template-columns: repeat(3"],
  [style*="grid-template-columns:repeat(4"],
  [style*="grid-template-columns: repeat(4"] {
    grid-template-columns: 1fr !important;
  }
}

@media (max-width: 480px) {
  [style*="grid-template-columns:repeat(2"],
  [style*="grid-template-columns: repeat(2"] {
    grid-template-columns: 1fr !important;
  }
}

/* ============================================
   Trust Bar — component layout overrides
   ============================================ */
/* .sb-trust-badges has width:100% by default (correct when standalone).
   When placed as a flex item inside a trust-bar section alongside sibling
   text, that 100% width pushes the text to the next row. Override it to
   auto so the two flex children sit side by side.
   NOTE: trust-strip is a standalone badges-only section (gallery, booking pages)
   where badges should remain centered. Only trust-bar has the side-by-side layout. */
[data-section="trust-bar"] .sb-trust-badges,
[data-section="trust"] .sb-trust-badges {
  width: auto;
}

/* Align badges to the left within the trust-bar (badges sit alongside text).
   trust-strip is excluded — standalone badge sections should stay centered. */
[data-section="trust-bar"] .sb-trust-badges__list--horizontal,
[data-section="trust"] .sb-trust-badges__list--horizontal {
  justify-content: flex-start;
}

/* Trust bar text: fixTrustBar() sets background → var(--color-surface) (light).
   Agent sometimes generates white or light-coloured text which becomes invisible.
   Force readable dark text regardless of what the agent generated. */
[data-section="trust-bar"] p,
[data-section="trust-bar"] h2,
[data-section="trust-bar"] h3,
[data-section="trust-bar"] span:not(.sb-trust-badges__label),
[data-section="trust-strip"] p,
[data-section="trust-strip"] h2,
[data-section="trust-strip"] h3,
[data-section="trust-strip"] span:not(.sb-trust-badges__label),
[data-section="trust"] p,
[data-section="trust"] h2,
[data-section="trust"] h3,
[data-section="trust"] span:not(.sb-trust-badges__label) {
  color: var(--color-text, #1a1a1a) !important;
}

/* ============================================
   Reduced Motion — respect user preferences
   ============================================ */
@media (prefers-reduced-motion: reduce) {
  .animations-ready [data-reveal] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  [data-reveal-stagger] > * {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  .lightbox-overlay,
  .lightbox-image-wrapper,
  .accordion-content,
  .carousel-slide,
  [data-sticky-nav],
  [data-mobile-menu],
  [data-back-to-top],
  .lightbox-close,
  .lightbox-nav,
  .carousel-dot,
  .mobile-menu-backdrop {
    transition: none !important;
  }

  [data-parallax] {
    transform: none !important;
  }
}
