/* =========================================================================
   matt.crew907.com — birthday page
   Mobile-first. Three themes selectable via <html data-theme>.
   ========================================================================= */

/* ---------- themes ---------- */
/* MONO — no accent colour at all. The photos are already loud (magenta,
   gold, sunset); the interface stays out of their way. Gallery-clean. */
:root,
[data-theme="mono"] {
  --bg:        #0a0a0b;
  --bg-2:      #131315;
  --surface:   #1c1c1f;
  --text:      #f4f4f5;
  --muted:     #8e8e95;
  --acc:       #ffffff;
  --acc-2:     #c9c9d0;
  --on-acc:    #0a0a0b;
  --frame:     #ffffff;
  --glow:      rgba(255, 255, 255, .22);
  --field:     #26262b;
  --field-br:  #45454f;
  --card:      #3f3f46;
  --card-ink:  #fafafa;
}

/* ICE — cold blue-black with an electric blue edge. Sharp and modern;
   picks up the stage lighting in the concert shots. */
[data-theme="ice"] {
  --bg:        #080d14;
  --bg-2:      #0e1622;
  --surface:   #16202f;
  --text:      #eaf2fb;
  --muted:     #7d94af;
  --acc:       #4db8ff;
  --acc-2:     #8fd6ff;
  --on-acc:    #04121f;
  --frame:     #f2f7fc;
  --glow:      rgba(77, 184, 255, .28);
  --field:     #1d2b3e;
  --field-br:  #3a5471;
  --card:      #4db8ff;
  --card-ink:  #04121f;
}

/* COURT — charcoal and a deep varsity red. The most straightforwardly
   athletic of the set. */
[data-theme="court"] {
  --bg:        #0c0c0d;
  --bg-2:      #161617;
  --surface:   #1f1f21;
  --text:      #f5f3f2;
  --muted:     #97918f;
  --acc:       #e03131;
  --acc-2:     #ff6b6b;
  --on-acc:    #ffffff;
  --frame:     #faf8f7;
  --glow:      rgba(224, 49, 49, .30);
  --field:     #29292c;
  --field-br:  #4d4a4c;
  --card:      #e03131;
  --card-ink:  #ffffff;
}

/* MIDNIGHT — deep indigo with a violet edge, pulled straight out of the
   Above and Beyond closer. */
[data-theme="midnight"] {
  --bg:        #0b0a14;
  --bg-2:      #14121f;
  --surface:   #1e1b2e;
  --text:      #f0edf8;
  --muted:     #8f88ad;
  --acc:       #a78bfa;
  --acc-2:     #f0abfc;
  --on-acc:    #120e21;
  --frame:     #f6f3fb;
  --glow:      rgba(167, 139, 250, .30);
  --field:     #272242;
  --field-br:  #4a4173;
  --card:      #a78bfa;
  --card-ink:  #17102e;
}

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

/* The UA rule for [hidden] is `display:none` with almost no specificity, so
   any class rule that sets `display` silently defeats it — which left the
   signed-out gate still occupying a full screen after login (blank screen),
   the theme switcher always visible, and stray buttons showing through.
   This makes the hidden attribute actually mean hidden. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 400 16px/1.55 -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui,
        "Segoe UI", Roboto, sans-serif;
  /* `clip`, not `hidden`: overflow-x:hidden turns body into a scroll
     container and silently kills position:sticky, which the chapters need. */
  overflow-x: clip;
}

body.locked { overflow: hidden; }

h1, h2 {
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", system-ui,
               "Segoe UI", Roboto, sans-serif;
  font-weight: 800;
  letter-spacing: -.035em;
  line-height: 1.02;
  margin: 0;
}

.acc { color: var(--acc); }

.eyebrow, .kicker {
  margin: 0;
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--muted);
}

/* =========================================================================
   GATE
   ========================================================================= */
.gate {
  /* --vvh tracks the VISUAL viewport, so when the iOS keyboard opens the
     centring box shrinks to the space above it instead of staying 100dvh
     and pushing the fields underneath the keys. */
  min-height: var(--vvh, 100dvh);
  display: grid;
  place-items: center;
  padding: 2.5rem 1.5rem calc(2.5rem + env(safe-area-inset-bottom));
  background:
    radial-gradient(120% 80% at 50% 0%, var(--bg-2) 0%, var(--bg) 62%);
  text-align: center;
}
.gate.leaving { animation: fadeOut .55s ease forwards; }

.gate-inner { width: 100%; max-width: 26rem; }

.gate-title {
  margin: 1.1rem 0 0;
  font-size: clamp(2.6rem, 15vw, 4rem);
}
.gate-sub {
  margin: 1.1rem auto 2.2rem;
  max-width: 20rem;
  color: var(--muted);
  font-size: .95rem;
}

/* date entry */
.fields {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
}
.fld {
  appearance: none;
  -webkit-appearance: none;
  background: var(--field);
  border: 2px solid var(--field-br);
  border-radius: .85rem;
  color: var(--text);
  font: 700 1.65rem/1 -apple-system, system-ui, sans-serif;
  letter-spacing: .05em;
  text-align: center;
  padding: .9rem .25rem;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .06);
  transition: border-color .18s ease, box-shadow .18s ease, background .18s ease;
}
.fld::placeholder { color: var(--muted); opacity: .85; font-weight: 700; }
.fld:focus {
  outline: none;
  background: color-mix(in srgb, var(--field) 70%, #fff 8%);
  border-color: var(--acc);
  box-shadow: 0 0 0 4px var(--glow);
}
.fld-2 { width: 4.4rem; }
.fld-4 { width: 6.6rem; }
.sep { color: var(--muted); font-weight: 700; opacity: .7; }

/* tiny labels so it reads unmistakably as "type your birthday here" */
.field-labels {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  margin-bottom: .45rem;
  font-size: .62rem;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--muted);
}
.field-labels span { text-align: center; }
.field-labels .l-2 { width: 4.4rem; }
.field-labels .l-4 { width: 6.6rem; }
.field-labels .l-sep { width: .5rem; opacity: 0; }

.fields.shake { animation: shake .42s cubic-bezier(.36,.07,.19,.97); }

.btn {
  appearance: none;
  -webkit-appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  margin-top: 1.5rem;
  padding: .95rem 2rem;
  min-height: 3rem;
  border: 0;
  border-radius: 2rem;
  background: var(--acc);
  color: var(--on-acc);
  font: 700 1rem/1 -apple-system, system-ui, sans-serif;
  letter-spacing: -.01em;
  cursor: pointer;
  transition: transform .16s ease, filter .16s ease;
}
.btn:active { transform: scale(.97); }
.btn:hover { filter: brightness(1.06); }
.btn-after { margin-top: 2rem; }
.btn-claim {
  margin-top: 1.6rem;
  margin-bottom: 1.4rem;
  padding-inline: 2.6rem;
  text-decoration: none;
  font-size: 1.05rem;
}
.btn-ghost {
  background: transparent;
  color: var(--text);
  border: 1.5px solid color-mix(in srgb, var(--muted) 45%, transparent);
}

.link-btn {
  display: block;
  margin: 1.6rem auto 0;
  padding: .6rem;
  background: none;
  border: 0;
  color: var(--muted);
  font: 500 .9rem/1.4 inherit;
  text-decoration: underline;
  text-underline-offset: .25em;
  cursor: pointer;
}
.link-btn:active { color: var(--text); }

.err {
  margin: 1rem 0 0;
  min-height: 1.2rem;
  color: var(--acc-2);
  font-size: .88rem;
  font-weight: 600;
}

/* =========================================================================
   SHOW / INTRO
   ========================================================================= */
.show { display: block; }
.show.entering { animation: fadeIn .8s ease both; }

.intro {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 2.5rem 1.5rem;
  text-align: center;
  background: radial-gradient(120% 80% at 50% 30%, var(--bg-2) 0%, var(--bg) 65%);
}
.intro-title { font-size: clamp(2.8rem, 16vw, 4.5rem); }

.chip {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  margin-top: 2.6rem;
  padding: .6rem 1.15rem;
  border-radius: 2rem;
  background: color-mix(in srgb, var(--surface) 85%, transparent);
  border: 1px solid color-mix(in srgb, var(--muted) 28%, transparent);
  color: var(--muted);
  font-size: .82rem;
  font-weight: 600;
  letter-spacing: .04em;
  animation: bob 2.4s ease-in-out infinite;
}
.chip.hide { opacity: 0; transition: opacity .4s ease; }

.chip-arrow {
  width: .55rem; height: .55rem;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translate(-1px, -1px);
}

/* =========================================================================
   CHAPTERS (scroll-driven)
   ========================================================================= */
.chapter { position: relative; }

.stage {
  position: sticky;
  top: 0;
  height: 100dvh;
  overflow: hidden;
}

/* A text band across the top, the picture filling everything under it. The
   line lives in that band, so it is legible without a heavy scrim and the
   photograph is never buried. */
.stage-in {
  position: relative;
  width: 100%;
  height: 100%;
  display: grid;
  grid-template-rows: 24vh 1fr;
  align-items: center;
  padding: 0 10px calc(3vh + env(safe-area-inset-bottom));
}

/* photo cluster */
.photos {
  grid-row: 2;
  width: 100%;
  max-width: 40rem;
  margin-inline: auto;
  display: grid;
  gap: 6px;                          /* the white seam between photos */
  background: var(--frame);
  padding: 6px;
  border-radius: 8px;
  overflow: hidden;
  will-change: transform;
}
.photos.l-1 { grid-template-columns: 1fr; }
.photos.l-2 { grid-template-columns: 1fr 1fr; }
.photos.l-3 { grid-template-columns: 1fr 1fr 1fr; }
.photos.l-4 { grid-template-columns: 1fr 1fr; }

.ph {
  position: relative;
  margin: 0;
  overflow: hidden;
  background: var(--bg);
  aspect-ratio: 3 / 4;
}
.ph img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 42%;
  display: block;
}

/* a single photo keeps its own shape, at its own resolution — no upscaling */
.photos.l-1 .ph { aspect-ratio: auto; }
.photos.l-1 img {
  width: 100%;
  height: auto;
  max-height: 68dvh;
  object-fit: contain;
}

/* ---- the staggered three ----------------------------------------------
   Three overlapping prints, tilted, rather than three vertical slices.  */
.photos.stagger {
  position: relative;
  display: block;
  background: none;
  padding: 0;
  border-radius: 0;
  overflow: visible;
  aspect-ratio: 1 / 1.02;
  max-width: 26rem;
}
.photos.stagger .ph {
  position: absolute;
  width: 47%;
  aspect-ratio: 3 / 4;
  border: 5px solid var(--frame);
  border-radius: 3px;
  box-shadow: 0 12px 30px rgba(0, 0, 0, .55);
}
.photos.stagger .ph:nth-child(1) { left: 0;   top: 3%;  transform: rotate(-6deg); z-index: 1; }
.photos.stagger .ph:nth-child(2) { left: 26%; top: 26%; transform: rotate(2deg);  z-index: 3; }
.photos.stagger .ph:nth-child(3) { left: 52%; top: 1%;  transform: rotate(7deg);  z-index: 2; }

/* the line of text, in the band above the picture */
.line {
  position: absolute;
  z-index: 3;
  top: 0;
  left: 0;
  right: 0;
  height: 24vh;
  margin: 0;
  padding: 0 1.3rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", system-ui, sans-serif;
  font-size: clamp(1.7rem, 8vw, 2.5rem);
  font-weight: 800;
  letter-spacing: -.03em;
  line-height: 1.1;
  text-align: center;
  text-wrap: balance;
  color: var(--text);
  text-shadow: 0 2px 20px var(--bg);
  will-change: transform, opacity;
}

/* the gift block and the signature ride in the same slot as a line */
.rises {
  position: absolute;
  z-index: 3;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 0 1.3rem;
  will-change: transform, opacity;
}

/* the scroll cue, on the first screen only */
.chip-in {
  position: absolute;
  z-index: 4;
  left: 50%;
  translate: -50% 0;                 /* not `transform` — bob animates that */
  bottom: calc(3.5vh + env(safe-area-inset-bottom));
  margin-top: 0;
}

/* placeholder tile until the real photos land */
.ph.is-placeholder::after {
  content: attr(data-label);
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: .5rem;
  text-align: center;
  color: var(--muted);
  font-size: .7rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  background: repeating-linear-gradient(
      45deg, var(--surface), var(--surface) 10px,
      var(--bg-2) 10px, var(--bg-2) 20px);
}

/* the line of text that rises and holds */
.line {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", system-ui, sans-serif;
  font-size: clamp(1.7rem, 8vw, 2.6rem);
  font-weight: 800;
  letter-spacing: -.03em;
  line-height: 1.08;
  text-align: center;
  text-wrap: balance;
  will-change: transform, opacity;
  text-shadow: 0 2px 30px var(--bg);
}

/* =========================================================================
   FINALE
   ========================================================================= */
.finale { position: relative; }

.pane {
  min-height: var(--vvh, 100dvh);
  display: grid;
  place-items: center;
  padding: 3rem 1.5rem calc(3rem + env(safe-area-inset-bottom));
  text-align: center;
  background: radial-gradient(120% 80% at 50% 35%, var(--bg-2) 0%, var(--bg) 68%);
}

/* =========================================================================
   keyboard open (iOS Safari)
   The visible area can drop to ~350px. Shed everything decorative so the
   fields and the submit button are always reachable without scrolling.
   ========================================================================= */
body.kb .gate,
body.kb .pane {
  padding-top: 1rem;
  padding-bottom: 1rem;
  align-content: start;
}
body.kb .eyebrow,
body.kb .kicker,
body.kb .gate-sub { display: none; }

body.kb .gate-title,
body.kb .pane-title {
  font-size: clamp(1.5rem, 7vw, 1.9rem);
  margin-top: .25rem;
  margin-bottom: 1rem;
}
body.kb .btn { margin-top: 1rem; }
body.kb .link-btn { margin-top: .9rem; }
body.kb .field-labels { margin-bottom: .35rem; }
.pane-inner { width: 100%; max-width: 27rem; }
.pane.fade-in .pane-inner { animation: riseIn .7s cubic-bezier(.2,.7,.3,1) both; }

.pane-title {
  margin: .9rem 0 2rem;
  font-size: clamp(2.1rem, 11vw, 3rem);
}

.beat {
  margin: 0 0 2.4rem;
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", system-ui, sans-serif;
  font-size: clamp(1.8rem, 9vw, 2.6rem);
  font-weight: 800;
  letter-spacing: -.03em;
  line-height: 1.1;
  text-wrap: balance;
}
.beat.swap { animation: riseIn .6s cubic-bezier(.2,.7,.3,1) both; }

/* the heartfelt run after the gift — slower, softer, less shouty */
.warm .beat {
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: 1.22;
  font-size: clamp(1.6rem, 7.5vw, 2.2rem);
}
.warm .beat.swap { animation: riseIn 1.15s cubic-bezier(.16,.8,.28,1) both; }

/* ---------- the closing picture ---------- */
.pane.answered { display: none; }

/* the gift block, when it rises inside a scroll section */
.gift-block { display: flex; flex-direction: column; align-items: center; }
.gift-block .gift-stage { min-height: 11rem; margin-bottom: 1.2rem; }
.gift-block .gift-title { font-size: clamp(1.7rem, 8vw, 2.3rem); }
.gift-block .gift-sub { margin: .9rem auto 1.4rem; font-size: .9rem; }

/* a warm line reads softer than a punchline */
.line.warm-line {
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: 1.22;
  font-size: clamp(1.5rem, 7vw, 2.1rem);
}

/* the closing section: picture above, signature under it */
/* on the closing frame the signature sits under the picture, not over it */
.is-closer .rises { top: auto; bottom: 5vh; padding-top: 0; }
.is-closer .sig { margin: 0; color: #fff; text-shadow: 0 2px 18px rgba(0,0,0,.8); }

.pane-close { padding-inline: 1rem; }
.close-photo {
  margin: 0;
  padding: 5px;
  background: var(--frame);
  border-radius: .5rem;
  overflow: hidden;
  line-height: 0;
}
.close-photo img {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 72dvh;
}
.pane-close .sig { margin-top: 1.6rem; }

/* an empty photo frame would otherwise show as a white bar */
.photos.empty { display: none; }

/* ---------- gift ---------- */
.gift-stage {
  position: relative;
  display: grid;
  place-items: center;
  height: auto;
  min-height: 12.5rem;
  margin-bottom: 1.8rem;
}

/* the gift card itself */
.gift-card {
  position: relative;
  width: min(84%, 19rem);
  aspect-ratio: 1.586;              /* credit-card proportions */
  border-radius: 1rem;
  background: var(--card);
  color: var(--card-ink);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  overflow: hidden;
  box-shadow: 0 18px 44px rgba(0, 0, 0, .45);
  animation: cardIn 1s cubic-bezier(.2,.8,.25,1) both;
}
/* faint diagonal streaks across the card */
.gift-card::before {
  content: "";
  position: absolute;
  inset: -30%;
  background: repeating-linear-gradient(
      58deg, transparent 0 26px,
      rgba(255, 255, 255, .10) 26px 28px);
  pointer-events: none;
}
.gift-box {
  position: relative;
  width: 4.4rem;
  height: auto;
  fill: none;
  stroke: var(--card-ink);
  stroke-width: 4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.gift-box .box-body { fill: #faf7f0; }
.gift-card-label {
  position: relative;
  padding: 0 1rem;
  font-size: .92rem;
  font-weight: 700;
  letter-spacing: -.01em;
  text-align: center;
}

.burst { position: absolute; inset: 0; display: grid; place-items: center; }
.burst span {
  position: absolute;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--acc-2);
  opacity: 0;
  animation: pop 1.5s ease-out both;
}
.burst span:nth-child(1) { --a:   0deg; animation-delay: .18s; }
.burst span:nth-child(2) { --a:  45deg; animation-delay: .24s; }
.burst span:nth-child(3) { --a:  90deg; animation-delay: .20s; }
.burst span:nth-child(4) { --a: 135deg; animation-delay: .28s; }
.burst span:nth-child(5) { --a: 180deg; animation-delay: .22s; }
.burst span:nth-child(6) { --a: 225deg; animation-delay: .30s; }
.burst span:nth-child(7) { --a: 270deg; animation-delay: .19s; }
.burst span:nth-child(8) { --a: 315deg; animation-delay: .26s; }

.gift-title { font-size: clamp(2rem, 10vw, 2.8rem); }
.gift-sub {
  margin: 1.1rem auto 2rem;
  max-width: 22rem;
  color: var(--muted);
  font-size: .95rem;
}

.sending {
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  padding: .7rem 1.2rem;
  border-radius: 2rem;
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  border: 1px solid color-mix(in srgb, var(--acc) 34%, transparent);
  font-size: .85rem;
  font-weight: 600;
  color: var(--text);
}
.pulse {
  width: .5rem; height: .5rem;
  border-radius: 50%;
  background: var(--acc);
  box-shadow: 0 0 0 0 var(--glow);
  animation: pulse 1.8s ease-out infinite;
}

.sig {
  margin: 2.4rem 0 0;
  color: var(--muted);
  font-size: .9rem;
  font-style: italic;
  letter-spacing: .02em;
}

/* =========================================================================
   theme preview switcher (?preview=1 only)
   ========================================================================= */
.theme-switch {
  position: fixed;
  left: 50%;
  bottom: calc(.9rem + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  z-index: 99;
  display: flex;
  gap: .3rem;
  padding: .3rem;
  border-radius: 2rem;
  background: rgba(0,0,0,.72);
  backdrop-filter: blur(12px);
  border: 1px solid rgba(255,255,255,.14);
}
.theme-switch button {
  padding: .5rem .85rem;
  border: 0;
  border-radius: 2rem;
  background: transparent;
  color: #fff;
  font: 600 .78rem/1 -apple-system, system-ui, sans-serif;
  cursor: pointer;
}
.theme-switch button[aria-pressed="true"] { background: var(--acc); color: var(--on-acc); }

/* =========================================================================
   animations
   ========================================================================= */
@keyframes fadeIn  { from { opacity: 0 } to { opacity: 1 } }
@keyframes fadeOut { from { opacity: 1 } to { opacity: 0; visibility: hidden } }
@keyframes bob {
  0%, 100% { transform: translateY(0) }
  50%      { transform: translateY(6px) }
}
@keyframes shake {
  10%, 90% { transform: translateX(-2px) }
  20%, 80% { transform: translateX(4px) }
  30%, 50%, 70% { transform: translateX(-7px) }
  40%, 60% { transform: translateX(7px) }
}
@keyframes riseIn {
  from { opacity: 0; transform: translateY(28px) }
  to   { opacity: 1; transform: translateY(0) }
}
@keyframes cardIn {
  0%   { opacity: 0; transform: translateY(26px) scale(.86) rotate(-7deg) }
  55%  { opacity: 1; transform: translateY(0) scale(1.04) rotate(2deg) }
  100% { opacity: 1; transform: translateY(0) scale(1) rotate(0) }
}
@keyframes pop {
  0%   { opacity: 0; transform: rotate(var(--a)) translateY(0) scale(.4) }
  35%  { opacity: 1 }
  100% { opacity: 0; transform: rotate(var(--a)) translateY(-5.5rem) scale(1) }
}
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 var(--glow) }
  70%  { box-shadow: 0 0 0 .7rem transparent }
  100% { box-shadow: 0 0 0 0 transparent }
}

/* =========================================================================
   larger screens
   ========================================================================= */
@media (min-width: 40rem) {
  .stage-in { max-width: 30rem; }
  .photos { gap: 6px; padding: 6px; }
}

/* =========================================================================
   reduced motion — everything still readable, nothing moves
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}
