/* ============================================================
   AZ Party Mart — Shared Styles
   Design tokens: primary-900 #48139a · accent-400 #fb7185
                  surface #fdf8f6
   ============================================================ */

:root {
    --primary-900: #48139a;
    --accent-400:  #fb7185;
    --surface:     #fdf8f6;
}

/* ── Base ────────────────────────────────────────────────── */

/* overflow-x must be on <html>, not just <body>. AOS parks fade-left/fade-right
   elements at translateX(±100px) until they scroll into view, and an element
   below the fold never animates — so the page is 100px wider than the viewport
   the whole time it sits there. Clipping on <body> hides the paint but does NOT
   stop a mobile browser widening the LAYOUT VIEWPORT to fit it: at a 375px
   device width the viewport became 459px, so every `w-full` element laid out at
   459 and the header's hamburger landed at x=443 — off-screen and only reachable
   by side-scrolling. Setting it on <html> constrains the layout viewport itself,
   and the fade-in still animates in from the clipped edge as intended. */
/* BOTH html and body are required — this was measured, not assumed. body alone
   (the previous state) let the layout viewport widen to 459px. html alone does
   too: with body back to `visible` the overflow returns at exactly 84px and the
   hamburger goes back to x=443. Only the pair holds the viewport at 375px.
   Checked that this does not shift the scrolling element to <body>:
   document.scrollingElement stays documentElement, window.scrollTo reaches 900,
   and an anchor jump to #contact reaches 4336. */
html,
body {
    overflow-x: hidden;
}

body {
    background-color: var(--surface);
    color: #1f2937;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

::selection {
    background-color: var(--accent-400);
    color: #fff;
}

/* ── Scrollbar ───────────────────────────────────────────── */
::-webkit-scrollbar            { width: 8px; }
::-webkit-scrollbar-track     { background: var(--surface); }
::-webkit-scrollbar-thumb     { background: #cbb5ff; border-radius: 10px; }
::-webkit-scrollbar-thumb:hover{ background: #8e54ff; }

/* ── Layout utilities ────────────────────────────────────── */
.text-balance      { text-wrap: balance; }
.clip-diagonal     { clip-path: polygon(0 0, 100% 0, 100% 95%, 0 100%); }
.clip-diagonal-bottom { clip-path: polygon(0 5%, 100% 0, 100% 100%, 0 100%); }

/* ── Glassmorphism nav ───────────────────────────────────── */
.glass-nav {
    background: rgba(253, 248, 246, 0.92) !important;
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-bottom: 1px solid rgba(255,255,255,0.3);
    box-shadow: 0 4px 30px rgba(0,0,0,0.07);
}

/* Flip nav text to dark when glass kicks in */
.glass-nav .nav-text {
    color: #48139a !important;
}

/* ── Mobile menu overlay ─────────────────────────────────────
   The overlay carries flex-col / justify-center / items-center, but those only do
   anything if it is actually a flex container. Tailwind's `hidden` is display:none,
   so removing it left the element at its default display:block and the links
   rendered top-aligned underneath the fixed header instead of centred. Setting
   display here rather than adding a `flex` class in JS, because the Tailwind Play
   CDN only generates utilities it can see in the markup — a class added at runtime
   would have no rule behind it.

   The overlay must also stay a direct child of <body>. It is position:fixed, and
   .glass-nav applies a backdrop-filter on scroll, which makes an element a
   containing block for its fixed-position descendants — nesting this inside the
   header collapsed it to the header's height once the page was scrolled. */
#mobile-menu:not(.hidden) {
    display: flex;
}

/* ── Services dropdown ───────────────────────────────────── */
.services-dropdown {
    opacity: 0;
    visibility: hidden;
    transform: translateY(-8px);
    transition: opacity 0.2s ease, visibility 0.2s ease, transform 0.2s ease;
    pointer-events: none;
}
.services-parent:hover .services-dropdown,
.services-parent:focus-within .services-dropdown {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
    pointer-events: auto;
}
/* Invisible bridge across the 12px (mt-3) gap so hover survives
   the trip from the trigger to the menu. */
.services-dropdown::before {
    content: "";
    position: absolute;
    top: -14px;   /* covers the 12px mt-3 gap (+ a little slack) */
    left: 0;
    right: 0;
    height: 14px;
}

/* ── Active nav link ─────────────────────────────────────── */
.nav-link.is-active {
    color: var(--accent-400) !important;
}

/* ── Image hover zoom ────────────────────────────────────── */
.img-zoom-container { overflow: hidden; }
.img-zoom-container img {
    transition: transform 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94);
    width: 100%; height: 100%; object-fit: cover;
}
.img-zoom-container:hover img { transform: scale(1.06); }

/* ── Google Maps iframe ──────────────────────────────────── */
.map-container iframe {
    width: 100%; height: 100%; border: 0;
    border-radius: 1rem;
    filter: grayscale(20%) contrast(1.1);
}

/* ── Preloader ───────────────────────────────────────────── */
.preloader {
    position: fixed; inset: 0;
    background-color: var(--primary-900);
    z-index: 9999;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    transition: opacity 0.5s ease;
}
.preloader.fade-out {
    opacity: 0;
    pointer-events: none;
}

.spinner {
    width: 40px; height: 40px;
    border: 3px solid rgba(255,255,255,0.2);
    border-radius: 50%;
    border-top-color: var(--accent-400);
    animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ── Page hero (inner pages) ─────────────────────────────── */
.page-hero {
    background-color: var(--primary-900);
    padding-top: 7rem;
    padding-bottom: 5rem;
    position: relative;
    overflow: hidden;
}

/* ── Storefront-sign hero ────────────────────────────────────
   showroom-storefront-sign.jpg is a wide, diagonal band of text ("PaRtY MaRt"),
   so it only survives a `cover` crop while the hero is wider than the image's
   1.47 ratio. On a phone the hero is taller than it is wide — 375x634, because
   the headline wraps to three lines — and cover then keeps just the middle 40%
   of the image width, which shows huge fragments of two letters and reads as
   abstract blue shapes rather than the store's name.

   Below md, fit the whole sign instead and let --primary-900 fill the rest of
   the hero. !important is needed because background-position is set inline on
   these heroes and background-size comes from Tailwind's bg-cover utility. */
@media (max-width: 767px) {
    .hero-bg-sign {
        background-size: contain !important;
        background-repeat: no-repeat;
        background-position: center 26% !important;
    }
}

/* ── Gallery filter pills ────────────────────────────────── */
.gallery-filter {
    padding: 0.625rem 1.5rem;
    border-radius: 9999px;
    font-family: "Plus Jakarta Sans", sans-serif;
    font-size: 0.875rem;
    font-weight: 600;
    border: 2px solid #e1d5ff;
    color: #48139a;
    background: #fff;
    cursor: pointer;
    transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease,
                box-shadow 0.2s ease, transform 0.15s ease;
    white-space: nowrap;
}
.gallery-filter:hover {
    background: #f0eaff;
    border-color: #ae8aff;
    color: #48139a;
    transform: translateY(-1px);
    box-shadow: 0 4px 14px rgba(72,19,154,0.12);
}
.gallery-filter.active {
    background: var(--primary-900);
    border-color: var(--primary-900);
    color: #fff;
    box-shadow: 0 4px 18px rgba(72,19,154,0.32);
    transform: translateY(0);
}

/* ── Gallery masonry ─────────────────────────────────────── */
.gallery-item { break-inside: avoid; margin-bottom: 1rem; display: block; }

/* ── FAQ accordion ───────────────────────────────────────── */
.faq-answer {
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.35s ease, padding 0.35s ease;
}
.faq-answer.open { max-height: 600px; }
.faq-icon { transition: transform 0.3s ease; }

/* ── Blob / float animations (home page) ─────────────────── */
@keyframes blob {
    0%   { transform: translate(0,0) scale(1); }
    33%  { transform: translate(30px,-50px) scale(1.1); }
    66%  { transform: translate(-20px,20px) scale(0.9); }
    100% { transform: translate(0,0) scale(1); }
}
@keyframes float {
    0%,100% { transform: translateY(0); }
    50%     { transform: translateY(-20px); }
}
.animate-blob   { animation: blob 7s infinite; }
.animate-float  { animation: float 6s ease-in-out infinite; }

/* ── Quote form honeypot ─────────────────────────────────────
   A decoy field that humans never see and naive spam bots fill in because they
   populate every input they find. api/quote.js discards any submission where it
   arrives non-empty.

   Deliberately NOT hidden with `left: -9999px`, the usual honeypot trick. That is
   exactly the off-screen-element pattern that widened the mobile layout viewport
   in the AOS bug above, and re-introducing 9999px of overflow to catch spam would
   trade a working header for it. This is the standard clip-based visually-hidden
   recipe instead: out of flow, 1px, no offset larger than 1px, so it cannot widen
   anything even if the overflow-x guard is ever removed.

   Not `display: none` either — bots increasingly skip fields they can tell are
   undisplayed, and a field they skip catches nothing.

   The three attributes in the markup matter as much as this rule:
     tabindex="-1"      keyboard users can't tab into it
     aria-hidden="true" screen readers don't announce it
     autocomplete="off" browser autofill / password managers don't populate it,
                        which would otherwise silently block a real customer. */
.hp-field {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    border: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

/* ── Quote popup modal ───────────────────────────────────── */
.quote-modal {
    position: fixed;
    inset: 0;
    z-index: 9500;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    background: rgba(15, 4, 38, 0.62);
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.3s ease, visibility 0.3s ease;
}
.quote-modal.is-open { opacity: 1; visibility: visible; }

.quote-modal__dialog {
    position: relative;
    width: 100%;
    max-width: 42rem;
    max-height: 90vh;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    background: #fff;
    border-radius: 1.5rem;
    padding: 1.75rem;
    box-shadow: 0 40px 100px rgba(0, 0, 0, 0.45);
    transform: translateY(18px) scale(0.98);
    transition: transform 0.32s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
@media (min-width: 640px) { .quote-modal__dialog { padding: 2.5rem; } }
.quote-modal.is-open .quote-modal__dialog { transform: none; }

.quote-modal__close {
    position: absolute;
    top: 1rem;
    right: 1rem;
    width: 2.5rem;
    height: 2.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 9999px;
    color: #48139a;
    background: #f0eaff;
    font-size: 1.25rem;
    cursor: pointer;
    transition: background 0.2s ease, color 0.2s ease;
    z-index: 1;
}
.quote-modal__close:hover { background: #e1d5ff; }

@media (prefers-reduced-motion: reduce) {
    .quote-modal, .quote-modal__dialog { transition: none; }
    .quote-modal__dialog { transform: none; }
}
