/* Ben's Bar Mitzvah — one stylesheet for all five routes.
   Tokens, card markup and card typography are lifted from proofs/bm-proofs.html.
   Only the page frame (.page, .btn) is new; it takes its colours from the tokens. */

:root {
  --bg:        #FAFAF6;
  --surface:   #FFFFFF;
  --surface-2: #F2F2ED;
  --ink:       #14161F;
  --muted:     #565B70;
  --faint:     #868BA0;
  --line:      #E1E0D9;
  --line-2:    #CCCBC2;
  --accent:    #1B4A8F;
  --accent-2:  #E4EBF6;
  --on-accent: #FFFFFF;
  --shadow:    0 1px 2px rgba(20,22,31,.05), 0 10px 30px -18px rgba(20,22,31,.3);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0E1019; --surface: #171A26; --surface-2: #1F2331;
    --ink: #ECEDF3; --muted: #9CA1B4; --faint: #757A90;
    --line: #282C3C; --line-2: #383D52; --accent: #8CA8E6; --accent-2: #1E2740;
    --on-accent: #0E1019;
    --shadow: 0 1px 2px rgba(0,0,0,.3), 0 10px 30px -18px rgba(0,0,0,.8);
  }
}
:root[data-theme="dark"] {
  --bg: #0E1019; --surface: #171A26; --surface-2: #1F2331;
  --ink: #ECEDF3; --muted: #9CA1B4; --faint: #757A90;
  --line: #282C3C; --line-2: #383D52; --accent: #8CA8E6; --accent-2: #1E2740;
  --on-accent: #0E1019;
  --shadow: 0 1px 2px rgba(0,0,0,.3), 0 10px 30px -18px rgba(0,0,0,.8);
}

/* ---------- the fixed palette — none of this themes ----------
   The invitation is printed matter. The frame around it matches the email, which
   is one pale blue for every recipient: a navy card floating on a near-black
   ground would no longer match the mail that brought the guest here. So the
   ground and the card's shadow are pinned in both schemes. (The button needs no
   pinning: it is on the card, so it reads the card's palette, which never themed.)
   The tokens above still swap; nothing the guest can see reads them any more. */
:root {
  color-scheme: light;
  --page-ground:  #C6D4EE;
  --card-shadow:  0 1px 2px rgba(20,22,31,.05), 0 10px 30px -18px rgba(20,22,31,.3);
}
.card3d {
  --p-ground: #12377A;
  --p-ink:    #FFFFFF;
  --p-soft:   #C6D4EE;
  --p-rule:   #4569AC;
  --p-blue:   #AFC5EA;
  --p-faint:  #93ACDA;
}

* { box-sizing: border-box; }

body {
  margin: 0; background: var(--page-ground); color: var(--ink);
  font-family: "Source Sans 3", ui-sans-serif, system-ui, -apple-system, sans-serif;
  font-size: 16.5px; line-height: 1.6; -webkit-font-smoothing: antialiased;
}

/* ---------- page frame: one visible block, floating on the pale blue ----------
   The block-axis padding is the MINIMUM band of ground above and below; when the
   viewport is taller than the card, .block's auto margins open it up further. */
.page {
  min-height: 100dvh;
  display: flex; flex-direction: column; align-items: center;
  padding: 20px 1.25rem;
}
@media (min-width: 40rem) {
  .page { padding: 40px 1.5rem; }
}

/* Exactly one .block is visible at a time. margin-block: auto centres it and
   collapses to zero when the card is taller than the viewport, so a long card
   scrolls instead of having its top cut off. */
.block {
  flex: none; margin-block: auto;
  display: flex; flex-direction: column; align-items: center; width: 100%;
}
[hidden] { display: none !important; }

/* the generic block is the one thing not lifted from the proofs */
[data-block="generic"] .lede { margin-top: .85rem; }

/* ---------- the card ---------- */
.stage { perspective: 1600px; width: 100%; max-width: 23rem; }
@media (min-width: 40rem) { .stage { max-width: 600px; } }   /* the email's card width */
.card3d {
  display: grid; position: relative;
  transform-style: preserve-3d;
  border-radius: 14px;
}
.card3d.static { cursor: default; transform: none !important; }

.face {
  grid-area: 1 / 1;
  backface-visibility: hidden; -webkit-backface-visibility: hidden;
  background: var(--p-ground); color: var(--p-ink);
  border: 1px solid #0C2B63; border-radius: 14px;
  box-shadow: var(--card-shadow);
  padding: 2.1rem 1.5rem 30px;   /* 30px is the gap under the button every card carries */
  display: flex; flex-direction: column; align-items: center; text-align: center;
}

@media (prefers-reduced-motion: reduce) {
  .card3d { transition: none; transform: none !important; }
  .face { backface-visibility: visible; -webkit-backface-visibility: visible; }
}

/* ---------- front typography ---------- */
.plate { line-height: 0; margin-bottom: .85rem; }
.plate img { width: 88px; height: auto; display: block; }   /* 80px x 1.1; source is 300px wide */
.lede { font-size: .86rem; color: var(--p-soft); line-height: 1.5; margin: 0; max-width: 41ch; }
.nm {
  font-family: Fraunces, Georgia, serif; font-size: clamp(1.9rem, 5vw, 2.4rem);
  font-weight: 600; letter-spacing: -.02em; line-height: 1.05; margin: .5rem 0 0; color: var(--p-ink);
}
.nm-he {
  font-family: "Frank Ruhl Libre", "Times New Roman", serif;
  font-size: 1.42rem; font-weight: 500; line-height: 1.35;
  color: var(--p-blue); direction: rtl; margin: .3rem 0 0;
}
.rule { width: 3rem; height: 2px; background: var(--p-rule); margin: 1rem 0; flex: none; }
.pair { display: flex; flex-direction: column; gap: .1rem; }
.pair + .pair { margin-top: .6rem; }
.p-he {
  font-family: "Frank Ruhl Libre", "Times New Roman", serif;
  font-size: 1.22rem; font-weight: 400; line-height: 1.4;
  color: var(--p-blue); direction: rtl; margin-top: .12rem;
}
.d-en { font-family: "IBM Plex Mono", monospace; font-size: .82rem; letter-spacing: .05em; color: var(--p-ink); }
.place { font-size: .89rem; color: var(--p-soft); line-height: 1.45; margin: .8rem 0 0; }

/* dayguest and friends read programme-then-venue; family, family-nobrunch and intown
   read venue-then-programme. The divider belongs BETWEEN the two, so it travels with the
   pair instead of staying on .prog and stranding itself under the date line. The spacing
   swaps with them: whichever block comes first takes .place's .8rem lead-in, whichever
   comes second takes .prog's rule and the .85rem of air beneath it. */
[data-block="dayguest"] .prog,
[data-block="friends"] .prog { margin-top: .8rem; padding-top: 0; border-top: 0; }
[data-block="dayguest"] .place,
[data-block="friends"] .place {
  margin-top: .9rem; padding-top: .85rem;
  border-top: 1px solid var(--p-rule);
}
.prog {
  display: flex; flex-direction: column; gap: .5rem;
  margin: .9rem 0 0; padding-top: .85rem;
  border-top: 1px solid var(--p-rule); max-width: 33ch;
}
.prog p { margin: 0; font-size: .87rem; line-height: 1.45; color: var(--p-soft); }
.prog .t { color: var(--p-blue); font-weight: 600; white-space: nowrap; }

/* Time-led tiers — family and family-nobrunch: the programme as a two-column grid,
   event then time. The grid sizes to its own content and is centred as a unit, so
   the card keeps one centre line even though the columns inside it are aligned
   left and right.

   .prog's 33ch cap was tuned for the centred prose programme the remaining tiers
   still use. It is 43px narrower than this grid wants, which wrapped the Shacharit
   row on desktop where the card has 550px to spare, so it is lifted on the time-led
   tiers only. The card still bounds the grid on mobile. */
[data-block="family"] .prog,
[data-block="family-nobrunch"] .prog { max-width: none; }
.pgrid {
  display: grid; grid-template-columns: minmax(0, max-content) max-content;
  column-gap: 18px; row-gap: 11px; text-align: left;
  width: fit-content; max-width: 100%; margin-inline: auto;
}
.ev { font-family: Georgia, serif; font-size: .87rem; line-height: 1.5; color: var(--p-ink); }
.tm {
  font-family: "IBM Plex Mono", ui-monospace, monospace; font-size: .78rem;
  letter-spacing: .04em; color: var(--p-blue); text-align: right;
  padding-top: .2em; white-space: nowrap;
}
.from { font-family: Fraunces, Georgia, serif; font-size: 1.12rem; margin: 1.1rem 0 0; color: var(--p-ink); }
/* flex children don't collapse margins — zero the follower so the rule sits symmetrically */
.rule + .from { margin-top: 0; }
.rsvp {
  font-family: "IBM Plex Mono", monospace; font-size: .68rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--p-faint); margin: .8rem 0 0;
}

/* ---------- RSVP status ----------
   Added by JS, and only when the endpoint confirms this household has already
   replied. It is never in the markup, never on first paint, and never appears at
   all if the fetch fails — so nothing below it may depend on it being there.

   It sits between the respond-by line and the button, in --p-soft, the card's
   colour for secondary prose. Sized between the respond-by line above it and the
   card's prose: .rsvp's .68rem is tracked uppercase mono set in three words, and
   two sentences do not read at that size. Capped at .prog's 33ch so the measure
   holds on the 600px card. The button keeps its own 26px above it. */
.status {
  font-size: .75rem; line-height: 1.5; color: var(--p-soft);
  margin: .8rem 0 0; max-width: 33ch;
}

/* ---------- iOS data detectors ----------
   Safari on iOS auto-links dates, times and addresses at render time, injecting an
   <a x-apple-data-detectors> around them and painting it blue and underlined. The
   anchor is not in our markup, so CSS is the only lever. The format-detection meta
   in the head is not enough on its own — only telephone=no is reliably honoured —
   so this rule is what actually holds the type.

   inherit is deliberate rather than a fixed colour: the bait sits in .d-en (white,
   --p-ink) and in .tm (--p-blue), so each injected anchor must take its own parent's
   colour. Only reproducible on a real iPhone; this cannot be seen on desktop. */
a[x-apple-data-detectors],
a[x-apple-data-detectors] * {
  color: inherit !important;
  text-decoration: none !important;
  font-size: inherit !important;
  font-family: inherit !important;
  font-weight: inherit !important;
  letter-spacing: inherit !important;
  line-height: inherit !important;
  pointer-events: none !important;
}

/* The flattening clause above is what stops Safari colouring nested spans blue, but it
   also strips .t's own emphasis when Safari wraps a whole programme line rather than
   just the time inside it. This puts it back. Cheap insurance against a failure nobody
   can reproduce without an iPhone. */
a[x-apple-data-detectors] .t {
  color: var(--p-blue) !important;
  font-weight: 600 !important;
}

/* ---------- the button ----------
   Geometry from the proofs' .btn. Every button on this page now sits inside the card,
   as it does in the email — one floating on the ground below read as page furniture —
   so it takes the card's own palette rather than the theme tokens. White on navy is
   the strongest signal available there. 26px above it, 30px from .face to the edge. */
.btn {
  display: inline-block; background: var(--p-ink); color: var(--p-ground);
  font-family: "Source Sans 3", ui-sans-serif, system-ui, -apple-system, sans-serif;
  font-size: .86rem; font-weight: 700; letter-spacing: .04em; text-decoration: none;
  padding: .85rem 1.6rem; border-radius: 4px; border: 1px solid var(--p-ink);
  margin-top: 26px;
  text-align: center; cursor: pointer;
  transition: background-color .15s, color .15s;
}
.btn:hover { background: var(--p-soft); border-color: var(--p-soft); }
.btn:focus-visible { outline: 2px solid var(--p-ink); outline-offset: 3px; }
.btn[aria-disabled="true"] { pointer-events: none; opacity: .55; }

/* RSVP only. The arrow means "continue", and RSVP leads onward to the Tally form whose
   submit button it echoes; "Get in touch" opens a mail client, which is another kind of
   action, so it stays a plain label. Decoration: aria-hidden, and never the only sign
   that this is a button. */
.btn .arw { margin-left: .5em; }
