/* ===========================================================
   Lumière — storefront styling (Liquid Glass / premium beauty)
   Tailwind handles layout utilities; this file holds the
   bespoke effects, animations and form primitives.
   =========================================================== */

:root {
    /* Light-only design. "only light" opts the page out of the automatic dark
       inversion Chrome/Samsung Internet apply on phones set to dark mode —
       without it the cream & gold palette renders as muddy black. */
    color-scheme: only light;

    --gold: #A16207;
    --ink: #1C1917;

    /* The page ground. Warm, not white: at the old #FAFAF9 (Tailwind stone-50)
       the ground sat one value off pure white, so every white card floated on
       nothing and the one sand band read as a stray beige stripe. #FAF7F2 sits
       between white and --sand, which gives white surfaces something to lift
       off and lets the gold read as gold rather than as mustard on white. */
    --cream: #FAF7F2;
    --sand: #F5F0EA;
}

/* ---- Warm section band ----
   Used for the full-bleed sand sections that break up the page. A flat slab of
   --sand next to the cream ground reads as a stripe, so the gradient lifts the
   top edge and settles the bottom, and the gold hairlines tie the band to the
   palette rather than leaving it as an untethered beige box. */
.band-warm {
    background: linear-gradient(180deg, #F7F2E9 0%, var(--sand) 45%, #F1E9DB 100%);
    border-top: 1px solid rgba(161, 98, 7, 0.18);
    border-bottom: 1px solid rgba(161, 98, 7, 0.18);
}

/* Horizontal overflow is clipped so wide hero decoration can't cause sideways
   scrolling — but it must be `clip`, not `hidden`. `overflow-x: hidden` turns
   html/body into scroll containers, which silently breaks `position: sticky`
   on their descendants: the sticky header would scroll away on mobile instead
   of pinning. `clip` does the same visual job without creating a scroll
   container. `hidden` stays first as the fallback for browsers without clip. */
html {
    -webkit-font-smoothing: antialiased;
    overflow-x: hidden;
    overflow-x: clip;

    /* Stated here as well as on <body class="bg-cream">, for two reasons: the
       root canvas colour is what shows through before Tailwind's CDN script has
       run, and an explicitly painted background gives a dark-mode filter nothing
       transparent to fall back on. */
    background-color: var(--cream);
    color: var(--ink);
}
body {
    overflow-x: hidden;
    overflow-x: clip;
    background-color: var(--cream);
    color: var(--ink);
}

/* Belt and braces: if a browser insists on evaluating the page as dark, keep the
   surfaces light anyway. This does not defeat Chrome's Auto Dark Theme (that is
   a compositor filter, and color-scheme above is its only opt-out) but it does
   cover browsers that merely flip prefers-color-scheme at the page. */
@media (prefers-color-scheme: dark) {
    html, body {
        background-color: var(--cream);
        color: var(--ink);
    }
}

/* iOS Safari auto-zooms (and stays zoomed) when focusing any input smaller
   than 16px, which makes the page look like it no longer fits. Keep every
   field at 16px on phones so tapping an input never zooms the page. */
@media (max-width: 767px) {
    input, select, textarea { font-size: 16px !important; }
}

/* ---- Glassmorphism ---- */
.glass {
    background: rgba(250, 250, 249, 0.65);
    backdrop-filter: blur(16px) saturate(180%);
    -webkit-backdrop-filter: blur(16px) saturate(180%);
    border: 1px solid rgba(255, 255, 255, 0.4);
}
.glass-nav {
    background: rgba(250, 250, 249, 0.75);
    backdrop-filter: blur(18px) saturate(180%);
    -webkit-backdrop-filter: blur(18px) saturate(180%);
}

/* ---- Announcement marquee ---- */
.marquee {
    width: max-content;
    animation: marquee 40s linear infinite;
}
@keyframes marquee {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
}

/* ---- Animated hero blobs ---- */
.hero-blob {
    position: absolute;
    border-radius: 9999px;
    filter: blur(60px);
    opacity: 0.55;
    z-index: 0;
    pointer-events: none;
    will-change: transform;
}
.hero-blob--1 {
    width: 30rem; height: 30rem;
    background: radial-gradient(circle at 30% 30%, #E9C46A, transparent 70%);
    top: -8rem; left: -6rem;
    animation: float1 18s ease-in-out infinite;
}
.hero-blob--2 {
    width: 26rem; height: 26rem;
    background: radial-gradient(circle at 60% 40%, #D4A373, transparent 70%);
    top: 2rem; right: -8rem;
    animation: float2 22s ease-in-out infinite;
}
.hero-blob--3 {
    width: 22rem; height: 22rem;
    background: radial-gradient(circle at 50% 50%, #CCD5AE, transparent 70%);
    bottom: -10rem; left: 35%;
    animation: float3 26s ease-in-out infinite;
}
@keyframes float1 { 0%,100% { transform: translate(0,0) scale(1);} 50% { transform: translate(40px,30px) scale(1.1);} }
@keyframes float2 { 0%,100% { transform: translate(0,0) scale(1);} 50% { transform: translate(-30px,40px) scale(1.08);} }
@keyframes float3 { 0%,100% { transform: translate(0,0) scale(1);} 50% { transform: translate(20px,-30px) scale(1.12);} }

/* ---- Animated nav underline ---- */
.nav-link { position: relative; }
.nav-link::after {
    content: "";
    position: absolute; left: 0; bottom: -4px;
    height: 1.5px; width: 100%;
    background: var(--gold);
    transform: scaleX(0);
    transform-origin: right;
    transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1);
}
.nav-link:hover::after { transform: scaleX(1); transform-origin: left; }

/* ---- Floating WhatsApp button: attention pulse ----
   An expanding ring rather than a flicker: it catches the eye in peripheral
   vision without the harsh on/off blink, which reads as a broken element and
   is a photosensitivity risk. The ring rides on top of Tailwind's shadow-lg,
   so both shadows are restated in every keyframe. */
.wa-fab {
    animation: wa-pulse 2.6s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
/* Once the user is clearly aiming at it, stop competing for attention. */
.wa-fab:hover,
.wa-fab:focus-visible { animation-play-state: paused; }

@keyframes wa-pulse {
    0% {
        box-shadow: 0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1),
                    0 0 0 0 rgba(37, 211, 102, 0.65);
    }
    70% {
        box-shadow: 0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1),
                    0 0 0 18px rgba(37, 211, 102, 0);
    }
    100% {
        box-shadow: 0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1),
                    0 0 0 0 rgba(37, 211, 102, 0);
    }
}

/* ---- Mobile drawer rows ---- */
.drawer-link {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.7rem 0.85rem;
    border-radius: 0.7rem;
    font-size: 0.95rem;
    font-weight: 500;
    color: var(--ink);
    -webkit-tap-highlight-color: transparent;
    transition: background-color 0.2s ease, color 0.2s ease, transform 0.15s ease;
}
/* Gold marker that grows in from the left edge on hover/focus/press. */
.drawer-link::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    height: 0;
    width: 3px;
    border-radius: 9999px;
    background: var(--gold);
    transform: translateY(-50%);
    transition: height 0.25s ease;
}
.drawer-link:hover,
.drawer-link:focus-visible {
    background: rgba(161, 98, 7, 0.09);
    color: var(--gold);
    outline: none;
}
.drawer-link:hover::before,
.drawer-link:focus-visible::before { height: 58%; }
.drawer-link:active {
    background: rgba(161, 98, 7, 0.16);
    transform: scale(0.985);
}

/* ---- Shine sweep on primary buttons ---- */
.btn-shine { position: relative; overflow: hidden; }
.btn-shine::before {
    content: "";
    position: absolute; top: 0; left: -120%;
    width: 60%; height: 100%;
    background: linear-gradient(120deg, transparent, rgba(255,255,255,0.35), transparent);
    transition: left 0.6s ease;
}
.btn-shine:hover::before { left: 140%; }

/* ---- Filter chips ---- */
.chip {
    display: inline-flex; align-items: center;
    border-radius: 9999px;
    border: 1px solid var(--ink);
    border-color: rgba(28,25,23,0.15);
    padding: 0.4rem 1rem;
    font-size: 0.8rem;
    transition: all 0.2s ease;
    cursor: pointer;
}
.chip:hover { border-color: rgba(28,25,23,0.5); }
.chip--active { background: var(--ink); color: var(--cream); border-color: var(--ink); }

/* ---- Creator videos ----
   All state is a class on .creator-card that the JS flips from the video's own
   events: .is-playing and .is-muted. The CSS just shows the right glyph. The
   centre button fades out while a clip plays and comes back on hover, so the
   clip is not permanently covered but a pause is always one tap away. */
.creator-row { scrollbar-width: none; }
.creator-row::-webkit-scrollbar { display: none; }

.creator-card .cv-center { transition: opacity 0.2s ease; }
.creator-card.is-playing .cv-center { opacity: 0; }
.creator-card.is-playing:hover .cv-center { opacity: 1; }
.creator-card .cv-pause { display: none; }
.creator-card.is-playing .cv-play { display: none; }
.creator-card.is-playing .cv-pause { display: block; }

.creator-card .cv-sound-on { display: none; }
.creator-card:not(.is-muted) .cv-sound-on { display: block; }
.creator-card:not(.is-muted) .cv-sound-off { display: none; }

.creator-card .cv-compress { display: none; }
.creator-card.is-fullscreen .cv-expand { display: none; }
.creator-card.is-fullscreen .cv-compress { display: block; }

/* The card as the fullscreen element: fill the screen on black and letterbox
   the 9:16 clip inside it, so a portrait video on a landscape monitor is
   shown whole rather than cropped. Controls keep their absolute positions. */
.creator-card:fullscreen,
.creator-card:-webkit-full-screen {
    width: 100vw;
    height: 100vh;
    max-width: none;
    border-radius: 0;
    background: #000;
}
.creator-card:fullscreen video,
.creator-card:-webkit-full-screen video {
    width: 100%;
    height: 100%;
    aspect-ratio: auto;
    object-fit: contain;
}

/* Some phone browsers (Samsung Internet's video assistant, Chrome's
   picture-in-picture nudge) paint their own fullscreen / PiP buttons over any
   playing video, with their own flickery hide timer. The attributes on the
   <video> ask them not to; this hides whatever still gets through. Our own
   controls are separate elements, so none of this touches them. */
.creator-card video::-webkit-media-controls,
.creator-card video::-webkit-media-controls-enclosure,
.creator-card video::-webkit-media-controls-panel,
.creator-card video::-webkit-media-controls-overlay-play-button,
.creator-card video::-webkit-media-controls-start-playback-button,
.creator-card video::-webkit-media-controls-fullscreen-button,
.creator-card video::-webkit-media-controls-picture-in-picture-button {
    display: none !important;
    -webkit-appearance: none;
}

/* Tailwind's CDN build has no h-4.5; one rule beats an arbitrary value in markup. */
.creator-card .h-4\.5 { height: 1.125rem; }
.creator-card .w-4\.5 { width: 1.125rem; }

/* ---- Testimonial slider ----
   The row scrolls and snaps natively; the scrollbar is hidden because the
   arrows and dots already say there is more. */
.testimonials-track { scrollbar-width: none; }
.testimonials-track::-webkit-scrollbar { display: none; }

/* ---- Ingredients ----
   One native <details> holds the full description list. Only the chevron
   needs CSS: it turns when the list is open. The label swap on the button is
   done with Tailwind's group-open. */
.ingredients-more .ingredient-chevron { transition: transform 0.2s ease; }
.ingredients-more[open] .ingredient-chevron { transform: rotate(180deg); }
.ingredients-more summary:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* ---- Policy pages ----
   Plain prose rather than a Tailwind class list on every element: these pages
   are edited as text by whoever maintains the shop's wording, and they
   shouldn't have to touch markup classes to add a paragraph. */
.legal { color: var(--ink2); line-height: 1.75; }
.legal h2 { font-family: 'Playfair Display', serif; font-size: 1.5rem; color: var(--ink); margin: 2.5rem 0 0.75rem; }
.legal h3 { font-weight: 600; color: var(--ink); margin: 1.5rem 0 0.4rem; }
.legal p { margin: 0.75rem 0; }
.legal ul { margin: 0.75rem 0; padding-left: 1.1rem; list-style: disc; }
.legal ol { margin: 0.75rem 0; padding-left: 1.3rem; list-style: decimal; }
.legal li { margin: 0.35rem 0; }
.legal a { color: var(--gold); text-decoration: underline; text-underline-offset: 2px; }
.legal strong { color: var(--ink); font-weight: 600; }
.legal table { width: 100%; border-collapse: collapse; margin: 1rem 0; font-size: 0.9rem; }
.legal th, .legal td { text-align: left; padding: 0.6rem 0.5rem; border-bottom: 1px solid var(--line); vertical-align: top; }
.legal th { color: var(--ink); font-weight: 600; }
.legal code { background: var(--sand); border-radius: 4px; padding: 0.1rem 0.35rem; font-size: 0.85em; }

/* A detail nobody has confirmed yet. Deliberately visible on the rendered page,
   not only in the markup, so a placeholder cannot reach production unnoticed.
   Search the views for "needs-detail" to find every one. */
.needs-detail { background: #FEF3C7; color: #92400E; border-bottom: 1px dashed #D97706; padding: 0 0.2rem; border-radius: 3px; font-style: normal; }

/* ---- Form primitives ---- */
.form-label {
    display: block;
    font-size: 0.8rem;
    font-weight: 500;
    margin-bottom: 0.4rem;
    color: var(--ink);
}
.form-input {
    width: 100%;
    border-radius: 0.75rem;
    border: 1px solid #E7E1D8;
    background: #fff;
    padding: 0.7rem 0.9rem;
    font-size: 0.9rem;
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.form-input:focus {
    outline: none;
    border-color: var(--gold);
    box-shadow: 0 0 0 3px rgba(161, 98, 7, 0.15);
}
.form-error { display: block; margin-top: 0.3rem; font-size: 0.75rem; color: #dc2626; }

/* ---- Sortable admin table headers ---- */
.th-sort {
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
    transition: color 0.15s ease;
}
.th-sort:hover { color: var(--gold); }
.th-sort:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }
/* Neutral chevrons until sorted, then the active direction in gold. */
.th-sort::after {
    content: "\2195";
    margin-left: 0.35rem;
    opacity: 0.35;
    font-size: 0.85em;
}
.th-sort--asc::after  { content: "\2191"; opacity: 1; color: var(--gold); }
.th-sort--desc::after { content: "\2193"; opacity: 1; color: var(--gold); }

/* ---- Password show/hide toggle (wrapper injected by site.js) ---- */
.pw-field { position: relative; }
.pw-field .form-input { padding-right: 2.75rem; }
.pw-toggle {
    position: absolute;
    top: 50%;
    right: 0.5rem;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border-radius: 0.5rem;
    color: rgba(28, 25, 23, 0.45);
    cursor: pointer;
    transition: color 0.2s ease, background-color 0.2s ease;
}
.pw-toggle:hover { color: var(--gold); background: rgba(161, 98, 7, 0.09); }
.pw-toggle:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.pw-toggle svg { width: 1.15rem; height: 1.15rem; }

/* ---- Fractional star display (supports 2.5, 3.7, etc.) ---- */
.star-display {
    --rating: 0;
    display: inline-block;
    position: relative;
    line-height: 1;
    white-space: nowrap;
    font-size: 1em;
}
.star-display::before {
    content: "★★★★★";
    letter-spacing: 2px;
    color: #D6D3D1;
}
.star-display__fill {
    position: absolute;
    top: 0;
    left: 0;
    overflow: hidden;
    white-space: nowrap;
    width: calc(var(--rating) / 5 * 100%);
    pointer-events: none;
}
.star-display__fill::before {
    content: "★★★★★";
    letter-spacing: 2px;
    color: #A16207;
}

/* ---- Star rating input (radio-based, no JS) ---- */
.star-rating { display: inline-flex; flex-direction: row-reverse; gap: 4px; }
/* Visually hidden but still focusable, so keyboard users can rate and the
   browser never tries to anchor UI to a zero-size control. */
.star-rating input {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
}
.star-rating label {
    font-size: 1.9rem;
    line-height: 1;
    color: #D6D3D1;
    cursor: pointer;
    transition: color 0.15s ease;
}
.star-rating input:checked ~ label,
.star-rating label:hover,
.star-rating label:hover ~ label { color: #A16207; }
.star-rating input:focus-visible + label { outline: 2px solid #A16207; outline-offset: 2px; border-radius: 4px; }
.star-rating--error label { color: #fca5a5; }

/* ---- Validation state (hide when valid/empty) ---- */
.validation-summary-valid { display: none; }
.field-validation-valid { display: none; }

/* ---- Reduced motion: disable decorative animation ---- */
@media (prefers-reduced-motion: reduce) {
    .marquee, .hero-blob, .wa-fab { animation: none !important; }
    #mobile-menu, #menu-overlay, .drawer-link, .drawer-link::before { transition: none !important; }
    * { scroll-behavior: auto !important; }
}
