/* ══════════════════════════════════════════════════════════════════════
   PROJECT DETAIL  (zvv-pjx-*)
   ----------------------------------------------------------------------
   One development, sold to members before it lists publicly.

   The direction is an architect's drawing sheet crossed with an inventory
   ledger, because those are the two artifacts this subject actually
   produces: a title block that states project / location / client / date in
   ruled cells, and a release schedule saying how many units are gone.

   So the page is built from hairlines and data type rather than from a stack
   of shadowed white cards, and the one bold thing on it is the ledger — one
   tile per unit, filled as they are taken. A percentage bar abstracts away
   the only figure a buyer acts on; the tiles are the inventory itself,
   countable at a glance. Everything else stays quiet so that reads.

   Type does three jobs and each has a face: Sora carries the name at display
   size, Space Grotesk sets every number and label (the instrument face —
   ledger, figures, stages), Plus Jakarta Sans runs the prose.

   Violet appears in three places only: reserved units, the primary action,
   and the live stage tag. Anything else that wanted colour gets a hairline.

   Light-first tokens with a dark override, scoped under .zvv-pjx so nothing
   leaks into app.css.
   ══════════════════════════════════════════════════════════════════════ */

.zvv-pjx {
    --pj-ink:     #171034;
    --pj-paper:   #f7f5f0;
    --pj-panel:   #ffffff;
    --pj-line:    rgba(23, 16, 52, 0.13);
    --pj-rule:    rgba(23, 16, 52, 0.08);
    --pj-muted:   #6b6486;
    --pj-violet:  #6d28d9;
    --pj-violet-soft: rgba(109, 40, 217, 0.1);

    --pj-display: "Sora", "Plus Jakarta Sans", sans-serif;
    --pj-data:    "Space Grotesk", "Plus Jakarta Sans", sans-serif;

    display: block;
    background: var(--pj-paper);
    color: var(--pj-ink);
}

[data-bs-theme="dark"] .zvv-pjx {
    --pj-ink:     #efeafb;
    --pj-paper:   #0f0a24;
    --pj-panel:   #17102f;
    --pj-line:    rgba(189, 147, 249, 0.2);
    --pj-rule:    rgba(189, 147, 249, 0.12);
    --pj-muted:   #9d94c4;
    --pj-violet:  #bd93f9;
    --pj-violet-soft: rgba(189, 147, 249, 0.14);
}

/* The label opening every block. A ruled caption rather than a coloured pill:
   on a drawing sheet the label is the smallest thing on the page and it still
   tells you where you are. */
.zvv-pjx-eyebrow {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    margin-bottom: 0.55rem;
    font-family: var(--pj-data);
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--pj-muted);
}

.zvv-pjx-eyebrow::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--pj-line);
}

/* ── Hero ─────────────────────────────────────────────────────────────
   The photograph is the site, so it runs full-bleed and the title block sits
   on it — the way a rendering is presented in a brochure. */

.zvv-pjx-hero {
    position: relative;
    display: flex;
    align-items: flex-end;
    min-height: min(84vh, 720px);
    padding: 7rem 0 0;
    overflow: hidden;
    isolation: isolate;
    background: #0f0a24;
}

.zvv-pjx-hero-art {
    position: absolute;
    inset: 0;
    z-index: 0;
}

.zvv-pjx-hero-art img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* Pulled toward the ink so type sits on it without a heavy scrim. */
    filter: saturate(0.82) contrast(1.05);
}

.zvv-pjx-hero-veil {
    position: absolute;
    inset: 0;
    background:
        linear-gradient(180deg, rgba(15, 10, 36, 0.62) 0%, rgba(15, 10, 36, 0.14) 34%, rgba(15, 10, 36, 0.92) 90%),
        linear-gradient(90deg, rgba(15, 10, 36, 0.7) 0%, transparent 64%);
}

.zvv-pjx-hero-inner {
    position: relative;
    z-index: 1;
    width: 100%;
    padding-bottom: 3.6rem;
    color: #f8f6ff;
}

.zvv-pjx-crumbs {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: auto;
    font-family: var(--pj-data);
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: rgba(248, 246, 255, 0.62);
}

.zvv-pjx-crumbs a { color: inherit; text-decoration: none; }
.zvv-pjx-crumbs a:hover { color: #fff; text-decoration: underline; }
.zvv-pjx-crumbs i { font-size: 0.62rem; opacity: 0.55; }

/* The title block: the sheet header, ruled, data-set, above the name.
   Its rule is a pseudo-element rather than a border so the entrance can draw
   it left to right — a border has no geometry to animate. */
.zvv-pjx-sheet {
    position: relative;
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.6rem;
    margin: 2.4rem 0 1.15rem;
    padding-bottom: 0.85rem;
    font-family: var(--pj-data);
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: rgba(248, 246, 255, 0.72);
}

.zvv-pjx-sheet::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 1px;
    background: rgba(248, 246, 255, 0.22);
    transform-origin: left;
}

.zvv-pjx-sheet span { display: inline-flex; align-items: center; gap: 0.45rem; }
.zvv-pjx-sheet .zvv-pjx-flag { font-size: 0.95rem; letter-spacing: 0; }

.zvv-pjx-stage { color: #fff; }

/* A live project is a thing in progress, so its tag has a pulse on it. One
   6px dot — the smallest possible way to say "this is open now". */
.zvv-pjx-stage::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #c4b5fd;
    animation: pjxPulse 2.6s ease-out infinite;
}

@keyframes pjxPulse {
    0%   { box-shadow: 0 0 0 0 rgba(196, 181, 253, 0.55); }
    70%  { box-shadow: 0 0 0 9px rgba(196, 181, 253, 0); }
    100% { box-shadow: 0 0 0 0 rgba(196, 181, 253, 0); }
}

.zvv-pjx-hero h1 {
    margin: 0;
    max-width: 15ch;
    font-family: var(--pj-display);
    font-size: clamp(2.7rem, 6.4vw, 5.4rem);
    font-weight: 800;
    line-height: 0.94;
    letter-spacing: -0.038em;
    color: #fff;
}

/* Headline figures, ruled apart like a schedule row rather than boxed. The
   rule is a pseudo-element for the same reason as the title block's. */
.zvv-pjx-headline {
    position: relative;
    display: flex;
    flex-wrap: wrap;
    gap: 1rem 2.6rem;
    margin: 1.9rem 0 0;
    padding-top: 1.15rem;
}

.zvv-pjx-headline::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: 1px;
    background: rgba(248, 246, 255, 0.22);
    transform-origin: left;
}

.zvv-pjx-headline > div { min-width: 0; }

.zvv-pjx-headline dt {
    font-family: var(--pj-data);
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: rgba(248, 246, 255, 0.6);
}

.zvv-pjx-headline dd {
    margin: 0.25rem 0 0;
    font-family: var(--pj-data);
    font-size: clamp(1.15rem, 2vw, 1.55rem);
    font-weight: 700;
    letter-spacing: -0.01em;
    color: #fff;
    font-variant-numeric: tabular-nums;
}

.zvv-pjx-headline dd.is-accent { color: #c4b5fd; }

/* ── The ledger ────────────────────────────────────────────────────────
   The signature. One tile per unit: solid means taken, hollow means you can
   still have it. It sits between the hero and everything else because it is
   the fact the rest of the page is arguing about. */

.zvv-pjx-ledger {
    position: relative;
    z-index: 2;
    margin-top: -3.4rem;
    padding: 1.7rem 1.8rem 1.55rem;
    border: 1px solid var(--pj-line);
    border-radius: 20px;
    background: var(--pj-panel);
    box-shadow: 0 32px 70px -42px rgba(23, 16, 52, 0.55);
}

.zvv-pjx-ledger-top {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 0.6rem 1.5rem;
    margin-bottom: 1.2rem;
}

.zvv-pjx-ledger-count {
    margin: 0;
    font-family: var(--pj-data);
    font-size: clamp(1.45rem, 3.2vw, 2.05rem);
    font-weight: 700;
    letter-spacing: -0.022em;
    line-height: 1.1;
    color: var(--pj-ink);
    font-variant-numeric: tabular-nums;
}

.zvv-pjx-ledger-count strong { color: var(--pj-violet); font-weight: 700; }

.zvv-pjx-ledger-sub {
    margin: 0.3rem 0 0;
    font-size: 0.86rem;
    color: var(--pj-muted);
}

.zvv-pjx-ledger-key {
    display: flex;
    gap: 1.1rem;
    padding-bottom: 0.2rem;
    font-family: var(--pj-data);
    font-size: 0.64rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--pj-muted);
}

.zvv-pjx-ledger-key span { display: inline-flex; align-items: center; gap: 0.4rem; }

.zvv-pjx-ledger-key i {
    width: 10px;
    height: 10px;
    border-radius: 3px;
    border: 1.5px solid var(--pj-violet);
}

.zvv-pjx-ledger-key .is-taken i { background: var(--pj-violet); }

/* Capped width, not full bleed: 48 tiles stretched across a 1200px panel
   become one thin strip, which is the bar this was meant to replace. Held to
   ~30 per row they stack into a block you read as a set of things. auto-fill
   still handles the range — 48 units and 120 units both land as a block. */
.zvv-pjx-units {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(14px, 1fr));
    gap: 5px;
    max-width: 36rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.zvv-pjx-unit {
    aspect-ratio: 1;
    border-radius: 3px;
    border: 1.5px solid var(--pj-violet-soft);
    background: transparent;
}

.zvv-pjx-unit.is-taken {
    border-color: var(--pj-violet);
    background: var(--pj-violet);
}

/* The reveal: tiles land in order, so the ledger fills the way the building
   sold. Armed by script — without it they are simply drawn in place. */
.zvv-pjx-ledger.is-armed .zvv-pjx-unit {
    opacity: 0;
    transform: scale(0.6);
}

.zvv-pjx-ledger.is-armed.is-in .zvv-pjx-unit {
    opacity: 1;
    transform: none;
    transition: opacity 0.3s ease, transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
    transition-delay: calc(var(--i) * 13ms);
}

/* ── Body ─────────────────────────────────────────────────────────────── */

.zvv-pjx-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 21rem;
    gap: 3.4rem;
    align-items: start;
    padding: 3.2rem 0 4rem;
}

.zvv-pjx-main {
    display: flex;
    flex-direction: column;
    gap: 3.2rem;
    min-width: 0;
}

/* Blocks are ruled, not boxed — the sheet is one surface, divided. */
.zvv-pjx-block { min-width: 0; }

.zvv-pjx-block h2 {
    margin: 0 0 1rem;
    font-family: var(--pj-display);
    font-size: clamp(1.35rem, 2.4vw, 1.85rem);
    font-weight: 700;
    letter-spacing: -0.024em;
    color: var(--pj-ink);
}

.zvv-pjx-prose {
    max-width: 62ch;
    font-size: 1.02rem;
    line-height: 1.72;
    color: var(--pj-muted);
}

/* ── Gallery ──
   The lead shot is tall and the rest stack beside it: a rendering set is not
   a grid of equals, there is always a hero view. */
.zvv-pjx-gallery {
    display: grid;
    grid-template-columns: 1.55fr 1fr;
    /* Equal rows so the stacked column ends level with the lead shot rather
       than leaving a gap under the last one. */
    grid-auto-rows: 1fr;
    gap: 0.9rem;
}

.zvv-pjx-shot {
    position: relative;
    margin: 0;
    overflow: hidden;
    border-radius: 16px;
    background: var(--pj-violet-soft);
}

.zvv-pjx-shot img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 0.6s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.zvv-pjx-shot:hover img { transform: scale(1.045); }

/* The lead sets the height of the whole set; the rest divide the column
   beside it, so the block always squares off however many shots there are. */
.zvv-pjx-shot.is-lead {
    grid-row: span 2;
    aspect-ratio: 4 / 5;
}

.zvv-pjx-shot:not(.is-lead) { min-height: 0; }

/* A lead and a single companion: nothing to stack, so they sit side by side. */
.zvv-pjx-gallery:has(.zvv-pjx-shot:nth-child(2):last-child) .zvv-pjx-shot.is-lead {
    grid-row: auto;
}

/* ── Amenities ──
   A ruled list in two columns. Chips would make eight equal pills; the rules
   keep it a specification. */
.zvv-pjx-amenities {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: 0 2.4rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.zvv-pjx-amenities li {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 0.72rem 0;
    border-bottom: 1px solid var(--pj-rule);
    font-size: 0.95rem;
    color: var(--pj-ink);
}

.zvv-pjx-amenities i { font-size: 0.8rem; color: var(--pj-violet); }

/* ── Payment stages ──
   Numbered because the content is genuinely a sequence: the money moves in
   this order and the order is the terms. The percentage is the marker, so
   there is no invented 01 / 02 / 03 sitting on top of it. */
.zvv-pjx-stages {
    margin: 0;
    padding: 0;
    list-style: none;
}

.zvv-pjx-stage-row {
    display: grid;
    grid-template-columns: 5.4rem 1fr;
    align-items: baseline;
    gap: 1.4rem;
    padding: 1.15rem 0;
    border-top: 1px solid var(--pj-rule);
}

.zvv-pjx-stage-row:last-child { border-bottom: 1px solid var(--pj-rule); }

.zvv-pjx-stage-pct {
    font-family: var(--pj-data);
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--pj-violet);
    font-variant-numeric: tabular-nums;
}

.zvv-pjx-stage-label { font-size: 1rem; color: var(--pj-ink); }

.zvv-pjx-stage-note {
    margin: 1.1rem 0 0;
    font-size: 0.88rem;
    color: var(--pj-muted);
}

/* ── Location ─────────────────────────────────────────────────────────── */

.zvv-pjx-address {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: -0.4rem 0 1rem;
    font-family: var(--pj-data);
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--pj-muted);
}

.zvv-pjx-map {
    height: 22rem;
    border: 1px solid var(--pj-line);
    border-radius: 18px;
    overflow: hidden;
}

/* ── Reservation rail ─────────────────────────────────────────────────── */

.zvv-pjx-rail { min-width: 0; }

.zvv-pjx-card {
    position: sticky;
    top: 5.5rem;
    padding: 1.6rem 1.5rem 1.4rem;
    border: 1px solid var(--pj-line);
    border-radius: 20px;
    background: var(--pj-panel);
    box-shadow: 0 30px 60px -46px rgba(23, 16, 52, 0.6);
}

.zvv-pjx-price {
    margin: 0;
    font-family: var(--pj-data);
    font-size: 2rem;
    font-weight: 700;
    letter-spacing: -0.03em;
    color: var(--pj-ink);
    font-variant-numeric: tabular-nums;
}

.zvv-pjx-price-sub {
    margin: 0.2rem 0 1.2rem;
    font-size: 0.85rem;
    color: var(--pj-muted);
}

.zvv-pjx-cta {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.55rem;
    width: 100%;
    padding: 0.9rem 1rem;
    border: 0;
    border-radius: 13px;
    background: var(--pj-violet);
    color: #fff;
    font-family: var(--pj-data);
    font-size: 0.92rem;
    font-weight: 700;
    text-decoration: none;
    transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.2s ease, filter 0.2s ease;
}

.zvv-pjx-cta:hover {
    color: #fff;
    transform: translateY(-2px);
    filter: brightness(1.08);
    box-shadow: 0 14px 30px -14px rgba(109, 40, 217, 0.8);
}

[data-bs-theme="dark"] .zvv-pjx-cta,
[data-bs-theme="dark"] .zvv-pjx-cta:hover { color: #17102f; }

.zvv-pjx-cta-sub {
    margin: 0.65rem 0 0;
    font-size: 0.78rem;
    line-height: 1.5;
    text-align: center;
    color: var(--pj-muted);
}

.zvv-pjx-secondary {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    margin-top: 0.7rem;
    padding: 0.7rem 1rem;
    border: 1px solid var(--pj-line);
    border-radius: 13px;
    color: var(--pj-ink);
    font-size: 0.86rem;
    font-weight: 600;
    text-decoration: none;
    transition: border-color 0.16s ease, color 0.16s ease;
}

.zvv-pjx-secondary:hover { border-color: var(--pj-violet); color: var(--pj-violet); }

/* The facts continue the title block: label left, value right, ruled. */
.zvv-pjx-facts {
    margin: 1.4rem 0 0;
    padding-top: 0.3rem;
    border-top: 1px solid var(--pj-line);
}

.zvv-pjx-facts > div {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.68rem 0;
    border-bottom: 1px solid var(--pj-rule);
}

.zvv-pjx-facts > div:last-child { border-bottom: 0; }

.zvv-pjx-facts dt {
    font-family: var(--pj-data);
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--pj-muted);
}

.zvv-pjx-facts dd {
    margin: 0;
    font-family: var(--pj-data);
    font-size: 0.92rem;
    font-weight: 700;
    text-align: right;
    color: var(--pj-ink);
    font-variant-numeric: tabular-nums;
}

.zvv-pjx-note {
    display: flex;
    gap: 0.55rem;
    margin: 1.1rem 0 0;
    font-size: 0.8rem;
    line-height: 1.55;
    color: var(--pj-muted);
}

.zvv-pjx-note i { color: var(--pj-violet); }

/* ── Other projects ───────────────────────────────────────────────────── */

.zvv-pjx-more {
    padding: 3rem 0 4.5rem;
    border-top: 1px solid var(--pj-line);
}

/* ── Entrance ─────────────────────────────────────────────────────────
   The sheet draws itself. Rules scale out from the left, then the type they
   underline rises — one sequence in the hero when the page loader clears,
   and a quieter version of the same idea for each block as it is reached.

   Armed by script only (.is-anim), and only when the visitor has not asked
   for less motion, so no JS or no patience leaves every element exactly
   where it belongs. .is-live releases the hero; .is-in releases a block.
────────────────────────────────────────────────────────────────────────── */

.zvv-pjx.is-anim .zvv-pjx-crumbs,
.zvv-pjx.is-anim .zvv-pjx-sheet > span,
.zvv-pjx.is-anim .zvv-pjx-hero h1,
.zvv-pjx.is-anim .zvv-pjx-headline > div {
    opacity: 0;
    transform: translateY(15px);
}

.zvv-pjx.is-anim .zvv-pjx-sheet::after,
.zvv-pjx.is-anim .zvv-pjx-headline::before { transform: scaleX(0); }

/* The photograph settles rather than arrives: it is already there when the
   loader lifts, so it only has to stop moving. */
.zvv-pjx.is-anim .zvv-pjx-hero-art img { transform: scale(1.06); }

.zvv-pjx.is-anim.is-live .zvv-pjx-crumbs,
.zvv-pjx.is-anim.is-live .zvv-pjx-sheet > span,
.zvv-pjx.is-anim.is-live .zvv-pjx-hero h1,
.zvv-pjx.is-anim.is-live .zvv-pjx-headline > div {
    opacity: 1;
    transform: none;
    transition: opacity 0.62s cubic-bezier(0.22, 0.61, 0.36, 1),
                transform 0.62s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.zvv-pjx.is-anim.is-live .zvv-pjx-sheet::after,
.zvv-pjx.is-anim.is-live .zvv-pjx-headline::before {
    transform: none;
    transition: transform 0.7s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.zvv-pjx.is-anim.is-live .zvv-pjx-hero-art img {
    transform: none;
    transition: transform 1.6s cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* The order is the reading order: where it is, what it is called, what it
   costs. Each figure follows the one before it rather than all four landing
   together, so the row reads as a row. */
.zvv-pjx.is-anim.is-live .zvv-pjx-crumbs        { transition-delay: 0.05s; }
.zvv-pjx.is-anim.is-live .zvv-pjx-sheet::after  { transition-delay: 0.12s; }
.zvv-pjx.is-anim.is-live .zvv-pjx-sheet > span:nth-child(1) { transition-delay: 0.2s; }
.zvv-pjx.is-anim.is-live .zvv-pjx-sheet > span:nth-child(2) { transition-delay: 0.26s; }
.zvv-pjx.is-anim.is-live .zvv-pjx-sheet > span:nth-child(3) { transition-delay: 0.32s; }
.zvv-pjx.is-anim.is-live .zvv-pjx-hero h1       { transition-delay: 0.34s; }
.zvv-pjx.is-anim.is-live .zvv-pjx-headline::before { transition-delay: 0.5s; }
.zvv-pjx.is-anim.is-live .zvv-pjx-headline > div:nth-child(1) { transition-delay: 0.58s; }
.zvv-pjx.is-anim.is-live .zvv-pjx-headline > div:nth-child(2) { transition-delay: 0.64s; }
.zvv-pjx.is-anim.is-live .zvv-pjx-headline > div:nth-child(3) { transition-delay: 0.7s; }
.zvv-pjx.is-anim.is-live .zvv-pjx-headline > div:nth-child(4) { transition-delay: 0.76s; }

/* Blocks below the fold: the same move, smaller, when each is reached. */
.zvv-pjx.is-anim .zvv-pjx-reveal {
    opacity: 0;
    transform: translateY(22px);
}

.zvv-pjx.is-anim .zvv-pjx-reveal.is-in {
    opacity: 1;
    transform: none;
    transition: opacity 0.55s cubic-bezier(0.22, 0.61, 0.36, 1),
                transform 0.55s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.zvv-pjx.is-anim .zvv-pjx-reveal .zvv-pjx-eyebrow::after { transform: scaleX(0); transform-origin: left; }

.zvv-pjx.is-anim .zvv-pjx-reveal.is-in .zvv-pjx-eyebrow::after {
    transform: none;
    transition: transform 0.6s cubic-bezier(0.22, 0.61, 0.36, 1) 0.12s;
}

/* Shots arrive in the order they are stacked. */
.zvv-pjx.is-anim .zvv-pjx-reveal .zvv-pjx-shot { opacity: 0; transform: translateY(16px); }

.zvv-pjx.is-anim .zvv-pjx-reveal.is-in .zvv-pjx-shot {
    opacity: 1;
    transform: none;
    transition: opacity 0.55s ease, transform 0.55s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.zvv-pjx.is-anim .zvv-pjx-reveal.is-in .zvv-pjx-shot:nth-child(2) { transition-delay: 0.1s; }
.zvv-pjx.is-anim .zvv-pjx-reveal.is-in .zvv-pjx-shot:nth-child(3) { transition-delay: 0.18s; }
.zvv-pjx.is-anim .zvv-pjx-reveal.is-in .zvv-pjx-shot:nth-child(n+4) { transition-delay: 0.24s; }

/* ── Responsive ───────────────────────────────────────────────────────── */

@media (max-width: 1000px) {
    .zvv-pjx-grid { grid-template-columns: minmax(0, 1fr); gap: 2.6rem; }
    .zvv-pjx-card { position: static; }
}

@media (max-width: 700px) {
    .zvv-pjx-hero { min-height: 76vh; padding-top: 5.5rem; }
    .zvv-pjx-hero-inner { padding-bottom: 3rem; }
    .zvv-pjx-headline { gap: 0.9rem 1.6rem; }
    .zvv-pjx-ledger { margin-top: -2.2rem; padding: 1.3rem 1.15rem 1.15rem; border-radius: 16px; }
    .zvv-pjx-units { grid-template-columns: repeat(auto-fill, minmax(12px, 1fr)); gap: 4px; }
    .zvv-pjx-gallery { grid-template-columns: 1fr; }
    .zvv-pjx-shot.is-lead { grid-row: auto; aspect-ratio: 4 / 3; }
    .zvv-pjx-stage-row { grid-template-columns: 4rem 1fr; gap: 1rem; }
}

@media (prefers-reduced-motion: reduce) {
    .zvv-pjx-stage::before { animation: none; }
    .zvv-pjx-ledger.is-armed .zvv-pjx-unit { opacity: 1; transform: none; }
    .zvv-pjx-ledger.is-armed.is-in .zvv-pjx-unit { transition: none; }
    .zvv-pjx-shot img, .zvv-pjx-cta { transition: none; }
    .zvv-pjx-shot:hover img, .zvv-pjx-cta:hover { transform: none; }

    /* The script does not arm the entrance under reduced motion; these are the
       belt to that brace, in case the class is ever set some other way. */
    .zvv-pjx.is-anim .zvv-pjx-crumbs,
    .zvv-pjx.is-anim .zvv-pjx-sheet > span,
    .zvv-pjx.is-anim .zvv-pjx-hero h1,
    .zvv-pjx.is-anim .zvv-pjx-headline > div,
    .zvv-pjx.is-anim .zvv-pjx-reveal,
    .zvv-pjx.is-anim .zvv-pjx-reveal .zvv-pjx-shot { opacity: 1; transform: none; transition: none; }

    .zvv-pjx.is-anim .zvv-pjx-sheet::after,
    .zvv-pjx.is-anim .zvv-pjx-headline::before,
    .zvv-pjx.is-anim .zvv-pjx-hero-art img,
    .zvv-pjx.is-anim .zvv-pjx-reveal .zvv-pjx-eyebrow::after { transform: none; transition: none; }
}
