@font-face { font-family: "Gabriela"; font-display: swap; src: url(/fonts/gabriela-cyrillic-400.woff2) format("woff2"); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: "Gabriela"; font-display: swap; src: url(/fonts/gabriela-latin-400.woff2) format("woff2"); unicode-range: U+0000-00FF, U+2000-206F, U+20AC, U+2122; }
@font-face { font-family: "Marck Script"; font-display: swap; src: url(/fonts/marck-script-cyrillic-400.woff2) format("woff2"); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: "Marck Script"; font-display: swap; src: url(/fonts/marck-script-latin-400.woff2) format("woff2"); unicode-range: U+0000-00FF, U+2000-206F, U+20AC, U+2122; }
@font-face { font-family: "EB Garamond"; font-weight: 400; font-display: swap; src: url(/fonts/eb-garamond-cyrillic-400.woff2) format("woff2"); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: "EB Garamond"; font-weight: 400; font-display: swap; src: url(/fonts/eb-garamond-latin-400.woff2) format("woff2"); unicode-range: U+0000-00FF, U+2000-206F, U+20AC, U+2122; }
@font-face { font-family: "EB Garamond"; font-weight: 400; font-style: italic; font-display: swap; src: url(/fonts/eb-garamond-cyrillic-400i.woff2) format("woff2"); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: "EB Garamond"; font-weight: 400; font-style: italic; font-display: swap; src: url(/fonts/eb-garamond-latin-400i.woff2) format("woff2"); unicode-range: U+0000-00FF, U+2000-206F, U+20AC, U+2122; }
@font-face { font-family: "EB Garamond"; font-weight: 500; font-display: swap; src: url(/fonts/eb-garamond-cyrillic-500.woff2) format("woff2"); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: "EB Garamond"; font-weight: 500; font-display: swap; src: url(/fonts/eb-garamond-latin-500.woff2) format("woff2"); unicode-range: U+0000-00FF, U+2000-206F, U+20AC, U+2122; }

:root {
  --night: #171a45;
  --night-up: #232764;
  --night-deep: #0e1033;
  --parchment: #ead7ae;
  --parchment-deep: #d9bf8a;
  --ink: #2a1b3d;
  --emerald: #0f5c43;
  --wax: #8e1b2d;
  --gold: #e2b650;
  --line: #a8863f;
  --house: #8e1b2d;
  --on-house: #fff4dc;
  --house-2: #e2b650;
  --display: "Gabriela", Georgia, serif;
  --script: "Marck Script", cursive;
  --text: "EB Garamond", Georgia, serif;
  --focus: var(--gold);
  --corner: 22px;
}
body[data-house="gryffindor"] { --house: #a81c2e; --on-house: #fff4dc; --house-2: #f2b632; --line: #b98a33; }
body[data-house="slytherin"] { --house: #16713f; --on-house: #f2f6ef; --house-2: #c8d0cf; --line: #7f9a8a; }
body[data-house="ravenclaw"] { --house: #2546a8; --on-house: #f3f1e6; --house-2: #c79a57; --line: #8a78a0; }
body[data-house="hufflepuff"] { --house: #eab928; --on-house: #2b2622; --house-2: #f6d774; --line: #bfa03e; }

*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

body {
  margin: 0;
  color: var(--parchment);
  font: 400 1.1875rem/1.5 var(--text);
  font-feature-settings: "onum";
  background-color: var(--night);
  background-image:
    radial-gradient(1.5px 1.5px at 22px 34px, #fff9 50%, transparent 52%),
    radial-gradient(1.1px 1.1px at 141px 89px, #fff7 50%, transparent 52%),
    radial-gradient(2px 2px at 263px 171px, var(--gold) 50%, transparent 52%),
    radial-gradient(1.1px 1.1px at 87px 243px, #fff8 50%, transparent 52%),
    radial-gradient(1.4px 1.4px at 331px 301px, #fff6 50%, transparent 52%);
  background-size: 317px 293px, 431px 383px, 613px 541px, 239px 457px, 523px 677px;
}
@media (pointer: fine) {
  body { cursor: url(/wand-cursor.svg) 2 2, auto; }
  a, button, label { cursor: url(/wand-cursor.svg) 2 2, pointer; }
}

h1, h2, h3 { font-family: var(--display); font-weight: 400; margin: 0; }
h2 { font-size: clamp(2.25rem, 8vw, 3.5rem); line-height: 1.05; }
p { margin: 0; }
a { color: inherit; text-underline-offset: 3px; }
:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.art { display: block; width: 100%; height: 100%; }
:where(.art) :where(g, path, rect, circle, ellipse) { transform-box: fill-box; transform-origin: center; }

/* buttons */
.btn {
  display: inline-block;
  min-height: 48px;
  padding: 0.6rem 1.4rem;
  border: 0;
  border-radius: 4px;
  background: var(--house);
  color: var(--on-house);
  font: 500 1.125rem/1.25 var(--text);
  text-align: center;
  text-decoration: none;
  transition: filter 0.15s, transform 0.1s, background-color 0.3s;
}
.btn:hover { filter: brightness(1.15); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: 0.6; }
.btn--ghost { background: none; color: var(--parchment); box-shadow: inset 0 0 0 1.5px var(--house-2); }
.btn--quiet, .btn--quiet-dark { background: none; padding-inline: 0; text-decoration: underline; text-underline-offset: 3px; }
.btn--quiet { color: var(--wax); }
.btn--quiet-dark { color: var(--parchment); }

/* enchanted ceiling */
.ceiling { position: relative; height: clamp(104px, 14vw, 130px); overflow: hidden; }
@media (max-width: 600px) { .candle:nth-child(n + 9) { display: none; } }
.candle {
  position: absolute;
  top: 34px;
  left: 8%;
  width: 11px;
  height: 46px;
  border-radius: 2px;
  background: linear-gradient(90deg, #cfc2a2, #f7f0de 45%, #c2b48f);
  animation: bob 5.2s ease-in-out infinite alternate;
}
.candle::before {
  content: "";
  position: absolute;
  left: 1px;
  top: -19px;
  width: 9px;
  height: 19px;
  border-radius: 50% 50% 45% 45% / 70% 70% 30% 30%;
  background: radial-gradient(circle at 50% 75%, #fff8d8 0 22%, #ffc94d 45%, #f08a1c 90%);
  transform-origin: 50% 100%;
  animation: flicker 0.32s ease-in-out infinite alternate;
}
.candle::after { content: ""; position: absolute; left: -24px; top: -40px; width: 60px; height: 60px; border-radius: 50%; background: radial-gradient(circle, #ffcf6b55, transparent 70%); }
.candle:nth-child(2) { left: 20%; top: 22px; height: 38px; animation-duration: 6.4s; animation-delay: -2s; }
.candle:nth-child(3) { left: 33%; top: 40px; height: 34px; animation-duration: 4.8s; animation-delay: -1s; }
.candle:nth-child(4) { left: 46%; top: 26px; height: 44px; animation-duration: 5.8s; animation-delay: -3s; }
.candle:nth-child(5) { left: 59%; top: 42px; height: 30px; animation-duration: 6.9s; animation-delay: -4s; }
.candle:nth-child(6) { left: 71%; top: 24px; height: 42px; animation-duration: 5s; animation-delay: -2.4s; }
.candle:nth-child(7) { left: 83%; top: 38px; height: 36px; animation-duration: 6.2s; animation-delay: -.6s; }
.candle:nth-child(8) { left: 93%; top: 26px; height: 46px; animation-duration: 5.5s; animation-delay: -3.6s; }
.candle:nth-child(9) { left: 14%; top: 60px; height: 26px; animation-duration: 7s; animation-delay: -1.6s; }
.candle:nth-child(10) { left: 77%; top: 62px; height: 24px; animation-duration: 6.6s; animation-delay: -5s; }
@keyframes bob { from { transform: translateY(-5px); } to { transform: translateY(7px); } }
@keyframes flicker { from { transform: scale(1, 1) rotate(-2deg); } to { transform: scale(0.88, 1.12) rotate(3deg); } }

/* cabinet */
.hero { max-width: 1240px; margin: 0 auto; padding: 0 1rem; }
.vit {
  display: grid;
  gap: 1.5px;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(2, 22vw) auto repeat(4, 22vw);
  grid-template-areas:
    "hat hat owl snitch"
    "hat hat owl glasses"
    "title title title title"
    "potion letter letter sock"
    "potion broom broom frog"
    "turner broom broom platform"
    "turner wand wand platform";
  border: 1.5px solid var(--line);
  background: var(--line);
  transition: background-color 0.5s, border-color 0.5s;
}
.vit__cell {
  position: relative;
  display: grid;
  place-items: center;
  min-width: 0;
  min-height: 0;
  padding: clamp(6px, 1.6vw, 14px);
  border: 0;
  overflow: hidden;
  background: var(--night);
  color: inherit;
  transition: background-color 0.2s;
}
.vit__cell:hover { background: var(--night-up); }
.vit__cell:focus-visible { outline-offset: -4px; }
.vit__cell--hat { grid-area: hat; } .vit__cell--owl { grid-area: owl; } .vit__cell--snitch { grid-area: snitch; }
.vit__cell--glasses { grid-area: glasses; } .vit__cell--potion { grid-area: potion; } .vit__cell--letter { grid-area: letter; }
.vit__cell--sock { grid-area: sock; } .vit__cell--broom { grid-area: broom; } .vit__cell--frog { grid-area: frog; }
.vit__cell--turner { grid-area: turner; } .vit__cell--wand { grid-area: wand; } .vit__cell--platform { grid-area: platform; padding: 0; }
.vit__title {
  grid-area: title;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 1.75rem 1rem;
  text-align: center;
  background: radial-gradient(ellipse at 50% 40%, var(--night-up), var(--night) 72%);
}
.vit__title h1 {
  font-size: clamp(3.1rem, 15.4vw, 6.4rem);
  line-height: 0.98;
  background: linear-gradient(175deg, #fff0bf 12%, #e2b650 52%, #9b6f1e 92%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.vit__date { margin-top: 0.5rem; font: 1.75rem/1.1 var(--script); color: var(--parchment); }
.vit__count { color: var(--house-2); font-style: italic; }
.vit__cta { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.75rem; margin-top: 1.1rem; }
.vit__hint { margin: 0.6rem 0 0; text-align: center; font-style: italic; opacity: 0.85; }
@media (min-width: 900px) {
  .vit__title { padding: 1rem; }
  .vit__title h1 { font-size: 4.7rem; }
  .hero { padding-inline: 2rem; }
  .vit {
    grid-template-columns: repeat(8, 1fr);
    grid-template-rows: repeat(4, minmax(170px, auto));
    grid-template-areas:
      "hat hat snitch snitch glasses glasses owl owl"
      "hat hat title title title title owl owl"
      "wand potion title title title title sock turner"
      "broom broom letter letter frog platform platform turner";
  }
}

/* living objects */
.hat__all { transform-origin: 50% 100%; animation: hat-sway 5s ease-in-out infinite alternate; }
.hat__tip { transform-origin: 0% 100%; animation: tip 3.4s ease-in-out infinite alternate; }
.hat__eye { animation: blink 6s infinite; }
.hat__eye--r { animation-delay: 0.08s; }
.hat__mouth { transform-origin: 50% 0; transform: scaleY(0.42); }
.is-talking .hat__mouth { animation: talk 0.2s ease-in-out infinite alternate; }
.is-thinking .hat__all { animation: hat-shake 0.28s ease-in-out infinite alternate; }
@keyframes hat-sway { from { transform: rotate(-1.6deg); } to { transform: rotate(1.6deg); } }
@keyframes tip { from { transform: rotate(-3deg); } to { transform: rotate(5deg); } }
@keyframes blink { 0%, 93%, 100% { transform: scaleY(1); } 96% { transform: scaleY(0.08); } }
@keyframes talk { from { transform: scaleY(0.25); } to { transform: scaleY(1); } }
@keyframes hat-shake { from { transform: rotate(-4deg) translateY(1px); } to { transform: rotate(4deg) translateY(-2px); } }

.owl__lids { transform-origin: 50% 0; transform: scaleY(0); animation: lids 7s infinite; }
@keyframes lids { 0%, 94%, 100% { transform: scaleY(0); } 96.5% { transform: scaleY(1); } }
.owl__wing { transform-origin: 80% 10%; }
.owl__wing--r { transform-origin: 20% 10%; }
[data-obj="owl"].is-hit .owl { animation: owl-hop 0.5s ease-out; }
@keyframes owl-hop { 40% { transform: translateY(-10%) rotate(-3deg); } }

.fly__wing--l { transform-origin: 100% 40%; animation: flap-l 0.34s ease-in-out infinite alternate; }
.fly__mirror { transform-box: view-box; transform-origin: 50% 0; transform: scaleX(-1); }
@keyframes flap-l { from { transform: rotate(14deg); } to { transform: rotate(-20deg); } }

.snitch__wing { transform-origin: 100% 60%; animation: flutter-l 0.11s linear infinite alternate; }
.snitch__wing--r { transform-origin: 0% 60%; animation-name: flutter-r; }
.vit__cell--snitch .art { animation: hover-snitch 2.6s ease-in-out infinite alternate; }
@keyframes flutter-l { from { transform: rotate(16deg) scaleY(1); } to { transform: rotate(-22deg) scaleY(0.72); } }
@keyframes flutter-r { from { transform: rotate(-16deg) scaleY(1); } to { transform: rotate(22deg) scaleY(0.72); } }
@keyframes hover-snitch { from { transform: translate(-4%, 5%); } to { transform: translate(4%, -5%); } }

.glasses__glint { animation: glint 5s ease-in-out infinite; opacity: 0; }
@keyframes glint { 0%, 70%, 100% { opacity: 0; transform: translateX(-10px); } 78% { opacity: 0.9; } 90% { opacity: 0; transform: translateX(60px); } }

.potion__liquid { fill: var(--potion, #e2b02c); transition: fill 0.5s; }
.potion__bubble { fill: #fff; opacity: 0; animation: bubble 2.6s ease-in infinite; }
.potion__bubble--2 { animation-delay: 0.9s; animation-duration: 3.2s; }
.potion__bubble--3 { animation-delay: 1.7s; animation-duration: 2.2s; }
@keyframes bubble { 0% { opacity: 0; transform: translateY(0); } 15% { opacity: 0.75; } 100% { opacity: 0; transform: translateY(-46px); } }

.sock { transform-origin: 50% 0; animation: swing 3.2s ease-in-out infinite alternate; }
@keyframes swing { from { transform: rotate(-6deg); } to { transform: rotate(6deg); } }
.vit__cell--sock.is-hit .art { animation: sock-free 1.1s ease-in forwards; }
@keyframes sock-free { 40% { transform: translateY(-16%) rotate(20deg); } 100% { transform: translateY(-160%) rotate(120deg); opacity: 0; } }

.turner__ring { animation: spin 14s linear infinite; }
.turner__glass { animation: tilt 7s ease-in-out infinite; }
.vit__cell--turner.is-hit .turner__ring { animation-duration: 0.9s; }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes tilt { 0%, 80%, 100% { transform: rotate(0); } 90% { transform: rotate(180deg); } }

.broom { animation: broom-hover 2.8s ease-in-out infinite alternate; }
.vit__cell--broom.is-hit .art { animation: broom-zoom 1s ease-in forwards; }
@keyframes broom-hover { from { transform: translateY(-5%) rotate(-3deg); } to { transform: translateY(5%) rotate(2deg); } }
@keyframes broom-zoom { 30% { transform: translateX(-12%) rotate(-8deg); } 100% { transform: translateX(150%) rotate(4deg); } }

.frog { animation: frog-sit 4.4s ease-in-out infinite; transform-origin: 50% 100%; }
.frog__eye { animation: blink 4s infinite; }
@keyframes frog-sit { 0%, 86%, 100% { transform: scale(1, 1); } 92% { transform: scale(1.05, 0.93); } }
.vit__cell--frog.is-hit .art { animation: frog-jump 0.9s ease-in forwards; }
@keyframes frog-jump { 20% { transform: scale(1.12, 0.8); } 60% { transform: translate(40%, -90%) rotate(14deg); } 100% { transform: translate(120%, -30%) rotate(30deg); opacity: 0; } }

.wand__spark { animation: twinkle 1.4s ease-in-out infinite alternate; }
.wand__spark--2 { animation-delay: 0.5s; }
.wand__spark--3 { animation-delay: 0.9s; }
@keyframes twinkle { from { opacity: 0.15; transform: scale(0.5) rotate(-20deg); } to { opacity: 1; transform: scale(1.1) rotate(20deg); } }

.vit__cell--letter .art { animation: letter-float 3.6s ease-in-out infinite alternate; }
@keyframes letter-float { from { transform: translateY(-4%) rotate(-2deg); } to { transform: translateY(4%) rotate(2deg); } }
.vit__cell--platform.is-hit .art { animation: wall-ripple 0.8s ease-in-out; }
@keyframes wall-ripple { 30% { transform: scale(1.1) skewX(3deg); filter: blur(2px); } 60% { transform: scale(0.97) skewX(-2deg); } }
.vit.is-away *, .vit.is-away *::before { animation-play-state: paused !important; }

/* intro */
.intro {
  position: fixed;
  inset: 0;
  width: 100vw;
  max-width: none;
  height: 100dvh;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  overflow: hidden;
  color: var(--parchment);
  background-color: var(--night-deep);
  background-image: radial-gradient(1.5px 1.5px at 22px 34px, #fff9 50%, transparent 52%), radial-gradient(1.1px 1.1px at 141px 89px, #fff7 50%, transparent 52%), radial-gradient(2px 2px at 263px 171px, var(--gold) 50%, transparent 52%);
  background-size: 317px 293px, 431px 383px, 613px 541px;
}
.intro[open] { display: grid; place-items: center; }
.intro:focus { outline: none; }
.intro::backdrop { background: var(--night-deep); }
.intro.is-closing { animation: intro-out 0.5s ease-in forwards; }
@keyframes intro-out { to { opacity: 0; transform: scale(1.06); } }
.intro__skip { position: absolute; top: 12px; right: 12px; z-index: 5; min-height: 44px; padding: 0.3rem 0.9rem; border: 0; background: none; color: var(--parchment); font: inherit; text-decoration: underline; text-underline-offset: 3px; }
.intro__owl { position: absolute; top: 6%; left: 50%; z-index: 4; width: min(62vw, 300px); margin-left: calc(min(62vw, 300px) / -2); opacity: 0; }
.intro__owl.is-in { opacity: 1; animation: owl-in 1.2s cubic-bezier(0.25, 0.7, 0.3, 1) forwards; }
.intro__owl.is-drop .fly__mail { opacity: 0; }
.intro__owl.is-out { opacity: 1; animation: owl-out 1s ease-in forwards; }
@keyframes owl-in { from { transform: translate(90vw, -40vh) scale(0.5); } to { transform: translate(0, 0) scale(1); } }
@keyframes owl-out { from { transform: translate(0, 0); } to { transform: translate(-95vw, -55vh) scale(0.45); } }

.env { position: relative; z-index: 2; width: min(86vw, 430px); aspect-ratio: 1.55; perspective: 1100px; opacity: 0; }
.env.is-dropped { opacity: 1; animation: env-drop 0.6s cubic-bezier(0.3, 0.1, 0.4, 1.35) both; }
.env.is-gone { animation: env-gone 0.5s ease-in forwards; }
@keyframes env-drop { from { transform: translateY(-30vh) rotate(-10deg) scale(0.5); } to { transform: none; } }
@keyframes env-gone { to { transform: translateY(70vh) rotate(6deg); opacity: 0; } }
.env__body { position: relative; width: 100%; height: 100%; transform-style: preserve-3d; transition: transform 0.75s cubic-bezier(0.4, 0, 0.2, 1); }
.env.is-back .env__body { transform: rotateY(180deg); }
.env__face { position: absolute; inset: 0; backface-visibility: hidden; border-radius: 4px; background: var(--parchment); box-shadow: 0 16px 40px #0007; }
.env__face--front { display: grid; place-items: center; padding: 1rem; }
.env__to { color: var(--emerald); font: 1.5rem/1.3 var(--script); text-align: center; }
.env__face--back { --focus: var(--wax); transform: rotateY(180deg); background: linear-gradient(160deg, #e3cd9c, #d6bd87); }
.env__flap { position: absolute; left: 0; right: 0; top: 0; height: 58%; background: var(--parchment); clip-path: polygon(0 0, 100% 0, 50% 100%); transform-origin: 50% 0; transition: transform 0.5s ease-in-out; filter: drop-shadow(0 3px 2px #0003); }
.env.is-open .env__flap { transform: perspective(700px) rotateX(165deg); }
.env__seal { position: absolute; left: calc(50% - 38px); top: calc(58% - 38px); width: 76px; height: 76px; padding: 0; border: 0; border-radius: 50%; background: none; animation: seal-pulse 1.4s ease-in-out infinite alternate; }
.env__half { position: absolute; inset: 0; display: grid; place-items: center; border-radius: 50%; background: radial-gradient(circle at 38% 32%, #b83148, var(--wax) 60%, #5e0f1d); box-shadow: inset 0 0 0 5px #a02840, inset 0 0 0 6.5px #d0687a; color: #ffe9c9; font: 2rem/1 var(--display); transition: transform 0.45s ease-in, opacity 0.45s ease-in; }
.env__half--l { clip-path: polygon(0 0, 54% 0, 44% 32%, 58% 60%, 46% 100%, 0 100%); }
.env__half--r { clip-path: polygon(54% 0, 100% 0, 100% 100%, 46% 100%, 58% 60%, 44% 32%); }
.env.is-broken .env__seal { animation: none; }
.env.is-broken .env__half--l { transform: translate(-38px, 26px) rotate(-34deg); opacity: 0; }
.env.is-broken .env__half--r { transform: translate(38px, 26px) rotate(34deg); opacity: 0; }
.env__hint { position: absolute; left: 0; right: 0; bottom: 8%; color: var(--ink); font: 1.25rem/1 var(--script); text-align: center; }
.env.is-broken .env__hint { opacity: 0; }
@keyframes seal-pulse { from { transform: scale(1); filter: drop-shadow(0 0 2px #ffd36a55); } to { transform: scale(1.09); filter: drop-shadow(0 0 14px #ffd36acc); } }

.letter {
  --focus: var(--wax);
  position: absolute;
  z-index: 3;
  width: min(92vw, 520px);
  max-height: 90dvh;
  overflow: auto;
  padding: 1.75rem 1.5rem;
  border-radius: 3px;
  color: var(--ink);
  background: linear-gradient(170deg, #f1e1bd, #e4cf9f);
  box-shadow: 0 20px 60px #000a;
  line-height: 1.4;
}
.letter.is-rising { animation: letter-rise 0.7s cubic-bezier(0.2, 0.8, 0.3, 1) both; }
@keyframes letter-rise { from { opacity: 0; transform: translateY(26vh) scale(0.55); } to { opacity: 1; transform: none; } }
.letter p + p { margin-top: 0.6rem; }
.letter__school { font-size: 1.6rem; line-height: 1.15; text-align: center; color: var(--emerald); }
.letter__head { margin-top: 0.4rem; text-align: center; }
.letter__head small { display: block; font-size: 0.95rem; font-style: italic; line-height: 1.25; }
.letter__hi { margin-top: 1rem !important; color: var(--emerald); font: 1.85rem/1.1 var(--script); }
.letter__sign { margin-top: 1rem !important; color: var(--emerald); font: 1.6rem/1.1 var(--script); }
.letter__sign small { font-size: 1.1rem; }
.letter .btn { margin-top: 1.1rem; width: 100%; }

/* sorting */
.sort { max-width: 880px; margin: 0 auto; padding: clamp(3rem, 9vw, 5.5rem) 1rem 2rem; text-align: center; }
.sort__stage { display: grid; justify-items: center; gap: 0.25rem; margin-top: 1rem; }
.sort__speech { position: relative; width: min(100%, 560px); min-height: 5.6rem; padding: 0.9rem 1.25rem; border-radius: 22px; color: var(--ink); background: var(--parchment); font: 1.5rem/1.25 var(--script); display: grid; place-items: center; }
.sort__speech::after { content: ""; position: absolute; left: calc(50% - 12px); bottom: -14px; border: 12px solid transparent; border-top-color: var(--parchment); border-bottom: 0; }
.sort__hat { width: min(72vw, 330px); aspect-ratio: 320 / 300; margin-top: 0.75rem; }
.sort__options { display: grid; gap: 0.6rem; max-width: 560px; margin: 1.25rem auto 0; }
.opt { min-height: 54px; padding: 0.55rem 1rem; border: 1.5px solid var(--house-2); border-radius: 6px; background: var(--night-up); color: var(--parchment); font: 1.1875rem/1.2 var(--text); text-align: left; transition: background-color 0.15s, transform 0.1s; }
.opt:hover { background: #2e3380; }
.opt:active { transform: scale(0.99); }
.opt span { display: block; font-size: 1rem; font-style: italic; opacity: 0.85; }
.sort__result { margin-top: 0.5rem; }
.banner { width: 124px; height: 158px; margin: 0 auto; display: grid; place-items: center; padding-bottom: 24px; color: var(--on-house); background: var(--house); clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 84%, 0 100%); box-shadow: inset 0 0 0 4px var(--house-2); transform-origin: 50% 0; animation: unfurl 0.65s cubic-bezier(0.2, 1.2, 0.4, 1) both; }
.banner b { font: 4.25rem/1 var(--display); }
@keyframes unfurl { from { transform: scaleY(0); } to { transform: scaleY(1); } }
.sort__house { margin-top: 0.5rem; font: clamp(2.75rem, 11vw, 4.5rem)/1.05 var(--display); color: var(--house-2); animation: shout 0.5s cubic-bezier(0.2, 1.4, 0.4, 1) both; }
@keyframes shout { from { opacity: 0; transform: scale(0.4); } to { opacity: 1; transform: none; } }
.sort__quip { max-width: 34em; margin: 0.5rem auto 0; font-style: italic; }
.sort__actions { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 0.75rem 1.25rem; margin-top: 1.25rem; }

/* wishes */
.wishes { max-width: 1240px; margin: 0 auto; padding: 3.5rem 1rem 1rem; }
@media (min-width: 900px) { .wishes { padding-inline: 2rem; } }
.wishes__head { max-width: 40em; }
.wishes__head p { margin-top: 0.75rem; }
.filter { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 1.5rem 0 2rem; }
.filter button { min-height: 52px; padding: 0.4rem 0.95rem; border: 1.5px solid var(--house-2); border-radius: 6px; background: none; color: var(--parchment); font: inherit; font-size: 1.0625rem; line-height: 1.15; text-align: left; transition: background-color 0.15s, color 0.15s; }
.filter b { display: block; font-weight: 500; }
.filter span { font-size: 0.9375rem; font-style: italic; }
.filter button[aria-pressed="true"] { background: var(--house-2); color: var(--ink); }
.filter .filter__accio { border-style: dashed; }

.wish-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); gap: clamp(1rem, 2.5vw, 2rem); margin: 0; padding: 0; list-style: none; }
.wish__card {
  --focus: var(--wax);
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.45rem;
  height: 100%;
  padding: 1.1rem 1.25rem 1.25rem;
  color: var(--ink);
  background: linear-gradient(170deg, #f0e0ba, var(--parchment) 40%, #e0c998);
  box-shadow: inset 0 0 0 1.5px var(--line), inset 0 0 0 5px var(--parchment), inset 0 0 0 6px var(--line);
  animation: levitate 5.6s ease-in-out infinite alternate;
}
.wish:nth-child(2n) .wish__card { animation-delay: -1.8s; animation-duration: 6.4s; }
.wish:nth-child(3n) .wish__card { animation-delay: -3.3s; animation-duration: 5s; }
@keyframes levitate { from { transform: translateY(-3px) rotate(-0.25deg); } to { transform: translateY(4px) rotate(0.25deg); } }
.wish__portrait { display: grid; place-items: center; width: 100%; aspect-ratio: 4 / 3; overflow: hidden; border-radius: 50% 50% 4px 4px / 34% 34% 4px 4px; border: 3px double var(--line); background: #efdfba; }
.wish__portrait img { width: 100%; height: 100%; object-fit: contain; mix-blend-mode: multiply; animation: portrait 8s ease-in-out infinite alternate; }
@keyframes portrait { from { transform: scale(1) translateX(-1%); } to { transform: scale(1.06) translateX(1%); } }
.wish__moon { width: 32%; fill: var(--parchment-deep); }
.wish__title { margin-top: 0.4rem; font-size: 1.55rem; line-height: 1.12; }
.wish__price { font-size: 1.3125rem; font-weight: 500; color: var(--wax); }
.wish__price span { display: block; font-size: 1rem; font-weight: 400; font-style: italic; color: var(--ink); }
.wish__note { font-style: italic; line-height: 1.3; }
.wish__shop { min-height: 32px; font-weight: 500; }
.wish__status { font-style: italic; color: var(--wax); margin-top: auto; }
.wish__card .btn { margin-top: auto; }
.wish__card .wish__status + .btn { margin-top: 0.25rem; }
.wish.is-summoned .wish__card { animation: summoned 2.2s ease-in-out; }
@keyframes summoned { 0%, 100% { box-shadow: inset 0 0 0 1.5px var(--line), 0 0 0 0 #ffd36a00; } 30%, 70% { box-shadow: inset 0 0 0 1.5px var(--line), 0 0 44px 12px #ffd36acc; transform: scale(1.03); } }
.wishes__empty { padding: 2rem 0 3rem; font-style: italic; }

.seal { position: absolute; top: 1.4rem; right: 1rem; z-index: 2; width: 104px; visibility: hidden; transform: rotate(-11deg); }
.seal__wax { fill: var(--wax); }
.seal__ring { fill: none; stroke: #c9505f; stroke-width: 1.5; }
.seal__text { fill: #fff4dc; font: 19px var(--display); }
.is-taken .seal { visibility: visible; }
.is-taken .wish__portrait { opacity: 0.6; }
.is-sealing .seal { animation: stamp 0.34s cubic-bezier(0.2, 0.9, 0.3, 1.15); }
.is-preseal .seal { visibility: hidden; }
@keyframes stamp { from { opacity: 0; transform: scale(2) rotate(-26deg); } to { opacity: 1; transform: scale(1) rotate(-11deg); } }

.courier { position: fixed; left: 0; top: 0; z-index: 40; width: 200px; pointer-events: none; will-change: transform; }
.flying-letter { position: fixed; left: 0; top: 0; z-index: 41; width: clamp(64px, 12vw, 112px); pointer-events: none; will-change: transform; }
.courier .art, .flying-letter .art, .patronus .art { height: auto; }

/* house cup */
.cup { max-width: 880px; margin: 0 auto; padding: 4rem 1rem 1rem; text-align: center; }
.cup__rules { max-width: 36em; margin: 0.6rem auto 0; }
.cup__glasses { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.5rem; margin-top: 1.75rem; }
.glass { display: grid; justify-items: center; gap: 0.2rem; }
.glass[data-house="gryffindor"] { --g: #c8283c; } .glass[data-house="slytherin"] { --g: #27a05c; }
.glass[data-house="ravenclaw"] { --g: #3f6be0; } .glass[data-house="hufflepuff"] { --g: #f0c32f; }
.glass__tube { position: relative; display: flex; align-items: flex-end; width: min(19vw, 96px); height: clamp(150px, 34vw, 210px); overflow: hidden; background: #ffffff1c; clip-path: polygon(6% 0, 94% 0, 94% 22%, 60% 50%, 94% 78%, 94% 100%, 6% 100%, 6% 78%, 40% 50%, 6% 22%); }
.glass__tube i { display: block; width: 100%; height: 3%; background-color: var(--g); background-image: radial-gradient(circle at 30% 30%, #fff8 1.5px, transparent 2px), radial-gradient(circle at 70% 60%, #fff6 1.5px, transparent 2px); background-size: 11px 11px, 14px 14px; transition: height 1.1s cubic-bezier(0.3, 1, 0.4, 1); }
.glass b { font: 1.0625rem/1.15 var(--display); font-weight: 400; }
.glass span { font-size: 1.3125rem; color: var(--gold); }
.glass.is-mine b { color: var(--house-2); text-decoration: underline; text-underline-offset: 3px; }
@media (max-width: 420px) { .glass b { font-size: 0.875rem; } }

/* marauder-style map */
.map { max-width: 820px; margin: 0 auto; padding: 4rem 1rem 3rem; }
.map h2 { text-align: center; }
.map__sheet { --focus: var(--wax); margin-top: 1.25rem; padding: 1.75rem 1.25rem; color: var(--ink); background: linear-gradient(170deg, #efdfba, var(--parchment) 45%, #dcc493); box-shadow: inset 0 0 40px #8a6a3555; }
.map__blank { display: grid; justify-items: center; gap: 1rem; padding: 2.5rem 0; text-align: center; font: 1.5rem/1.2 var(--script); }
.map__blank .btn { font-family: var(--text); }
@property --reveal { syntax: "<percentage>"; inherits: false; initial-value: 0%; }
.map__ink { animation: ink 1.6s ease-out both; -webkit-mask-image: radial-gradient(circle at 50% 30%, #000 var(--reveal), transparent calc(var(--reveal) + 12%)); mask-image: radial-gradient(circle at 50% 30%, #000 var(--reveal), transparent calc(var(--reveal) + 12%)); }
@keyframes ink { from { --reveal: 0%; } to { --reveal: 170%; } }
.map__title { font: 1.5rem/1.2 var(--script); text-align: center; color: var(--emerald); }
.map-art { display: block; width: 100%; height: auto; margin-top: 0.75rem; }
.map-art__walls path { stroke-dasharray: 1; stroke-dashoffset: 1; animation: draw 2.2s ease-in-out 0.3s forwards; }
@keyframes draw { to { stroke-dashoffset: 0; } }
.foot-step { fill: #3a2a1a; opacity: 0; animation: step 7s linear infinite; }
@keyframes step { 0% { opacity: 0; } 3% { opacity: 0.85; } 34% { opacity: 0.85; } 45%, 100% { opacity: 0; } }
.map__info { margin-top: 0.75rem; }
.map__when { font: 2rem/1.1 var(--display); color: var(--wax); }
.map__place { margin-top: 0.35rem; font-size: 1.3125rem; }
.map__details { margin-top: 0.5rem; font-style: italic; }
.map__going { margin-top: 0.5rem; color: var(--emerald); font: 1.4rem/1.15 var(--script); }
.map__form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 1rem; margin-top: 1.25rem; }
.map__form .field { flex: 1 1 14rem; }
.map__form .field--short { flex: 0 1 9rem; }
.map__done { margin-top: 1.25rem; }
.js-map-close { margin-top: 0.75rem; }

.field label { display: block; margin-bottom: 0.25rem; font-weight: 500; }
.field input, .field textarea { width: 100%; min-height: 48px; padding: 0.5rem 0.75rem; border: 1.5px solid var(--ink); border-radius: 4px; background: #f6eacd; color: var(--ink); font: inherit; }
.field__help { margin-top: 0.35rem; font-size: 1rem; font-style: italic; line-height: 1.3; }
.field__error { flex-basis: 100%; color: var(--wax); font-weight: 500; }

.sheet { --focus: var(--wax); width: min(92vw, 440px); padding: 1.75rem; border: 0; border-radius: 4px; color: var(--ink); background: var(--parchment); }
.sheet::backdrop { background: rgba(10, 12, 40, 0.78); }
.sheet h2 { font-size: 1.85rem; }
.sheet__item { margin: 0.5rem 0 1.25rem; font-style: italic; }
.sheet .field__error { margin-top: 0.75rem; }
.sheet__actions { display: flex; flex-wrap: wrap; gap: 1.25rem; margin-top: 0.75rem; }

.toast { position: fixed; left: 50%; bottom: max(1.25rem, env(safe-area-inset-bottom)); z-index: 45; translate: -50% 0; width: max-content; max-width: calc(100vw - 6.5rem); padding: 0.7rem 1.1rem; border: 1.5px solid var(--house-2); border-radius: 4px; background: var(--night-up); color: var(--parchment); line-height: 1.25; }

/* canvas sparks and effects */
.sparks { position: fixed; inset: 0; z-index: 50; width: 100%; height: 100%; pointer-events: none; }
.nox { position: fixed; inset: 0; z-index: 30; pointer-events: none; background: radial-gradient(circle 190px at var(--x, 50%) var(--y, 40%), transparent 0, transparent 35%, rgba(3, 4, 22, 0.95) 100%); }
.patronus { position: fixed; left: 0; top: 0; z-index: 42; width: min(70vw, 420px); pointer-events: none; color: #d9ecff; filter: drop-shadow(0 0 8px #bfe0ff) drop-shadow(0 0 26px #8fc5ff); }
.patronus .art path { fill: currentColor; }
.snitch-fly { position: fixed; left: 0; top: 0; z-index: 44; width: 76px; height: 46px; padding: 0; border: 0; background: none; will-change: transform; }
.snitch-fly::before { content: ""; position: absolute; inset: -14px; }
body.is-levitating .vit__cell .art, body.is-levitating .wish__card, body.is-levitating h2 { animation: leviosa 2.8s ease-in-out both !important; }
@keyframes leviosa { 0%, 100% { transform: none; } 25%, 75% { transform: translateY(-26px) rotate(-1.5deg); } 50% { transform: translateY(-34px) rotate(1.5deg); } }

.spells { position: fixed; right: 14px; bottom: max(14px, env(safe-area-inset-bottom)); z-index: 46; display: grid; justify-items: end; gap: 0.5rem; }
.spells__fab { width: 58px; height: 58px; padding: 11px; border: 1.5px solid var(--house-2); border-radius: 50%; background: var(--night-up); box-shadow: 0 6px 18px #0008; }
.spells__menu { display: grid; gap: 0.3rem; width: min(78vw, 290px); padding: 0.5rem; border: 1.5px solid var(--house-2); border-radius: 8px; background: var(--night-deep); animation: menu-in 0.18s ease-out; }
@keyframes menu-in { from { opacity: 0; transform: translateY(8px); } }
.spells__menu button { min-height: 50px; padding: 0.3rem 0.7rem; border: 0; border-radius: 4px; background: none; color: var(--parchment); font: inherit; line-height: 1.15; text-align: left; }
.spells__menu button:hover { background: var(--night-up); }
.spells__menu b { display: block; font-weight: 500; font-size: 1.125rem; }
.spells__menu span { font-size: 0.9375rem; font-style: italic; opacity: 0.85; }

.foot { max-width: 44em; margin: 0 auto; padding: 1rem 5rem 5.5rem 1rem; font-size: 1rem; font-style: italic; opacity: 0.8; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .map-art__walls path { stroke-dashoffset: 0; }
  .env { opacity: 1; }
  .hat__mouth { transform: scaleY(0.6); }
  .owl__lids { transform: scaleY(0); }
  .map__ink { -webkit-mask-image: none; mask-image: none; }
  .foot-step { opacity: 0.85; }
  .potion__bubble, .glasses__glint { opacity: 0; }
}
