/* ==========================================================================
   Прослави / Events — page-scoped styles.
   Loads AFTER styles.css and borrows every token from it: no new colours, no
   new fonts, no new spacing values. What is new here is the page's own spine —
   a full-bleed masthead of the room, a ledger that ends in a zero, and the
   film frames.
   Mobile-first without exception. Base rules are the phone.

   Anything that starts hidden is scoped to `body.gsap`, a class this page's
   script adds only once GSAP and ScrollTrigger have both actually loaded and
   motion is allowed. If either script 404s, or the visitor asks for reduced
   motion, the class is never added and the page is simply a static document.
   ========================================================================== */

/* ==========================================================================
   1. Masthead — the room, full bleed, held while it is scrolled past
   ========================================================================== */

.mast {
  position: relative;
  /* Track length. 100svh of this is the sticky hold, the rest is scrub
     distance for the slow push-in. Much shorter than the home page's hero:
     this is a photograph being looked at, not a sequence being played. */
  height: 155svh;
  background: var(--pitch);
}

/* Sticky, not GSAP-pinned. Same choice as the home hero — the browser owns
   the position, ScrollTrigger only reads progress, so there is no pin-spacer
   to fight with and nothing collapses if the script never runs. */
.mast__pin {
  position: sticky;
  inset-block-start: 0;
  height: 100svh;
  overflow: clip;
}

.mast__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 62%;
}

/* The headline sits over the brightest part of the photograph — a table of
   pastry and cake under warm light — so the shade under it has to be deep and
   has to start high. Off-white on that food is barely 3:1 unaided. */
.mast__veil {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to top,
    oklch(12.5% 0.008 67 / 0.95) 0%,
    oklch(12.5% 0.008 67 / 0.85) 24%,
    oklch(12.5% 0.008 67 / 0.5) 50%,
    oklch(12.5% 0.008 67 / 0.16) 76%,
    oklch(12.5% 0.008 67 / 0.42) 100%
  );
  pointer-events: none;
}

.mast__say {
  position: absolute;
  inset-block-end: calc(56px + var(--space-xl));
  inset-inline: 0;
  padding-inline: var(--gutter);
}

/* Entrance is pure CSS, never JS: it starts from the hidden state on the very
   first painted frame, so there is no flash of the finished layout and no way
   for a failed script to leave the headline invisible. */
.mast__say > * {
  opacity: 0;
  animation: mast-in 1s var(--ease) forwards;
}
.mast__say > :nth-child(1) { animation-delay: 0.15s; }
.mast__say > :nth-child(2) { animation-delay: 0.28s; }
.mast__say > :nth-child(3) { animation-delay: 0.44s; }

@keyframes mast-in {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: none; }
}

.mast__say h1 {
  margin-block: var(--space-sm);
  font-size: var(--step-5);
}
.mast__say .lead { max-width: 24ch; color: var(--ink); }

/* Hidden on the phone: the lead runs to two lines there and the cue lands on
   top of it, and a phone needs no invitation to scroll. It returns at 56rem,
   where it has a corner of its own. */
.mast__cue {
  display: none;
  position: absolute;
  inset-block-end: var(--space-lg);
  inset-inline-end: var(--gutter);
  font-size: var(--step--1);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* ==========================================================================
   2. Headings that arrive one line at a time
   Each line is a clipping box with the words inside it; the words slide up
   from under their own baseline. Written out in the markup rather than split
   by script, so the text is real text to a screen reader and to Google.
   ========================================================================== */

/* Cormorant's descenders hang far below the baseline, and the site's heading
   leading is 1.02 — tight enough that a clipping box drawn on the line box
   would shave the tail off every ј, р and у. Each row is given a little room
   below the baseline to clip against, and takes it straight back as negative
   margin so the heading's rhythm is unchanged. */
.lines { display: block; line-height: 1.08; }
.lines__row {
  display: block;
  overflow: clip;
  padding-block-end: 0.16em;
  margin-block-end: -0.12em;
}
.lines__in { display: block; }

body.gsap .lines__in { transform: translateY(130%); }

/* ==========================================================================
   3. The number sections — 150, and then 0
   ========================================================================== */

/* A numeral used as an image: Cormorant set enormous, cropped tight, with the
   label doing the explaining so the digit never has to. */
.tally {
  display: grid;
  gap: var(--space-sm);
  justify-items: start;
}

.tally__num {
  display: flex;
  align-items: baseline;
  gap: var(--space-sm);
  font-family: var(--display);
  font-weight: 600;
  line-height: 0.78;
  letter-spacing: -0.045em;
  font-variant-numeric: lining-nums tabular-nums;
}

.tally__digits { font-size: clamp(5.5rem, 26vw, 11rem); }
.tally__unit {
  font-family: var(--body);
  font-size: var(--step-1);
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--ink-3);
}

/* The zero is the one place on the page where the accent is allowed to be
   enormous. It is the whole argument, so it gets the whole colour budget. */
.tally--free .tally__digits { font-size: clamp(7rem, 38vw, 16rem); color: var(--accent); }
.tally--free .tally__unit { font-size: var(--step-2); color: var(--accent-dim); }

/* The rule under a numeral, drawn left to right as it comes into view. */
.sweep {
  display: block;
  width: 100%;
  height: 1px;
  background: var(--hairline);
  transform-origin: 0 50%;
}
body.gsap .sweep { transform: scaleX(0); }

.free__grid { display: grid; gap: var(--space-2xl); }

/* The two lines of the bill, set to the same rhythm as a row on the menu
   page — deliberately, so it reads as an extract from their own board. */
.bill { border-block-start: 1px solid var(--hairline-2); }

.bill__row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  column-gap: var(--space-lg);
  padding-block: var(--space-md);
  border-block-end: 1px solid var(--hairline-2);
}
.bill__what { font-family: var(--display); font-size: var(--step-1); font-weight: 600; line-height: 1.15; }
.bill__cost { justify-self: end; white-space: nowrap; font-size: var(--step-0); font-weight: 500; color: var(--ink); }
.bill__cost--free { color: var(--accent); }
.bill__note {
  grid-column: 1 / -1;
  margin-block-start: var(--space-2xs);
  font-size: var(--step--1);
  line-height: 1.5;
  color: var(--ink-3);
}

/* ==========================================================================
   4. Ruled lists — the catering ledger and the list of occasions
   ========================================================================== */

.ruled { list-style: none; padding: 0; border-block-start: 1px solid var(--hairline-2); }

.ruled li {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  column-gap: var(--space-lg);
  padding-block: var(--space-md);
  border-block-end: 1px solid var(--hairline-2);
}

.ruled__name {
  font-family: var(--display);
  font-size: var(--step-2);
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -0.01em;
}
.ruled__count {
  justify-self: end;
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.06em;
  color: var(--ink-3);
  white-space: nowrap;
}
.ruled__note {
  grid-column: 1 / -1;
  margin-block-start: var(--space-2xs);
  max-width: 56ch;
  font-size: var(--step--1);
  line-height: 1.5;
  color: var(--ink-3);
}

/* The occasions read as a list of headlines, so they lose the second column
   and get the display size to themselves. */
.ruled--big li { grid-template-columns: 1fr; }
.ruled--big .ruled__name { font-size: var(--step-3); }

body.gsap .ruled li { opacity: 0; transform: translateY(14px); }

/* ==========================================================================
   5. The films — click-to-play, nothing from YouTube until asked
   Until the button is pressed the page has loaded a local still and no
   third-party code at all. The iframe is built on click.
   ========================================================================== */

.films { display: grid; gap: var(--space-2xl); }

.film__frame {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: clip;
  background: var(--pitch);
  border: 1px solid var(--hairline-2);
}

/* The still is a sibling of the button, not a child of it: inside the button
   its alt text would be swallowed into the button's own name and the control
   would announce as a paragraph. Out here the photograph describes itself and
   the button says one thing — play. */
.film__btn {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}

/* The still holds no position of its own. Once the parallax is running its
   <picture> becomes the clipping frame (`.px` in styles.css) and the still is
   the thing that travels inside it, taller than the frame and free to move.
   Until then — no JS, reduced motion — the `:not(.px)` rule below fills the
   frame with it flat, as a plain 16/9 photograph in a 16/9 hole.

   Sizing the still directly here would be the obvious way to write that, and
   it would quietly break the parallax: `.film__img` and `.px__img` have the
   same weight, this stylesheet is loaded second, and the frame would win the
   height it needs to have overspill. Hence the `:not()`, which cannot clash
   with the rule it is standing in for. */
.film__frame picture { position: absolute; inset: 0; }
.film__frame picture:not(.px) > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.film__img { transition: opacity 0.4s var(--ease); }
.film__frame:hover .film__img { opacity: 0.82; }

.film__play {
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 50%;
  translate: -50% -50%;
  display: grid;
  place-items: center;
  width: 4.5rem;
  height: 4.5rem;
  border-radius: 50%;
  background: var(--accent);
  color: var(--pitch);
  box-shadow: var(--lift-2);
  transition: background-color 0.25s var(--ease), scale 0.25s var(--ease);
}
.film__frame:hover .film__play { background: oklch(75.8% 0.119 71); scale: 1.06; }
.film__btn:active .film__play { scale: 0.98; }
.film__play svg { width: 1.5rem; height: 1.5rem; translate: 2px 0; }

.film__frame iframe { width: 100%; height: 100%; border: 0; }

.film__cap {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2xs) var(--space-sm);
  margin-block-start: var(--space-sm);
}
.film__title { font-family: var(--display); font-size: var(--step-1); font-weight: 600; }
.film__by { font-size: var(--step--1); color: var(--ink-3); }

body.gsap .film { opacity: 0; transform: translateY(20px); }

/* ==========================================================================
   6. The three steps
   ========================================================================== */

.steps { display: grid; gap: var(--space-xl); counter-reset: none; }

.step {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: start;
  column-gap: var(--space-lg);
  padding-block-start: var(--space-lg);
  border-block-start: 1px solid var(--hairline-2);
}

.step__n {
  font-family: var(--display);
  font-size: var(--step-3);
  font-weight: 600;
  line-height: 0.9;
  color: var(--ink-3);
  font-variant-numeric: lining-nums tabular-nums;
}
.step__body h3 { margin-block-end: var(--space-xs); }
.step__body p { color: var(--ink-2); max-width: 46ch; }

body.gsap .step { opacity: 0; transform: translateY(16px); }

/* ==========================================================================
   7. Desktop — added, never subtracted
   ========================================================================== */

@media (min-width: 48rem) {
  .films { grid-template-columns: 1fr 1fr; gap: var(--space-2xl); }
  .steps { grid-template-columns: repeat(3, 1fr); gap: var(--space-xl); }
  .step { grid-template-columns: 1fr; row-gap: var(--space-sm); }
  .mast__img { object-position: 50% 55%; }
}

@media (min-width: 56rem) {
  .mast__say { inset-block-end: var(--space-3xl); }
  .mast__cue { display: block; }
  /* The zero and the sentence it belongs to, side by side, with the numeral
     given the smaller column so it sits against the text rather than under it. */
  .free__grid {
    grid-template-columns: auto 1fr;
    gap: var(--space-4xl);
    align-items: center;
  }
}

/* ==========================================================================
   8. Reduced motion — nothing is hidden, nothing moves
   The body.gsap class is never added in this case, so the rules above never
   apply; these are here as a second belt in case the class is already on the
   element when the preference changes mid-session.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .mast { height: 100svh; }
  .mast__say > * { opacity: 1; animation: none; }
  body.gsap .lines__in,
  body.gsap .ruled li,
  body.gsap .film,
  body.gsap .step { opacity: 1; transform: none; }
  body.gsap .sweep { transform: none; }
}

/* ==========================================================================
   9. Print
   ========================================================================== */

@media print {
  .mast, .films { display: none; }
  .tally__digits { color: #000; }
}
