/* gift-carder viewer - riso party print
   Palette: paper #FFF9EF, ink #2B2141, riso pink #FF48B0,
   cobalt #0078BF, sunshine #FFE800, clover #00A95C, flame #FF6C2F */

@import url('https://fonts.googleapis.com/css2?family=Shrikhand&family=Karla:ital,wght@0,400;0,700;1,400&family=Caveat:wght@600&display=swap');

:root {
  --paper: #FFF9EF;
  --ink: #2B2141;
  --ink-soft: rgba(43, 33, 65, 0.62);
  /* theme slots, overridden per card */
  --hue-a: #FF48B0;
  --hue-b: #0078BF;
  --hue-c: #FFE800;
  --display: 'Shrikhand', 'Georgia', serif;
  --body: 'Karla', 'Helvetica Neue', sans-serif;
  --hand: 'Caveat', cursive;
}

* { box-sizing: border-box; margin: 0; }

button, .arrows, .garland { touch-action: manipulation; }

html, body {
  height: 100%;
  overscroll-behavior: none;
}

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
}

/* paper grain over everything */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 200;
  pointer-events: none;
  opacity: 0.5;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3CfeColorMatrix values='0 0 0 0 0.85 0 0 0 0 0.83 0 0 0 0 0.80 0 0 0 0.06 0'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23n)'/%3E%3C/svg%3E");
}

#card {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
}

/* ---------- bunting garland (progress) ---------- */

.garland {
  position: relative;
  z-index: 60;
  display: flex;
  justify-content: center;
  gap: 10px;
  padding: max(14px, env(safe-area-inset-top)) 16px 4px;
}

/* the string the flags hang from */
.garland::before {
  content: '';
  position: absolute;
  top: max(13px, env(safe-area-inset-top));
  left: -5%;
  right: -5%;
  height: 2px;
  background: var(--ink);
  opacity: 0.28;
  border-radius: 2px;
  transform: rotate(-0.4deg);
}

.flag {
  width: 16px;
  height: 20px;
  padding: 0;
  border: 0;
  cursor: pointer;
  clip-path: polygon(0 0, 100% 0, 50% 100%);
  background: var(--flag-hue, var(--hue-a));
  opacity: 0.22;
  transform-origin: top center;
  transition: opacity 0.35s ease, transform 0.35s ease;
}

.flag.is-done { opacity: 1; }

.flag.is-here {
  opacity: 1;
  transform: scale(1.35);
  animation: flag-wave 1.6s ease-in-out infinite alternate;
}

@keyframes flag-wave {
  from { transform: scale(1.35) rotate(-7deg); }
  to   { transform: scale(1.35) rotate(7deg); }
}

.flag:focus-visible {
  outline: 3px solid var(--hue-b);
  outline-offset: 3px;
}

/* ---------- the deck ---------- */

.deck {
  position: relative;
  flex: 1;
  overflow: hidden;
}

.slide {
  position: absolute;
  inset: 0;
  background: var(--paper);
  overflow: hidden;
  will-change: transform;
  transition: transform 0.55s cubic-bezier(0.33, 0.02, 0.2, 1);
}

.slide-body {
  height: 100%;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  /* browser handles vertical panning, our JS handles horizontal swipes */
  touch-action: pan-y;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(14px, 3vh, 26px);
  padding: 3vh clamp(20px, 6vw, 64px) 12vh;
  text-align: center;
}

/* invisible spacers: center short content, top-align overflowing
   content so it stays scrollable from the very top on any browser */
.slide-body::before,
.slide-body::after { content: ''; flex: 0 0 0; }
.slide-body::before { margin-top: auto; }
.slide-body::after { margin-bottom: auto; }

.copy {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(14px, 3vh, 26px);
}

/* a little more air between the words and the photo */
.slide-body .snapshot { margin-top: clamp(10px, 2.5vh, 26px); }

/* wide screens: same stack (text above photo), everything scaled up */
@media (min-width: 900px) {
  .slide-has-photo .prose { max-width: 52ch; }
  .slide-has-photo .snapshot { width: min(54vw, 640px); }
  .slide-has-photo .snapshot img { max-height: 54vh; }
}

/* dealt off the stack, resting to the left */
.slide.is-out {
  transform: translate(-120%, -5%) rotate(-9deg);
  box-shadow: 24px 0 40px rgba(43, 33, 65, 0.18);
}

.slide.is-under { transform: scale(0.965); }

@media (prefers-reduced-motion: reduce) {
  .slide { transition: opacity 0.25s ease; }
  .slide.is-out, .slide.is-under { transform: none; opacity: 0; }
  .slide.is-current { opacity: 1; }
  .flag.is-here { animation: none; }
}

/* ---------- type ---------- */

.eyebrow {
  font-size: clamp(0.72rem, 2.4vw, 0.85rem);
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.slide h1 {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(2.6rem, 11vw, 5.2rem);
  line-height: 1.08;
  color: var(--hue-a);
  text-shadow: 3px 3px 0 var(--hue-c);
}

.slide h2 {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(1.5rem, 5.6vw, 2.2rem);
  line-height: 1.2;
  color: var(--slide-hue, var(--hue-b));
}

.subtitle {
  font-size: clamp(1rem, 3.4vw, 1.2rem);
  color: var(--ink-soft);
}

/* the cover's subtitle is a second headline, not a caption */
.slide-cover .subtitle {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(1.9rem, 8vw, 3.8rem);
  line-height: 1.18;
  color: var(--hue-b);
  text-shadow: 2px 2px 0 var(--hue-c);
}

.prose {
  max-width: 38ch;
  font-size: clamp(1.3rem, 5vw, 1.65rem);
  line-height: 1.55;
}

.prose p + p { margin-top: 0.9em; }

/* long letters: left-aligned, wider measure */
.prose-long {
  max-width: 48ch;
  font-size: clamp(1.15rem, 4.2vw, 1.4rem);
  line-height: 1.6;
  text-align: left;
}

.sparkle.scatter { opacity: 0.9; }

.signoff {
  font-family: var(--hand);
  font-size: clamp(1.6rem, 6vw, 2.2rem);
  color: var(--slide-hue, var(--hue-b));
  transform: rotate(-2deg);
}

/* ---------- taped snapshot ---------- */

.snapshot {
  position: relative;
  background: #fff;
  padding: 10px 10px 14px;
  box-shadow: 0 10px 26px rgba(43, 33, 65, 0.2);
  transform: rotate(var(--tilt, -2.5deg));
  width: min(90vw, 460px);
}

.snapshot img {
  display: block;
  width: 100%;
  max-height: 52vh;
  object-fit: cover;
  /* bias the crop upward, faces usually live in the top half */
  object-position: 50% 35%;
}

/* washi tape */
.snapshot::before {
  content: '';
  position: absolute;
  top: -12px;
  left: 50%;
  width: 86px;
  height: 26px;
  transform: translateX(-50%) rotate(calc(var(--tilt, -2.5deg) * -1.4));
  background: linear-gradient(100deg, var(--hue-c) 0%, var(--hue-c) 55%, var(--hue-a) 55%);
  opacity: 0.82;
}

.snapshot figcaption {
  font-family: var(--hand);
  font-size: 1.4rem;
  color: var(--ink);
  padding-top: 8px;
}

/* ---------- hints and controls ---------- */

.hint {
  position: absolute;
  bottom: calc(max(18px, env(safe-area-inset-bottom)) + 66px);
  left: 50%;
  transform: translateX(-50%) rotate(-1.5deg);
  font-weight: 700;
  font-size: 0.82rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--paper);
  background: var(--ink);
  padding: 10px 20px;
  border-radius: 999px;
  animation: hint-bob 1.5s ease-in-out infinite alternate;
  pointer-events: none;
  white-space: nowrap;
}

@keyframes hint-bob {
  from { transform: translateX(-50%) rotate(-1.5deg) translateY(0); }
  to   { transform: translateX(-50%) rotate(-1.5deg) translateY(-7px); }
}

@media (prefers-reduced-motion: reduce) {
  .hint { animation: none; }
}

/* ---------- bottom arrows ---------- */

.arrows {
  position: absolute;
  bottom: max(18px, env(safe-area-inset-bottom));
  left: 50%;
  transform: translateX(-50%);
  z-index: 55;
  display: flex;
  gap: 18px;
}

.arrow {
  width: 54px;
  height: 54px;
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  background: var(--hue-a);
  color: var(--paper);
  font-size: 1.5rem;
  line-height: 1;
  display: grid;
  place-items: center;
  box-shadow: 3px 3px 0 var(--hue-c);
  transition: transform 0.15s ease, opacity 0.25s ease;
  -webkit-tap-highlight-color: transparent;
}

.arrow:hover:not(:disabled) { transform: translateY(-2px); }
.arrow:active:not(:disabled) { transform: translateY(1px); box-shadow: 1px 1px 0 var(--hue-c); }

.arrow:disabled {
  opacity: 0.25;
  cursor: default;
  box-shadow: none;
}

.arrow:focus-visible {
  outline: 3px solid var(--hue-b);
  outline-offset: 3px;
}

.arrow svg { width: 22px; height: 22px; display: block; }

/* ---------- girly extras: crown and sparkles ---------- */

.crown {
  width: clamp(56px, 14vw, 84px);
  margin-bottom: -6px;
  transform: rotate(-9deg);
  filter: drop-shadow(2px 3px 0 rgba(43, 33, 65, 0.15));
}

.sparkle {
  position: absolute;
  z-index: 5;
  font-size: var(--spk-size, 1.2rem);
  color: var(--spk-hue, #FFC42E);
  pointer-events: none;
  user-select: none;
  animation: twinkle 1.8s ease-in-out infinite alternate;
  animation-delay: var(--spk-delay, 0s);
}

@keyframes twinkle {
  from { opacity: 0.25; transform: scale(0.7) rotate(-12deg); }
  to   { opacity: 1;    transform: scale(1.15) rotate(12deg); }
}

@media (prefers-reduced-motion: reduce) {
  .sparkle { animation: none; opacity: 0.8; }
}


/* ---------- confetti canvas ---------- */

/* canvas is a replaced element: inset alone does not stretch it, so
   size it explicitly or high-DPI screens get a giant offset bitmap */
#confetti {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 150;
  pointer-events: none;
}

/* ---------- error state ---------- */

.load-error {
  max-width: 40ch;
  margin: 30vh auto 0;
  padding: 0 24px;
  text-align: center;
  line-height: 1.6;
}

.load-error h1 {
  font-family: var(--display);
  font-size: 1.6rem;
  color: var(--hue-a);
  text-shadow: none;
  margin-bottom: 12px;
}

.load-error a {
  display: inline-block;
  margin-top: 16px;
  font-weight: 700;
  font-size: 0.85rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--paper);
  background: var(--ink);
  padding: 12px 24px;
  border-radius: 999px;
}
