/*
 * N43Mont — animations.css
 * ─────────────────────────────────────────────────────────────────────────
 * Loaded separately from the Tailwind-compiled app.css because these rules
 * target classes/attributes added dynamically by app.js at runtime
 * (html.js-reveal, .revealed, .n43-filtered, etc). Tailwind's content
 * scanner only sees literal class names inside .php files, so anything
 * JS-only would be purged if it lived inside input.css.
 * ─────────────────────────────────────────────────────────────────────────
 */

/* ── Smooth scroll ─────────────────────────────────────────────────────── */
html {
  scroll-behavior: smooth;
  -webkit-font-smoothing: antialiased;
}

/* ── data-reveal scroll animation ─────────────────────────────────────────
   PHASE 1 (no JS):        fully visible — zero special styles.
   PHASE 2 (JS confirmed):  html.js-reveal is added by app.js.
   PHASE 3 (in viewport):   .revealed is added by IntersectionObserver.
─────────────────────────────────────────────────────────────────────────── */
[data-reveal] {
  opacity: 1;
  transform: translateY(0);
  transition: none;
}

html.js-reveal [data-reveal]:not(.revealed) {
  opacity: 0;
  transform: translateY(28px);
  transition:
    opacity   0.7s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}

html.js-reveal [data-reveal].revealed {
  opacity: 1;
  transform: translateY(0);
}

/* Stagger direct children inside a revealed grid/container */
html.js-reveal [data-reveal].revealed > *:nth-child(1) { transition-delay: 0ms;   }
html.js-reveal [data-reveal].revealed > *:nth-child(2) { transition-delay: 70ms;  }
html.js-reveal [data-reveal].revealed > *:nth-child(3) { transition-delay: 140ms; }
html.js-reveal [data-reveal].revealed > *:nth-child(4) { transition-delay: 210ms; }
html.js-reveal [data-reveal].revealed > *:nth-child(5) { transition-delay: 280ms; }
html.js-reveal [data-reveal].revealed > *:nth-child(6) { transition-delay: 350ms; }

@media (prefers-reduced-motion: reduce) {
  html.js-reveal [data-reveal]:not(.revealed) {
    opacity: 1;
    transform: translateY(0);
    transition: none;
    will-change: auto;
  }
  html.js-reveal [data-reveal].revealed > * {
    transition-delay: 0ms !important;
  }
}

/* ── Global link & button transitions ─────────────────────────────────── */
a, button {
  transition-property: color, background-color, border-color, box-shadow, transform, opacity;
  transition-duration: 200ms;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}

/* ── Image hover zoom ──────────────────────────────────────────────────── */
.img-zoom { overflow: hidden; }
.img-zoom img {
  transition: transform 0.7s cubic-bezier(0.25, 0.46, 0.45, 0.94);
  will-change: transform;
}
.img-zoom:hover img { transform: scale(1.06); }

/* ── Card lift effect ──────────────────────────────────────────────────── */
.card-lift {
  transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.35s ease;
}
.card-lift:hover {
  transform: translateY(-6px);
  box-shadow: 0 20px 40px -8px rgba(0, 0, 0, 0.15);
}

/* ── Underline slide-in for links ─────────────────────────────────────── */
.link-underline { position: relative; display: inline-block; }
.link-underline::after {
  content: '';
  position: absolute;
  bottom: -2px;
  left: 0;
  width: 0;
  height: 1px;
  background: currentColor;
  transition: width 0.3s ease;
}
.link-underline:hover::after { width: 100%; }

/* ── Amenity card hover ────────────────────────────────────────────────── */
.amenity-item {
  transition: background-color 0.2s ease, border-color 0.2s ease,
              box-shadow 0.2s ease, transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.amenity-item:hover {
  background-color: #ffffff;
  border-color: #d6d3d1;
  box-shadow: 0 4px 12px -2px rgba(0,0,0,0.08);
  transform: translateY(-3px);
}

/* ── Nav link underline slide-in ──────────────────────────────────────── */
.nav-link { position: relative; padding-bottom: 2px; }
.nav-link::after {
  content: '';
  position: absolute;
  bottom: -2px;
  left: 0;
  width: 0;
  height: 1.5px;
  background: currentColor;
  transition: width 0.25s ease;
  border-radius: 2px;
}
.nav-link:hover::after,
.nav-link.active::after { width: 100%; }

/* ── Hero scroll indicator line ───────────────────────────────────────── */
@keyframes scrollLine {
  0%   { transform: scaleY(0); transform-origin: top; }
  50%  { transform: scaleY(1); transform-origin: top; }
  51%  { transform-origin: bottom; }
  100% { transform: scaleY(0); transform-origin: bottom; }
}
.scroll-line { animation: scrollLine 2s ease-in-out infinite; }

/* ── Generic fade-up keyframe ──────────────────────────────────────────── */
@keyframes fadeInUp {
  from { opacity: 0; transform: translateY(20px); }
  to   { opacity: 1; transform: translateY(0); }
}
.animate-fade-up { animation: fadeInUp 0.7s cubic-bezier(0.22, 1, 0.36, 1) both; }
/* NOTE: a previous version had `body { animation: fadeInUp 0.4s ease both; }` here,
   applied unconditionally on every page load, ungated by html.js-reveal like every
   other animation in this file. Removed — it was an unnecessary inconsistency that
   briefly forced opacity:0→1 on <body> (and therefore every position:fixed child,
   including the header, since CSS opacity affects fixed-position descendants too)
   on every single page load regardless of JavaScript state. */

/* ── Gallery filter tabs ───────────────────────────────────────────────── */
.gallery-tab {
  transition: background-color 0.2s ease, border-color 0.2s ease,
              color 0.2s ease, box-shadow 0.2s ease;
}
.gallery-tab:hover { box-shadow: 0 2px 8px rgba(0,0,0,0.08); }

/* ── Review card lift ──────────────────────────────────────────────────── */
.review-card {
  transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1),
              box-shadow 0.35s ease,
              border-color 0.35s ease;
  /* NOTE: only border-color is touched here — border-width/style stay
     exactly as set by the Tailwind classes already on the element
     (border border-stone-700/50). Using the `border` shorthand here
     would have reset those to `none`/`transparent`, wiping out the
     element's default border entirely. */
}
.review-card:hover {
  transform: translateY(-6px);
  border-color: rgba(250, 204, 21, 0.45); /* warm gold, echoes the star rating color */
  box-shadow:
    0 0 0 1px rgba(250, 204, 21, 0.12),
    0 0 28px rgba(250, 204, 21, 0.22),
    0 20px 40px -12px rgba(0, 0, 0, 0.5);
}
/* Quote mark and avatar get a subtle lift too, reinforcing the "alive" feel */
.review-card-quote {
  transition: opacity 0.35s ease, transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}
.review-card:hover .review-card-quote {
  opacity: 0.9;
  transform: scale(1.08);
}
.review-card-avatar {
  transition: box-shadow 0.35s ease;
}
.review-card:hover .review-card-avatar {
  box-shadow: 0 0 0 2px rgba(250, 204, 21, 0.5);
}

@media (prefers-reduced-motion: reduce) {
  .review-card {
    transition: border-color 0.2s ease;
  }
  .review-card:hover {
    transform: none;
  }
}

/* ── Focus ring polish ─────────────────────────────────────────────────── */
:focus-visible {
  outline: 2px solid #78716c;
  outline-offset: 3px;
  border-radius: 4px;
}

/* ── Instagram grid hover ──────────────────────────────────────────────── */
#instagram-feed a { transition: transform 0.3s ease, opacity 0.3s ease; }
#instagram-feed a:hover { transform: scale(1.03); opacity: 0.9; }

/* ── Form input focus glow ─────────────────────────────────────────────── */
input:focus, select:focus, textarea:focus {
  outline: none;
  box-shadow: 0 0 0 3px rgba(120, 113, 108, 0.15);
  border-color: #a8a29e !important;
  transition: box-shadow 0.2s ease, border-color 0.2s ease;
}

/* ── Trust badge glow (footer) ────────────────────────────────────────── */
@keyframes trustGlow {
  0%, 100% { border-color: rgba(120, 113, 108, 0.35); box-shadow: none; }
  50%      { border-color: rgba(255, 255, 255, 0.4);
             box-shadow: 0 0 10px rgba(255,255,255,0.12), 0 0 20px rgba(255,255,255,0.06); }
}
.trust-badge { animation: trustGlow 3s ease-in-out infinite; }
.trust-badge:nth-child(2) { animation-delay: 1s; }
.trust-badge:nth-child(3) { animation-delay: 2s; }

/* ── Footer "Book Now" button pulse ───────────────────────────────────── */
.footer-book-btn::before {
  content: '';
  position: absolute;
  inset: -3px;
  border-radius: 9999px;
  background: white;
  opacity: 0;
  animation: btnPulse 3s ease-in-out infinite;
  z-index: -1;
}
@keyframes btnPulse {
  0%, 100% { opacity: 0;    transform: scale(1);    }
  50%      { opacity: 0.06; transform: scale(1.04); }
}

/* ── Lodgify widget positioning ───────────────────────────────────────────
   The Lodgify calendar/date-picker renders as a portal that must escape
   every parent stacking context to float correctly above the page.

   Rule: NEVER set position:relative on [class*="ldg-"] elements — doing
   so traps the calendar inside its parent's stacking context and breaks
   its positioning (this caused the "floating date selector" bug).

   Instead: keep the booking sections free of z-index/transform/isolation,
   and only raise the z-index of Lodgify's own portal/modal layers.
─────────────────────────────────────────────────────────────────────────── */
#booking {
  position: relative; /* positioning context only — no z-index/isolation */
}

:root {
  --ldg-component-modal-z-index: 99999 !important;
  --ldg-psb-modal-z-index: 99999 !important;
  --ldg-bnb-modal-z-index: 99999 !important;
}

[class*="ldg-modal"],
[class*="ldg-overlay"],
[class*="ldg-portal"],
[class*="ldg-dropdown"],
[class*="ldg-calendar"],
[class*="ldg-datepicker"],
[class*="ldg-popup"] {
  z-index: 99999 !important;
  position: fixed !important;
}

/* ── Card hover glitch-line fix ───────────────────────────────────────────
   Rounded cards that translate on :hover can show a 1px seam at the
   border-radius edge due to GPU compositing layer boundaries. Forcing a
   stable stacking context + pre-composited layer eliminates the artifact.
─────────────────────────────────────────────────────────────────────────── */
.group.rounded-2xl,
.group.rounded-xl,
article.group {
  isolation: isolate;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
}
.group.rounded-2xl img,
.group.rounded-xl img,
article.group img {
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

/* ── WordPress admin bar compatibility ───────────────────────────────────
   WordPress core renders #wpadminbar at z-index:99999, height 32px desktop
   / 46px mobile (<783px), position:fixed, top:0 — for every LOGGED-IN user
   viewing the front-end (which is exactly how a site owner tests changes).

   Our header is z-[100] and also position:fixed;top:0 — without this fix,
   the admin bar paints ON TOP of the header's top ~32px, visually cutting
   off the logo/nav and making the sticky header look broken or glitchy
   while logged in, even though the underlying fixed positioning is 100%
   correct. Logged-out visitors never see this — only admins testing while
   signed in are affected, which is a very common false-positive bug report.
─────────────────────────────────────────────────────────────────────────── */
body.admin-bar .site-header {
  top: 32px;
}
@media screen and (max-width: 782px) {
  body.admin-bar .site-header {
    top: 46px;
  }
}

/* ═══════════════════════════════════════════════════════════════════════
   STAT COUNTERS (Quick Stats section)
   ─────────────────────────────────────────────────────────────────────
   Fully independent of the data-reveal / js-reveal system above — uses
   its own class namespace (js-counters-armed, .stat-counter, .star-fill-item)
   and its own dedicated IntersectionObserver in app.js. This guarantees it
   can never interact with, conflict with, or be affected by scroll-reveal,
   the sticky header, or the gallery/lightbox — by design, per explicit
   requirement that new effects must not risk the already-working systems.
═══════════════════════════════════════════════════════════════════════ */

.stat-card {
  transition: border-color 0.3s ease, background-color 0.3s ease;
}

/* Stars: visible by default (safe fallback if JS never runs) */
.star-fill-item {
  opacity: 1;
  transform: scale(1);
}
/* Only animate once JS confirms it can run */
html.js-counters-armed .star-fill-item {
  opacity: 0;
  transform: scale(0.3) rotate(-15deg);
  transition: opacity 0.45s ease, transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
  transition-delay: var(--star-delay, 0ms);
}
html.js-counters-armed [data-star-row].stars-visible .star-fill-item {
  opacity: 1;
  transform: scale(1) rotate(0deg);
}

@media (prefers-reduced-motion: reduce) {
  html.js-counters-armed .star-fill-item {
    opacity: 1;
    transform: scale(1);
    transition: none;
  }
}

/* ═══════════════════════════════════════════════════════════════════════
   REVIEWS MARQUEE (two-row auto-scrolling testimonial carousel)
   ─────────────────────────────────────────────────────────────────────
   100% pure CSS animation — no JavaScript drives the scrolling itself,
   which means it cannot conflict with any JS module on the page, working
   or otherwise. Cards are duplicated in the PHP markup (rendered twice
   per row) so translateX(-50%) produces a perfectly seamless infinite
   loop with no visible seam or jump.
═══════════════════════════════════════════════════════════════════════ */

.reviews-marquee-track {
  overflow: hidden;
  /* Explicit scrollbar suppression across all browser engines, even though
     overflow:hidden already prevents one — belt-and-braces so no scrollbar
     can ever flash during the animation on any device/browser. */
  scrollbar-width: none;
  -ms-overflow-style: none;
  -webkit-mask-image: linear-gradient(to right, transparent 0%, black 6%, black 94%, transparent 100%);
  mask-image: linear-gradient(to right, transparent 0%, black 6%, black 94%, transparent 100%);
}
.reviews-marquee-track::-webkit-scrollbar {
  display: none;
  width: 0;
  height: 0;
}

.reviews-marquee-row {
  display: flex;
  gap: 1.25rem;
  width: max-content;
  padding: 0 1.5rem;
  will-change: transform;
}

.reviews-marquee-row.marquee-ltr {
  animation: n43MarqueeLTR 50s linear infinite;
}
.reviews-marquee-row.marquee-rtl {
  animation: n43MarqueeRTL 55s linear infinite;
}

/* Pause both rows when hovering the whole marquee area — lets a visitor
   actually read a card instead of chasing it while it scrolls away.
   Three overlapping selectors (wrap / track / row) guarantee the pause
   triggers regardless of which exact element the cursor lands on. */
.reviews-marquee-wrap:hover .reviews-marquee-row,
.reviews-marquee-track:hover .reviews-marquee-row,
.reviews-marquee-row:hover {
  animation-play-state: paused;
}

@keyframes n43MarqueeLTR {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
@keyframes n43MarqueeRTL {
  from { transform: translateX(-50%); }
  to   { transform: translateX(0); }
}

@media (prefers-reduced-motion: reduce) {
  .reviews-marquee-row.marquee-ltr,
  .reviews-marquee-row.marquee-rtl {
    animation: none;
  }
  .reviews-marquee-track {
    overflow-x: auto;
  }
}
