/* Vivly Living — Home popup (HotM / Promotion), spec 2026-07-30.
   Figma reads: overlay/panel 51:259, 51:528, 51:518, title/CTA 52:617, 52:638
   (pixel-digest.md's popup section — the values below are pixel-sourced,
   not invented).

   Markup (template-parts/popup.php):
     #vl-popup(.is-open)[hidden]
       .vl-popup__overlay
       .vl-popup__close   (overlay layer — lightbox pattern, 2026-07-31)
       .vl-popup__panel.vl-popup__panel--hotm|--promo
         .vl-popup__inner
           .vl-popup__copy   (title, body, optional CTA, optional terms)
           .vl-popup__media  (hotm: template-parts/card-plot.php; promo: img)

   js/popup.js toggles [hidden] ↔ .is-open (rAF'd so the entrance transition
   runs from the hidden state — see that file's open()). Above ALL chrome:
   header (z 50), nav drawer (z 55 overlay / 60 panel) — overlay 70, panel 71
   so the popup always wins. */

.vl-popup {
    position: fixed;
    inset: 0;
    z-index: 70;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Top gutter reserves headroom for the × floating ABOVE the panel
       (48px disc + 12px gap + 12px breathing = 72; Liam, 2026-07-31). */
    padding: 72px 40px 40px;
}

/* Positioning anchor: shrink-wraps the panel so the × can hang off its
   top-right corner, clear of the panel (Liam, 2026-07-31). */
.vl-popup__box {
    position: relative;
    width: min(1563px, 100%);
}

.vl-popup[hidden] {
    display: none;
}

/* Scroll lock via a body class, not an inline style (review fix 2026-07-30):
   nav.js's off-canvas drawer also toggles document.body.style.overflow
   directly, and its close() resets it to '' unconditionally — if the popup
   had set the inline style, a drawer open/close cycle while the popup is
   open would silently unlock page scroll out from under it. A class both
   sides can't stomp on each other's way avoids the race. */
body.vl-popup-open {
    overflow: hidden;
}

.vl-popup__overlay {
    position: absolute;
    inset: 0;
    background: rgba(50, 56, 59, 0.8); /* = --vl-ink at 80% (node fill) */
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.25s ease;
}

.vl-popup.is-open .vl-popup__overlay {
    opacity: 1;
}

.vl-popup__panel {
    position: relative;
    z-index: 71;
    /* The WRAPPER's padding defines the viewport gutter (40px, stepping
       to 20px on mobile below) — the panel just fills its content box.
       (A calc(100vw−40) width here previously lost a flex-shrink fight
       with the wrapper's padding — Liam caught the phantom gutters,
       2026-07-31.) The panel is a rounded SHELL (overflow hidden): the
       inner __scroll owns scrolling + padding, so the × and the __more
       fade pin to the shell's true bottom/corners (Liam, 2026-07-31 —
       the sticky fade couldn't cross the old scroller's bottom padding,
       and its corners sat square on the radius). */
    width: 100%; /* the __box carries the min(1563px, 100%) cap now */
    max-height: calc(100vh - 112px); /* wrapper gutters: 72 top + 40 bottom */
    display: flex;
    flex-direction: column;
    overflow: hidden;
    box-sizing: border-box;
    background: var(--vl-cream);
    border-radius: 20px;
    box-shadow: 0 4px 4px rgba(0, 0, 0, 0.15);
    /* Entrance animation lives on the SHELL (the rule split for the
       __scroll refactor briefly stranded opacity:0 on the scroller with
       nothing revealing it — an invisible, "empty" popup. Liam caught it
       live, 2026-07-31). */
    opacity: 0;
    transform: translateY(4px);
    transition: opacity 0.25s ease, transform 0.25s ease;
}

.vl-popup__scroll {
    overflow: auto;
    min-height: 0; /* let the flex child actually shrink and scroll */
    padding: 100px; /* node: content top 100, title x-offset 100 */
}

.vl-popup.is-open .vl-popup__panel {
    opacity: 1;
    transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
    .vl-popup__overlay,
    .vl-popup__panel {
        transition: none;
    }
}

/* Close × — floats just ABOVE the panel's top-right corner, clear of it,
   anchored to .vl-popup__box. Brick disc, brick-dark hover — the header
   Contact pill's exact rest/hover pair (Liam, 2026-07-31, superseding the
   morning's ink disc). */
.vl-popup__close {
    position: absolute;
    top: -60px; /* 40px disc + 20px gap above the panel (Liam) */
    right: 0;
    z-index: 72;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border: none;
    border-radius: 50%;
    background: var(--vl-brick);
    color: var(--vl-white);
    cursor: pointer;
    transition: background-color 0.2s ease;
}

.vl-popup__close svg {
    width: 18px;
    height: 18px;
    stroke: currentColor;
    stroke-width: 2.5;
    stroke-linecap: round;
}

.vl-popup__close:hover {
    background: var(--vl-brick-dark); /* header.css contact-pill hover */
}

.vl-popup__close:focus-visible {
    outline: 2px solid var(--vl-cornflower);
    outline-offset: 2px;
}

@media (max-width: 767px) {
    .vl-popup {
        padding: 72px 20px 20px; /* side/bottom gutter 20 (established); top keeps the × headroom */
    }
}

/* ── Interior — 750/100/513 (hotm) / 513/100/750 (promo); fr ratio keeps the
   750:513 proportion at any panel width while the 100px gap stays fixed
   (exact match at the panel's 1563px max: 750+100+513 = 1363 = 1563 − 2×100). ── */
.vl-popup__inner {
    display: grid;
    column-gap: 100px;
    align-items: stretch;
}

/* Grid areas (Liam, 2026-07-31 — T&Cs placement): desktop puts the terms
   UNDER the copy column while the media spans both rows; stacked (≤1024)
   reorders to copy → media → terms. The terms element is a direct grid
   child in the markup for exactly this. */
.vl-popup__copy {
    grid-area: copy;
}

.vl-popup__media {
    grid-area: media;
}

.vl-popup__inner > .vl-popup__terms {
    grid-area: terms;
}

/* Column model (Liam live review 2026-07-31, replacing the fr-ratio
   split): the 513px column is RIGID — it is the plot-card grid's native
   card width (hotm: the card; promo: the copy column) — and only the
   750px column flexes with the viewport (hotm: copy; promo: the image,
   which cover-crops gracefully). With 513 + the 100 gap locked, the
   flexing column would fall to ~130px by a 1025 viewport, so the RIGID
   513 is a ≥1281 guarantee only. Small desktop (1025–1280) keeps TWO
   COLUMNS (Liam, 2026-07-31 follow-up) via the proportional fr split +
   a 50px gap — both columns relax together there (nothing at that width
   shows the 513 grid card anyway; the plot grids are snap slides).
   Stacks ≤1024. */
.vl-popup__panel--hotm .vl-popup__inner {
    grid-template-columns: minmax(0, 1fr) 513px;
    grid-template-areas:
        "copy media"
        "terms media";
}

.vl-popup__panel--promo .vl-popup__inner {
    /* EQUAL columns for the promotion (Liam, 2026-07-31 — supersedes the
       rigid-513 copy column; that stays a HOTM-only trait where it is the
       plot-card grid width). 100px gap from the base rule; columns centre
       vertically against each other (align-items, Liam same day). */
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas:
        "copy media"
        "terms media";
    /* (align-items: center tried and removed same day, Liam 2026-07-31 —
       with the 3:2 lock kept, columns top-align like HotM's.) */
}

.vl-popup__panel--promo .vl-popup__media {
    align-self: start; /* hug the 3:2 image, top-aligned (restored with
                          the centring removal) */
}

@media (min-width: 1025px) and (max-width: 1280px) {
    /* Gap stays the sitewide 100px (Liam, 2026-07-31 — reverted the brief
       50px squeeze); the fr columns absorb the width instead. */
    .vl-popup__panel--hotm .vl-popup__inner {
        grid-template-columns: 750fr 513fr;
    }

    /* (Promo needs no band override — its equal columns hold at every
       side-by-side width.) */

    .vl-popup__inner {
        column-gap: 70px; /* 100 → 70 in this band only (Liam, 2026-07-31) */
    }

    .vl-popup__inner > .vl-popup__terms {
        margin-top: 50px; /* 70 → 50 in this band only (Liam, 2026-07-31) */
    }
}

.vl-popup__inner > * {
    min-width: 0;
}

.vl-popup__title {
    margin: 0 0 25px; /* title→copy, node-read */
    color: var(--vl-black);
    font-size: var(--vl-text-display);
    font-weight: var(--vl-weight-regular);
    line-height: 1; /* sitewide big-heading rule (Liam, 2026-07-23) */
}

/* Title→copy widened to 50px — BOTH layouts (Liam live review 2026-07-31;
   promo joined HotM's rule later the same day). */
.vl-popup__panel--hotm .vl-popup__title,
.vl-popup__panel--promo .vl-popup__title {
    margin-bottom: 50px;
}

.vl-popup__title strong {
    font-weight: var(--vl-weight-semibold);
}

.vl-popup__body {
    margin: 0 0 50px; /* copy→CTA (or copy→terms, when no CTA — margins
                          collapse with .vl-popup__terms' own margin-top,
                          below, so the gap is 50px either way) */
    color: var(--vl-black);
    font-size: var(--vl-text-card-title); /* 24px */
    line-height: 1.1667; /* unitless, node 28/24 */
}

.vl-popup__body p {
    margin: 0 0 1em;
}

.vl-popup__body p:last-child {
    margin-bottom: 0;
}

.vl-popup__body strong {
    font-weight: var(--vl-weight-semibold);
}

/* CTA = the dev-card pill (card-development.css .vl-dev-card__cta: 209×40,
   brick pill, arrow ::after) — reused verbatim via the second class on the
   link. Its own margin-top (18px, meant for that card's internal rhythm)
   is not wanted here: .vl-popup__body's margin-bottom already sets the gap. */
.vl-popup__cta.vl-dev-card__cta {
    margin-top: 0;
    text-decoration: none;
}

/* Hover feedback (card-development.css only scopes .vl-dev-card__cta's hover
   to a .vl-dev-card ancestor, which the popup's CTA doesn't have — review
   fix 2026-07-30). .vl-dev-card__cta already carries both transitions
   (background-color 0.2s, ::after's transform 0.2s) — this just supplies
   the popup-scoped trigger with matching values. */
.vl-popup__cta:hover {
    background: var(--vl-brick-dark);
}

.vl-popup__cta:hover::after {
    transform: translateX(10px);
}

.vl-popup__terms {
    margin: 70px 0 0; /* 50 → 70 (Liam live review 2026-07-31) */
    color: var(--vl-black);
    font-size: var(--vl-text-sm);
    line-height: 22px;
}

/* Promo media = a plain <img>, so it needs its own rounding/clip. HotM
   media = the plot card, which already rounds + clips itself
   (card-plot.php/dev-plots.css .vl-plot-card) — an overflow:hidden wrapper
   here would clip that card's hover lift/shadow (review fix 2026-07-30),
   so these two properties are scoped to the promo layout only. */
.vl-popup__panel--promo .vl-popup__media {
    border-radius: 20px;
    overflow: hidden;
}

/* The whole HotM card is a link to the plot page (Liam, 2026-07-31) —
   the card's own hover lift (dev-plots.css --available:hover) supplies
   the affordance. */
.vl-popup__cardlink {
    display: block;
    color: inherit;
    text-decoration: none;
}

.vl-popup__cardlink:focus-visible {
    outline: 2px solid var(--vl-cornflower);
    outline-offset: 3px;
    border-radius: 20px;
}

/* HotM: the plot card sits at its NATURAL height, top-aligned (frame
   52:604 — card top = content top). Without this the grid stretches the
   media column to the copy column's height and .vl-plot-card__body's
   flex:1 (equal-row machinery from the dev page) absorbs the excess as a
   void under the meta rows (Liam live review 2026-07-31). */
.vl-popup__panel--hotm .vl-popup__media {
    align-self: start;
}

/* ...and the body's own 230px min-height (dev-plots.css ≥768 — the
   price-less-cards-match-full-cards client rule, whose budget INCLUDES
   the 40px CTA this card doesn't render) — without both fixes a ~58px
   void sat under the meta rows (Liam live review 2026-07-31). No sibling
   rows to height-match in a popup. */
.vl-popup__panel--hotm .vl-plot-card__body {
    min-height: 0;
}

.vl-popup__image {
    display: block;
    width: 100%;
    aspect-ratio: 3 / 2; /* the sitewide image ratio — Liam wavered then
                            kept it ON (2026-07-31): predictable crop,
                            standard "landscape 3:2" client brief. */
    height: auto;
    object-fit: cover;
}

/* (Promo media needs no align-self — the inner's align-items: center
   places it, and the 3:2 image fixes its height either way.) */

/* ── Scroll cue (Liam, 2026-07-31): sticky ink fade + bobbing chevron at
   the panel's visible foot while content continues below — popup.js
   toggles .has-more on the root, clearing near the bottom. Ink gradient
   per Liam ("the ink colour would be the opacity fade colour"), which
   also gives the white hero chevron asset its backdrop. Decorative:
   pointer-events none, aria-hidden markup. Bleeds over the panel's side
   padding (margins per tier below). ── */
.vl-popup__more {
    position: absolute; /* pinned to the SHELL's true bottom; the shell's
                           overflow:hidden clips it to the 20px radius */
    inset-inline: 0;
    bottom: 0;
    z-index: 1;
    height: 100px;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    padding-bottom: 16px;
    background: linear-gradient(to bottom, rgba(50, 56, 59, 0), rgba(50, 56, 59, 0.85));
    opacity: 0;
    transition: opacity 0.25s ease;
    pointer-events: none;
}

.vl-popup.has-more .vl-popup__more {
    opacity: 1;
}

@media (prefers-reduced-motion: no-preference) {
    .vl-popup__more img {
        animation: vl-popup-bob 2s ease-in-out infinite; /* the hero cue's drop-bounce */
    }

    @keyframes vl-popup-bob {
        0%,
        100% {
            transform: translateY(0);
        }

        50% {
            transform: translateY(8px);
        }
    }
}

/* (No per-tier margins needed on __more anymore — absolute inset-inline 0
   spans the shell at every width.) */

/* ── Stacked ≤1024 (returned from the brief ≤1280 detour — small desktop
   keeps two fr columns, block above, Liam 2026-07-31): single column,
   copy first (already first in the DOM), media second, 50px gap — same
   for hotm and promo. Panel padding 50 covers the 1025–1280 band too,
   separate rule below. ── */
@media (max-width: 1280px) {
    .vl-popup__scroll {
        /* Top = bottom (Liam, 2026-07-31 — the ×-lane top padding died
           when the × moved to the overlay layer). */
        padding: 50px 40px;
    }
}

@media (max-width: 1024px) {

    .vl-popup__panel--hotm .vl-popup__inner,
    .vl-popup__panel--promo .vl-popup__inner {
        grid-template-columns: 1fr;
        grid-template-areas:
            "copy"
            "media"
            "terms"; /* T&Cs below the plot/image when stacked (Liam, 2026-07-31) */
        row-gap: 50px;
    }

    /* HOTM ONLY (Liam, 2026-07-31): stacked order is title → plot card →
       copy(+CTA) → T&Cs. The copy wrapper dissolves (display: contents)
       so its children place as grid items by order; areas drop to auto
       flow. Promo keeps the plain copy→image→terms stack above. Visual
       reorder only — DOM/reading order unchanged. */
    .vl-popup__panel--hotm .vl-popup__inner {
        grid-template-areas: none;
    }

    .vl-popup__panel--hotm .vl-popup__copy {
        display: contents;
    }

    .vl-popup__panel--hotm .vl-popup__title {
        order: 1;
        margin-bottom: 0; /* the 50px row-gap is the rhythm now */
    }

    .vl-popup__panel--hotm .vl-popup__media {
        grid-area: auto;
        order: 2;
    }

    .vl-popup__panel--hotm .vl-popup__body {
        order: 3;
        margin-bottom: 0; /* gap replaces the copy→CTA margin */
    }

    .vl-popup__panel--hotm .vl-popup__cta {
        order: 4;
        justify-self: start; /* grid item now — don't stretch the pill */
    }

    .vl-popup__panel--hotm .vl-popup__inner > .vl-popup__terms {
        grid-area: auto;
        order: 5;
    }

    .vl-popup__inner > .vl-popup__terms {
        margin-top: 0; /* the 50px row-gap is the stack rhythm; the 70px
                          margin is the desktop panel-foot value (grid
                          margins don't collapse with gaps) */
    }
}

@media (max-width: 767px) {
    /* (Mobile wrapper padding lives with the ×-headroom rule further up:
       72px 20px 20px.) */

    .vl-popup__scroll {
        /* Top = bottom here too (Liam, 2026-07-31). */
        padding: 50px 20px;
    }

    .vl-popup__panel--hotm .vl-popup__inner,
    .vl-popup__panel--promo .vl-popup__inner {
        row-gap: 40px; /* 50 → 40 on mobile (Liam, 2026-07-31) */
    }

    .vl-popup__panel--promo .vl-popup__title {
        margin-bottom: 30px; /* the HotM title's mobile step, promo edition
                                (HotM's own is gap-driven in its stacked
                                reorder — this layout keeps the margin) */
    }

    /* (The mobile 30px title margin died with the stacked HOTM reorder —
       the 50px row-gap owns the rhythm there now, rule above.) */
}
