/* ============================================================
   The invitation: one page, scrolled.

   There is one thing to open — the sealed sheet — and after it the
   hero is simply the first screen of the page. Nothing else is
   tapped, nothing advances, and the page scrolls from the hero
   straight on into the invitation.

     1. Ground
     2. The veil
     3. Screen
     4. The hero
     5. The names on it
     6. Entrance
     7. Reduced motion
   ============================================================ */

/* ---------- 1. Ground ------------------------------------- */
/* Pure black everywhere, so nothing can flash white around the
   artwork — the artwork's own ground is #000, so the seam between
   picture and page is invisible at every viewport size. */
:root {
  --ink:   #000000;
  --ivory: #F4F1EC;

  --serif: 'Bodoni Display', 'Old Standard Cyrillic', 'Didot', 'Times New Roman', serif;
  --ease:  cubic-bezier(.32, .08, .24, 1);
}

*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--ink);
  color: var(--ivory);
  overscroll-behavior: none;     /* no rubber-band revealing the page ground */
  -webkit-text-size-adjust: 100%;
  /* Full-bleed artwork is scaled slightly as it arrives. `clip` keeps that
     off the horizontal axis without making a scroll container of the page. */
  overflow-x: clip;
}

/* The page is held still only while there is a sheet in front of it. */
html[data-intro], html[data-intro] body { height: 100%; overflow: hidden; }

.sr {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }

/* ---------- 2. The veil ----------------------------------- */
/* One element on one axis. It closes over the sheet, the sheet is
   taken out of the document behind it, and then it draws up off the
   hero — so the two are never both on screen and nothing is ever
   caught half-drawn. The leading edge is soft, so it reads as a veil
   rather than as a shutter. */
.veil {
  position: fixed;
  inset: 0;
  z-index: 120;
  pointer-events: none;
  transform: translateY(100%);
  background: linear-gradient(to bottom,
    var(--ink) 0%, var(--ink) 88%, rgba(0,0,0,.55) 96%, rgba(0,0,0,0) 100%);
  visibility: hidden;
}
.veil[data-on] { visibility: visible; }

/* ---------- 3. Screen ------------------------------------- */
.deck { position: relative; width: 100%; }

.screen {
  position: relative;
  width: 100%;
  min-height: 100vh;             /* fallback for engines without svh */
  min-height: 100svh;
  background: var(--ink);
}

/* ---------- 4. The hero ----------------------------------- */
/* Held at the top while the invitation scrolls up over it, so the
   ivory rises over the black rather than arriving under it. */
.screen--cover {
  position: sticky;
  top: 0;
  z-index: 0;
  overflow: hidden;
  overflow: clip;
  display: grid;
  align-content: end;
  padding: 0 var(--pad) max(calc(var(--pad) * 1.1), env(safe-area-inset-bottom, 0px));
}
/* Everything after it rides over the hero. */
.screen--cover ~ .screen { position: relative; z-index: 1; }

.screen__art {
  position: absolute;
  inset: 0;
  overflow: hidden;
  overflow: clip;
  transform-origin: 50% 50%;
}
/* The artwork is 853 x 1844 and the window rarely is. On anything
   near a phone's shape it covers, edge to edge. On a tablet or a
   desktop it is sized so the monogram — which sits between 32% and
   65% of its height — always has room, and the lilies run off the
   top and bottom of the window instead of the composition shrinking
   into a column in the middle of the screen. */
.screen__art img {
  /* Placed rather than laid out: a grid or a flex box start-aligns an
     item taller than its track, which would put the lilies at the top
     of the window and cut the monogram off the bottom. */
  position: absolute;
  left: 50%;
  top: 50%;
  display: block;
  /* A little larger than it strictly needs to be, so the drift it
     carries can never pull an edge into the window. */
  width: calc(max(100%, calc(100svh * 0.4632)) + 18px);
  height: auto;
  max-width: none;
  object-fit: cover;
  border: 0;
  transform: translate(-50%, -50%) translateY(var(--drift, 0px));
}
@media (min-aspect-ratio: 4/5) {
  .screen__art img { width: min(94vw, 110svh); }
}

/* Just enough weight at the foot to carry the names, and no more. */
.screen--cover::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 46%;
  pointer-events: none;
  background: linear-gradient(to top,
    rgba(0,0,0,.94) 0%, rgba(0,0,0,.66) 28%, rgba(0,0,0,0) 100%);
}

/* ---------- 5. The names on it ---------------------------- */
/* Bottom left, where the artwork is empty: the monogram runs from the
   M at the upper left to the A at the lower right, so the foot of the
   left-hand side is the one place on it nothing is already drawn. */
.hero__type {
  position: relative;
  z-index: 1;
  justify-self: start;
  text-align: left;
  max-width: 34rem;
}

.hero__names {
  font-family: var(--display, var(--serif));
  /* Refined, not fragile: the names are information, so they are set
     at a weight that holds over a photograph. */
  font-weight: 500;
  font-variation-settings: 'opsz' 40;
  font-size: clamp(1.35rem, 5.6vw, 2.4rem);
  line-height: 1.25;
  letter-spacing: .05em;
  margin: 0;
  color: var(--ivory);
}
.hero__amp {
  font-style: italic;
  font-weight: 400;
  opacity: .74;
  padding: 0 .5em;
}

/* ---------- 5b. The day, wherever it is written ----------- */
/* The date is set three times across the invitation — under the names
   on the hero, under them again on the invitation itself, and closing
   the countdown — and it is the same mark each time: the display
   serif's lining figures, widely tracked, at one size. It is not a
   caption in the companion face; it is the day, and it is written the
   way the monogram is drawn. */
:root { --t-date: clamp(.85rem, 3.6vw, 1.05rem); }

.hero__date,
.invite__date,
.count__date {
  font-family: var(--display, var(--serif));
  font-weight: 500;
  font-variation-settings: 'opsz' 40;
  font-size: var(--t-date);
  line-height: 1.2;
  letter-spacing: .38em;
  text-indent: .38em;
  font-variant-numeric: lining-nums tabular-nums;
  white-space: nowrap;
}

.hero__date {
  color: rgba(244, 241, 236, .68);
  margin: clamp(1rem, 3vw, 1.5rem) 0 0;
}

@media (min-aspect-ratio: 4/5) {
  .hero__names { font-size: clamp(1.6rem, 2.7vw, 2.8rem); }
  .hero__type  { max-width: 46rem; }
  .screen--cover { padding-bottom: max(clamp(2.5rem, 7svh, 5rem), env(safe-area-inset-bottom, 0px)); }
}

/* ---------- 6. Entrance ----------------------------------- */
/* The hero is behind the veil while it arrives, so what it does here
   is not a performance — it is simply already settling as the black
   draws off it. The artwork first, the names after, the date last. */
.screen__art {
  opacity: 0;
  transform: scale(1.045);
}
html[data-opened] .screen__art {
  opacity: 1;
  transform: scale(1);
  transition:
    opacity 1400ms var(--ease) 60ms,
    transform 2800ms cubic-bezier(.22,.61,.24,1) 60ms;
}

.hero__type > * {
  opacity: 0;
  transform: translateY(14px);
}
html[data-opened] .hero__type > * {
  opacity: 1;
  transform: none;
  transition:
    opacity 1100ms var(--ease) calc(620ms + var(--i, 0) * 260ms),
    transform 1100ms var(--ease) calc(620ms + var(--i, 0) * 260ms);
}
html[data-opened] .hero__date { opacity: .68; }

/* ---------- 7. Reduced motion ----------------------------- */
@media (prefers-reduced-motion: reduce) {
  .screen__art,
  html[data-opened] .screen__art,
  .hero__type > *,
  html[data-opened] .hero__type > * {
    transition-duration: 1ms !important;
    transition-delay: 0ms !important;
    transform: none !important;
  }
  html[data-opened] .screen__art,
  html[data-opened] .hero__type > * { opacity: 1; }
  html[data-opened] .hero__date { opacity: .68; }
  /* The artwork is centred by its own transform, so it is the drift
     that is taken off it here, not the transform. */
  .screen__art img { --drift: 0px !important; }
}
