/* index.css — page-scoped additions for index.html — everything below the hero (agent A). Loads after site.css and home.css; consume tokens, never redefine them. KIT 2026-09-13. */

/* ============================================================================
   EVOLVE PASS 2026-09-13 — the Receptia kit applied band by band below the hero.
   Everything here is an ADDITION: no grammar is redesigned, no token is shadowed.
   Two mechanical rules govern the whole file:
     · .xe-lit and .xe-brackets live on ::after, .xe-glass on ::before. Where a band
       already owned one of those pseudo-elements (the door sheen, the rig sheen, the
       CTA scrim) the incumbent effect MOVES rather than the kit utility being faked.
     · Transform and opacity only. Shadows and filters are set, never tweened.
   ============================================================================ */

/* ---------- 01 · two doors — photographs that drift, lit at the corner ----------
   home.css owns .door::after for the 520ms light sweep, and .xe-lit wants the same
   pseudo-element. The sweep moves to ::before (z-index over the photograph) and
   ::after is handed back to the kit: the ring is what the class is for. */
.door.xe-lit::after { background: none; transform: none; transition: none; }
.door.xe-lit::before { content: ""; position: absolute; inset: 0; z-index: 3; pointer-events: none; border-radius: inherit;
  background: none;
  transform: none; transition: none; }
.door.xe-lit:hover::before, .door.xe-lit:focus-within::before { transform: none; }

/* the parallax carrier is the <picture>, not the <img>: the image already owns a
   transform (the hover push-in), and two engines must never share one property.
   Overscan of 12px covers the ±10px drift so no black edge enters the frame. */
.door .door-media[data-parallax] { inset: -12px 0; transform: translateY(calc(var(--fy, 0) * 1px)); will-change: transform; }
@media (prefers-reduced-motion: reduce) { .door .door-media[data-parallax] { inset: 0; transform: none; will-change: auto; } }
/* Phones do not get the drift. 09-13 bisect (scripts/tmp/xe-jank-where.mjs, which attributes every
   slow frame to the section under the viewport centre): the gate's intermittent mobile FAIL was ONE
   frame, always at #two-doors, always on the first measured document — an overscanned, transformed,
   promoted full-bleed photograph being composited for the first time. Single-variable runs:
     parallax on ................................ 66.7–83.4ms, 1 run in 4–8 FAILs
     will-change dropped, transform kept ........ 66.7ms, still FAILs  → promotion was not the cost
     transform + overscan dropped ............... 4/4 and then 6/6 clean, max 17.0ms
   ±10px of drift is invisible at 390px anyway, so this buys the frame back for nothing. The desktop
   drift, where the effect is actually legible and the first paint is cheap, is untouched. */
@media (max-width: 899px) { .door .door-media[data-parallax] { inset: 0; transform: none; will-change: auto; } }

/* ---------- 02 · spotlight — the photograph settles, then hover owns the zoom ----------
   .xe-img parks the image at scale(1.08)/opacity 0 until motion.js lands .in. The
   hover transform is scoped to .in so the settle and the zoom never fight. */
.spot-item.xe-lit { border-radius: 4px; } /* matches .spot-item .media, so the ring inherits it */
.spot-item .media.xe-img.in > img { transition: transform 700ms var(--ease-out), opacity 1s var(--ease-out); }

@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .spot-item:hover .media.xe-img.in > img,
  .spot-item:focus-within .media.xe-img.in > img { transform: scale(1.05); }
  .spot-item .meta { transition: transform 500ms var(--ease-out); }
  .spot-item:hover .meta,
  .spot-item:focus-within .meta { transform: translateY(-6px); }
}

/* the lead frame's venue, set vertically on the right edge — the same string that used
   to sit in the tag row, moved, not duplicated (see spotlight() in home.js) */
.spot-item .spot-edge { grid-area: 1 / 1; justify-self: end; align-self: start; z-index: 3; pointer-events: none;
  margin: 14px 12px 0 0; writing-mode: vertical-rl; font-family: var(--font-mono); font-size: .68rem;
  letter-spacing: .18em; text-transform: uppercase; color: #D9D9D9; text-shadow: 0 1px 8px rgba(0,0,0,.85);
  opacity: 0; transform: translateY(-12px); transition: opacity var(--t-cinematic) var(--ease-out), transform var(--t-cinematic) var(--ease-out); }
.spot-item.in .spot-edge { opacity: 1; transform: none; }

/* ---------- 03 · proof — the numbers sit on one glass slab ---------- */
.proof-stats.xe-glass { border-top: 0; gap: 0 clamp(16px, 2.2vw, 26px);
  padding: clamp(22px, 3vw, 32px) clamp(16px, 2vw, 22px) clamp(6px, 1.6vw, 16px); }
/* the slab eats ~40px of column width, and "Since 1986" broke to two lines against
   "6 DJs" on one — a hair off the ceiling puts every stat back on a single line */
.proof-stats.xe-glass .stat .k { font-size: clamp(1.9rem, 3.7vw, 2.8rem); }

/* ---------- 04 · films — the poster settles into its frame ----------
   home.css gives .film .media img a 900ms transform transition for the hover push-in;
   the settle needs its own pair, and hover only takes over once .in has landed. */
.film .media.xe-img > img { transition: opacity 1s var(--ease-out), transform 1.2s var(--ease-out); }
.film:hover .media.xe-img.in > img,
.film:focus-visible .media.xe-img.in > img { transform: scale(1.04); transition: transform 900ms var(--ease-out); }

/* ---------- 05 · services rig-board — same ::after trade as the doors, sheen unchanged ---------- */
.rig .card.xe-lit::after { background: none; transform: none; transition: none; }
.rig .card.xe-lit::before { content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none; border-radius: inherit;
  background: none;
  transform: none; transition: none; }
.rig .card.xe-lit:hover::before, .rig .card.xe-lit:focus-within::before { transform: none; }

/* ---------- 06 · reviews — glass cards; the lit card keeps the glow, not a second border ----------
   .xe-glass draws its edge in the 1px padding ring, so a second border-colour on the
   active card would print two hairlines. The glow alone says which card is centred. */
.rail .review.xe-glass.in { border-color: transparent; }

/* ---------- 07 · venues — the mid-page date form gets the hero's treatment ----------
   Same field, same action, same copy (the launch decision); only the finish is lifted:
   a sentence-case label instead of a mono chip, and the underline lights on focus. */
.datecheck-mid label { font-family: inherit; font-size: .92rem; letter-spacing: 0; text-transform: none; color: #CFCFCF; gap: 6px; }
.datecheck-mid .datefield .dateface { font-family: inherit; font-size: 1.15rem; font-weight: 500; letter-spacing: -0.01em;
  padding: 12px 0; min-height: 56px; transition: border-color var(--t-fast), color var(--t-fast); }
.datecheck-mid .datefield:hover .dateface { border-bottom-color: #fff; color: var(--text); }
.datecheck-mid .datefield:focus-within .dateface { border-bottom-color: #fff; box-shadow: 0 1px 0 0 #fff, 0 6px 22px rgba(255,255,255,.18); }
.datecheck-mid .datefield:active .dateface { background: var(--accent-soft); }
.datecheck-mid .datefield input[type="date"] { height: 56px; min-height: 56px; }
.datecheck-mid .btn-primary { min-height: 56px; padding: 0 24px; }
/* On a phone this button and the sticky mobile bar's pill are both on screen, both lit, both reading
   "Check my date" — two primary actions where DESIGN-SYSTEM.md allows one. The sticky bar is the
   persistent one, so it keeps the bloom; the in-flow button holds the bevel at rest and lights only
   when it is actually being used. Desktop, which has no mobile bar, is unchanged.
   Written as an at-rest-only rule (:not(:hover):not(:focus-visible):not(:active)) on purpose: site.css's
   own .btn-primary:hover carries the same specificity as a plain .datecheck-mid .btn-primary and index.css
   loads after it, so restating hover here would silently replace the brighter hover shadow with this
   dimmer one. Excluding the interactive states instead lets every one of them fall through untouched. */
@media (max-width: 899px) {
  .datecheck-mid .btn-primary:not(:hover):not(:focus-visible):not(:active) { box-shadow: var(--bevel); }
}

/* ---------- 09 · FAQ — the open panel lights up ----------
   The ring is mounted on every row and revealed only while the panel is open, so the
   closed list stays the plain hairline stack it was. */
.faq details.xe-lit::after { border-radius: var(--r-sm); opacity: 0; transition: opacity var(--t-base) var(--ease-out); }
.faq details[open].xe-lit::after { opacity: 1; }
.faq details[open].xe-lit { border-radius: var(--r-sm); background: linear-gradient(160deg, rgba(255,255,255,.05), transparent 62%); }

/* ---------- 10 · closing CTA — glass panel, console brackets ----------
   home.css owned .cta-final::before for the black scrim over the photograph. The scrim
   is now a real element (cta() in home.js) and ::before is handed to .xe-glass, whose
   gradient edge has to be restated here because the incumbent rule sits in home.css.
   See cssRequests: moving the scrim in home.css would let these four lines go. */
.cta-final .cta-scrim { position: absolute; inset: 0; z-index: -1; pointer-events: none; border-radius: inherit;
  background: linear-gradient(90deg, rgba(0,0,0,.94), rgba(0,0,0,.5)), radial-gradient(40% 60% at 82% 40%, rgba(255,255,255,.16), transparent 70%); }
.cta-final.xe-glass { border-color: transparent; }
.cta-final.xe-glass::before { z-index: 1;
  background: linear-gradient(160deg, rgba(255,255,255,.42), rgba(255,255,255,.08) 40%, rgba(255,255,255,.04) 62%, rgba(255,255,255,.3)); }
/* the panel clips its own overflow, so the brackets sit inside the padding instead of outside the edge */
.cta-final.xe-brackets::after { inset: clamp(12px, 1.6vw, 20px); }

/* ============================================================================
   EVOLVE PASS TWO — 2026-09-13. Punch-list repairs below the hero. Additions only:
   every rule here overrides a shared file from the page's own stylesheet rather
   than editing site.css / home.css, so no other page moves.
   ============================================================================ */

/* ---------- IDX-07 · proof — glow is light on objects, never a halo on words ----------
   site.css:305 puts an 18px white bloom on every .stat .k. Two of the four proof stats
   are words ("Since 1986", "Own gear, own crew") and wore it too — the only haloed type
   below the hero. The bloom is scoped to the two figures that actually count up. */
#proof-stats .stat .k { text-shadow: none; }
#proof-stats .stat .k[data-count] { text-shadow: 0 0 18px rgba(255,255,255,.25); }

/* ---------- MH-07 · the gear-strip label clears the contrast floor ----------
   --faint (#767676) on --ink-1 is 4.36:1 at 11.2px, under AA. #8A8A8A reads 5.6:1.
   Scoped to this one role: --faint itself is not touched. */
#brands .lbl { color: #8A8A8A; }

/* ---------- IDX-01 · films — the view badge stops punching through the play button ----------
   At 320–515px the poster is ~170×96 and the top-left badge sits across the centred play
   disc (measured overlap 52 × 16.6px at 390). Below 560 the badge drops to the poster
   floor and the disc comes down to 40px, which clears the pill with room to spare; from
   560 up nothing changes (1440 already cleared by 8.9px). */
@media (max-width: 560px) {
  .film .media .views { top: auto; bottom: 3px; left: 5px; right: auto; padding: 2px 7px; line-height: 1; }
  .film .media .play { width: 40px; height: 40px; }
  .film .media .play svg { width: 15px; height: 15px; }
}
/* the poster is 136–156px wide down here, so the disc comes down one more step to hold the
   clearance (nearest badge point to disc centre stays outside the radius at 320, 360 and 390). */
@media (max-width: 400px) {
  .film .media .play { width: 36px; height: 36px; }
  .film .media .play svg { width: 14px; height: 14px; }
}

/* ---------- IDX-08 / MH-03 · services rail keeps its gutter on load ----------
   `scroll-snap-type: x mandatory` snapped card 0 to the scrollport edge on first layout and
   ate the 18px padding, so the first card sat at x 0 under copy inset to 18. */
#services { scroll-padding-inline: var(--gutter); }

/* ---------- IDX-09 · event-type chips meet the 44px target bar ----------
   They are real links to work.html anchors and were the one 40px target on a phone-first page. */
#event-types .chip { min-height: 44px; }

/* ---------- IDX-13 / MH-08 · the night index rail carries its own ground ----------
   The rail is the only wayfinding in a 5,700px section and it sat over frames that go
   near-white at the top right, where neither the stage scrim nor the card scrim reaches.
   A local scrim plus a set (never tweened) text shadow, so the ticks read on every frame. */
@media (min-width: 900px) {
  #night-section .night-rail { padding: 14px 12px; border-radius: var(--r-md);
    background: linear-gradient(90deg, rgba(0,0,0,0), rgba(0,0,0,.55) 38%); }
  #night-section .night-ticks li { text-shadow: 0 1px 3px rgba(0,0,0,.7); }
  /* MH-14 · on desktop the .step-c panes are invisible scroll spacers, but opacity:0 leaves
     them in the accessibility tree, so the page exposed all six step headings twice.
     visibility:hidden keeps the layout box that provides the scroll length and drops the
     duplicate from the tree. The mobile path (max-width:899px) never sees this rule. */
  .night-scroll .night .step-c { visibility: hidden; }
}

/* ---------- IDX-14 · the mid-page date console reads as a console ----------
   It stretched the full 872px wrap under 512px of venue chips with nothing marking it as a
   separate object. Capped and set off by a hairline; the copy, the action and the 44px
   rhythm gap above it are untouched. */
#datecheck-mid { max-width: 520px; border-top: 0; padding-top: clamp(20px, 3vw, 28px); }

/* ---------- IDX-11 · FAQ — the head sits with the list, not above a 211px hole ----------
   auto-fit resolved to `518px 518px 0px` with align-items:start, leaving a third of the
   viewport empty beside the questions in the band right before the closing CTA. */
@media (min-width: 900px) {
  #faq-section .wrap.two-col { grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr); align-items: start; }
}
