@font-face { font-family: 'Garet'; src: url(/fonts/Garet-Book.woff2) format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'Garet'; src: url(/fonts/Garet-Heavy.woff2) format('woff2'); font-weight: 800; font-display: swap; }

:root {
  /* Page: deep forest green so the gold title and seals read as light. */
  --bg: #253020;
  --on-bg: #EEF0E4;
  --on-bg-soft: #AEBCA0;
  --on-bg-line: #C9D6B5;
  --paper: #E5ECDC;
  --pearl: #FBFAF5;
  --satin: #A8BB95;
  --satin-deep: #8EA47B;
  --olive: #6B7A4F;
  --ink: #36422A;
  --ink-soft: #5D6950;
  --gold: #B8954A;
  --sans: 'Garet', 'Helvetica Neue', Arial, sans-serif;
  color-scheme: light;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

/* Each screen fits the phone's visible height: header on top, the screen fills the rest,
   and the envelope and poster shrink to whatever room is left. */
html { background: var(--bg); }
body {
  margin: 0;
  /* The ribbon runs to the screen edges; never let it make the page scroll sideways. */
  overflow-x: clip;
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--on-bg);
  font: 400 16px/1.6 var(--sans);
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}

main {
  flex: 1;
  min-height: 0;
  width: 100%;
  max-width: 440px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  padding: 6px 20px calc(14px + env(safe-area-inset-bottom));
}
.screen { flex: 1; min-height: 0; display: flex; flex-direction: column; }

/* Logo pieces are alpha masks so they take the olive ink. */
.logo, .wordmark, .mark {
  display: block;
  background: currentColor;
  -webkit-mask: var(--src) center / contain no-repeat;
  mask: var(--src) center / contain no-repeat;
}
.wordmark { --src: url(/brand/wordmark.png); width: 112px; aspect-ratio: 480 / 59; color: var(--olive); }
.mark { --src: url(/brand/mark.png); aspect-ratio: 1; }
.logo { --src: url(/brand/logo.png); width: 92px; aspect-ratio: 480 / 359; color: var(--on-bg-line); }

.top {
  max-width: 440px;
  margin: 0 auto;
  flex: none;
  width: 100%;
  padding: calc(12px + env(safe-area-inset-top)) 20px 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  /* Sits above the envelope flap when it swings open. */
  position: relative;
  z-index: 5;
}
.top .logo { width: 52px; }
/* The occasion on a silk sash (drawn by scripts/build-ribbon.mjs) that runs edge to edge across the
   first page, like the ribbon on a gift box. It draws across as the page opens, then a gleam runs
   along it now and then. Only the first page shows it. */
.banner {
  position: relative;
  display: block;
  flex: none;
  width: min(100vw, 520px);
  margin-top: 6px;
  filter: drop-shadow(0 0 16px rgba(240, 213, 146, .22)) drop-shadow(0 5px 6px rgba(0, 0, 0, .35));
}
/* The sash itself draws across; its glow comes from the parent, so the glow follows the leading edge. */
.banner > * { animation: draw-across 1.1s cubic-bezier(.6, 0, .2, 1) .1s backwards; }
body:has(#intro[hidden]) .banner { display: none; }
.banner img { display: block; width: 100%; height: auto; }
.banner-shine {
  position: absolute;
  inset: 0;
  overflow: hidden;
  -webkit-mask: url(/ribbon.svg) 0 0 / 100% 100% no-repeat;
  mask: url(/ribbon.svg) 0 0 / 100% 100% no-repeat;
}
.banner-shine::before {
  content: '';
  position: absolute;
  top: 0; bottom: 0; left: 0;
  width: 22%;
  background: linear-gradient(100deg, rgba(255, 250, 232, 0), rgba(255, 250, 232, .7) 50%, rgba(255, 250, 232, 0));
  transform: translateX(-110%);
  animation: gleam 6s cubic-bezier(.45, 0, .25, 1) 1.3s infinite;
}
@keyframes draw-across { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0); } }
@keyframes gleam { 0% { transform: translateX(-110%); } 24%, 100% { transform: translateX(500%); } }

h1 {
  font: 400 clamp(36px, 10.5vw, 44px)/1.04 var(--sans);
  letter-spacing: -0.01em;
  margin: 28px 0 14px;
  text-wrap: balance;
}
.lede { margin: 0 0 28px; color: var(--on-bg-soft); max-width: 36ch; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.fine { font-size: 12px; color: var(--on-bg-soft); margin: 6px 0 0; text-align: center; }

.cta {
  display: block;
  width: 100%;
  min-height: 52px;
  padding: 0 24px;
  border: 0;
  border-radius: 999px;
  background: var(--ink);
  color: var(--pearl);
  font: 400 17px var(--sans);
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: background-color .15s, opacity .15s;
}
.cta:hover:not(:disabled) { background: #2B3521; }
.cta:disabled { opacity: .35; cursor: default; }
.cta.ghost { flex: none; margin-top: 12px; background: none; color: var(--on-bg); box-shadow: inset 0 0 0 1.5px rgba(201, 214, 181, .45); }
.cta.ghost:hover:not(:disabled) { background: rgba(238, 240, 228, .07); }
.cta[aria-busy="true"] { opacity: .7; }

:focus-visible { outline: 3px solid var(--gold); outline-offset: 3px; }

/* ---------- Start: lane + envelope ---------- */

/* The stage shares the lane SVG's 400×480 coordinate space, so the
   envelope's percentages line up with the trail and sparkles. */
.stage-wrap { display: grid; place-items: center; }
.stage { position: relative; width: 100%; aspect-ratio: 400 / 480; }
/* Fit the stage to the free height. Older phones (before iOS 16 / Chrome 105) skip this
   and get the full-width stage, scrolling a little. */
@supports (width: 1cqw) {
  .stage-wrap { flex: 1; min-height: 0; container-type: size; }
  .stage { width: min(100cqw, 100cqh * 400 / 480); }
  /* The letter's words scale with the envelope, so they stay inside it when a short screen shrinks it. */
  .envelope { container-type: inline-size; }
  .envelope .letter-note { font-size: min(22px, 8.4cqw); }
  .envelope .letter-sign { font-size: min(14px, 5.6cqw); }
  .envelope .letter .foil { width: min(100px, 38cqw); }
}
.stage::before {
  content: '';
  position: absolute;
  left: 0; right: 0; top: 38%; height: 66%;
  background: radial-gradient(closest-side, rgba(214, 228, 188, .2), rgba(214, 228, 188, 0));
}

.lane { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; z-index: 6; pointer-events: none; }
/* Title: fixed gold-foil letter shapes from scripts/build-title.mjs, so every phone lays it out the same.
   Each letter is its own element and the glow is one pre-blurred layer, so the motion runs on the GPU. */
.title { position: absolute; inset: 0; z-index: 6; pointer-events: none; transition: opacity .3s; }
.title .ch { position: absolute; overflow: visible; }
/* Garet ships in Book and Heavy only; a same-gold outline gives a weight just above Book. */
.title .ch path { fill: url(#title-gold); stroke: url(#title-gold); stroke-width: 1.4px; stroke-linejoin: round; }
.title-halo { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; fill: #F3DFA6; opacity: .4; filter: blur(4px); will-change: opacity; }
.title[data-walk] .title-halo { animation: fade-in .8s ease 1.2s backwards, breathe 3.8s ease-in-out 2.6s infinite; }
@keyframes breathe { 50% { opacity: .22; } }
#intro[data-hold] .title-halo, #intro:not([data-state="closed"]) .title-halo { animation-play-state: paused; }

/* Each letter steps down onto the lane, one after another. */
.title[data-walk] .ch {
  transform-origin: 50% 100%;
  animation: step .7s cubic-bezier(.2, .9, .25, 1.15) calc(.2s + var(--i) * 55ms) both;
}
@keyframes step {
  from { opacity: 0; transform: translateY(-18px) rotate(-12deg) scale(.9); }
  60% { opacity: 1; }
}

/* Once the letters land, a soft band of light crosses them, cut to the letters' shape. */
.title-shine {
  position: absolute;
  inset: 0;
  overflow: hidden;
  -webkit-mask: url(/title.svg) 0 0 / 100% 100% no-repeat;
  mask: url(/title.svg) 0 0 / 100% 100% no-repeat;
}
.title-shine::before {
  content: '';
  position: absolute;
  top: 0; bottom: 0; left: 0;
  width: 40%;
  background: linear-gradient(90deg, rgba(255, 248, 228, 0), rgba(255, 248, 228, .9) 50%, rgba(255, 248, 228, 0));
  transform: translateX(-100%);
}
.title[data-walk] .title-shine::before { animation: sweep 1.6s cubic-bezier(.45, 0, .25, 1) 1.5s both; }
@keyframes sweep { to { transform: translateX(250%); } }

.trail-reveal { fill: none; stroke: #fff; stroke-width: 12; stroke-dasharray: 1; stroke-dashoffset: 0; }
.lane[data-walk] .trail-reveal { stroke-dashoffset: 1; animation: draw 1s cubic-bezier(.4, 0, .2, 1) 1.35s forwards; }
@keyframes draw { to { stroke-dashoffset: 0; } }
.lane[data-walk] .spark { animation: fade-in .8s ease 1.1s backwards; }

.trail {
  fill: none;
  stroke: #C29A48;
  stroke-width: 3;
  stroke-linecap: round;
  stroke-dasharray: 0.1 11;
}
.spark.olive { fill: var(--on-bg-line); opacity: .7; }
.spark.gold { fill: var(--gold); }
.lane { transition: opacity .3s; }
@keyframes fade-in { from { opacity: 0; } }
@keyframes settle { from { opacity: 0; translate: 0 26px; } }

.envelope {
  position: absolute;
  left: 8%; width: 84%; top: 50%;
  aspect-ratio: 1.5;
  perspective: 900px;
  rotate: -3deg;
  transition: rotate .5s cubic-bezier(.3, 0, .2, 1);
  animation: settle .9s cubic-bezier(.2, .8, .2, 1) .5s backwards;
}
.envelope > span, .envelope > svg, .envelope > button { position: absolute; display: block; }

.env-back {
  inset: 0;
  background: var(--satin-deep);
  border-radius: 6px;
  box-shadow: 0 34px 44px -24px rgba(0, 0, 0, .55);
}
/* The letter is dark olive card stock with gilt edges: fine grain, soft light from the top left.
   It reads as a note rather than a greeting card: the message set left, signed with the foil wordmark. */
.letter {
  left: 7%; right: 7%; top: 5%; height: 88%;
  z-index: 1;
  display: flex !important;
  flex-direction: column;
  justify-content: space-between;
  padding: 8% 9% 7%;
  border: 1.5px solid transparent;
  border-radius: 3px;
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 .97 0 0 0 0 .88 0 0 0 .09 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E") padding-box,
    repeating-linear-gradient(90deg, rgba(255, 255, 255, .012) 0 1px, transparent 1px 3px) padding-box,
    radial-gradient(120% 90% at 22% 0%, #485A38, #34412A 55%, #2B3622) padding-box,
    linear-gradient(115deg, #8F6F2F, #E6CD8E 38%, #B8954A 62%, #8F6F2F) border-box;
  box-shadow: 0 2px 3px rgba(20, 26, 14, .35), 0 24px 40px -18px rgba(10, 14, 8, .6);
  will-change: transform;
}
.letter-note {
  max-width: 9em;
  font-size: clamp(19px, 5.9vw, 23px);
  line-height: 1.12;
  text-wrap: balance;
  color: #F3EFE2;
  text-shadow: 0 1px 0 rgba(0, 0, 0, .4);
}
.letter-sign {
  align-self: flex-end;
  display: flex !important;
  flex-direction: column;
  align-items: flex-end;
  font-size: clamp(12px, 3.6vw, 14px);
  line-height: 1.3;
  color: #B7C6A4;
}
.letter .foil {
  width: clamp(88px, 27vw, 108px);
  margin-top: 3px;
  background: linear-gradient(105deg, #A9843D 0%, #D9BE7C 30%, #FFF1C9 45%, #D3B26A 58%, #A9843D 100%) 100% 0 / 260% 100%;
  filter: drop-shadow(0 1px 0 rgba(0, 0, 0, .35));
}
/* The foil wordmark catches the light once the letter is in front. */
#intro:not([data-state="closed"]) .letter .foil { animation: foil .8s ease-in-out 2.2s both; }
@keyframes foil { from { background-position: 100% 0; } to { background-position: 0 0; } }

.env-pocket {
  inset: 0;
  border-radius: 6px;
  z-index: 2;
  /* Side flaps run to the top corners so the closed envelope hides the letter. */
  background:
    linear-gradient(to top right, #A0B58C 50%, transparent 50.3%) left / 50% 100% no-repeat,
    linear-gradient(to top left, #A0B58C 50%, transparent 50.3%) right / 50% 100% no-repeat,
    var(--satin);
  clip-path: polygon(0 0, 50% 60%, 100% 0, 100% 100%, 0 100%);
}
.env-flap {
  left: 0; right: 0; top: 0; height: 63%;
  background: #B7C9A4;
  clip-path: polygon(0 0, 100% 0, 50% 100%);
  border-radius: 6px 6px 0 0;
  transform-origin: top;
  transition: transform .5s cubic-bezier(.5, 0, .3, 1), z-index 0s .25s;
  z-index: 3;
  will-change: transform;
}

/* Satin ribbon wrapped round the envelope, tied in a bow on the top edge. */
.ribbon {
  left: 22%; width: 10%; top: 0; bottom: 0;
  z-index: 3;
  background: linear-gradient(90deg, #758B5E, #B7C9A2 32%, #8DA377 58%, #A9BC93 84%, #758B5E);
  box-shadow: 0 0 0 .5px rgba(84, 104, 64, .25);
  transform-origin: bottom;
  transition: transform .4s cubic-bezier(.5, 0, .7, .4), opacity .4s;
}
.bow {
  left: 27%; top: -20%;
  width: 34%;
  translate: -50% 0;
  z-index: 5;
  filter: drop-shadow(0 4px 5px rgba(54, 66, 42, .3));
  transition: transform .4s cubic-bezier(.5, 0, .7, .4), opacity .35s;
}

/* The seal is the button: press and hold to break it. */
.seal {
  left: 50%; top: 60%;
  width: 19%; aspect-ratio: 1;
  translate: -50% -50%;
  padding: 0;
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  background: radial-gradient(circle at 35% 30%, #CDAE66, var(--gold) 55%, #9C7C38);
  box-shadow: 0 2px 0 #8C6F31, 0 6px 14px rgba(84, 66, 24, .28);
  color: #F6EED9;
  z-index: 4;
  transition: transform .25s, opacity .25s;
}
.seal:disabled { cursor: default; }
.seal .mark { position: absolute; inset: 21%; pointer-events: none; }
.seal:not(:disabled):hover { transform: rotate(-8deg); }

/* Soft halo inviting a touch. */
.seal::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  box-shadow: 0 0 0 7px rgba(184, 149, 74, .4);
  opacity: 0;
  animation: halo 2.6s ease-out 2.4s infinite;
}
.seal:disabled::before, #intro[data-hold] .seal::before { animation: none; }
@keyframes halo {
  0% { transform: scale(.9); opacity: 1; }
  75%, 100% { transform: scale(1.3); opacity: 0; }
}

/* Hold progress: fills over 1s, matching HOLD_MS in app.js. */
.ring { position: absolute; inset: -22%; width: 144%; height: 144%; rotate: -90deg; overflow: visible; pointer-events: none; }
.ring circle { fill: none; stroke-width: 4; stroke-linecap: round; }
.ring .track { stroke: rgba(184, 149, 74, .22); opacity: 0; transition: opacity .2s; }
.ring .fill { stroke: var(--gold); stroke-dasharray: 100; stroke-dashoffset: 100; transition: stroke-dashoffset .25s ease-out; }
#intro[data-hold] .ring .track { opacity: 1; }
#intro[data-hold] .ring .fill { stroke-dashoffset: 0; transition: stroke-dashoffset 1s linear; }
#intro[data-hold] .seal { transform: scale(.92); }


.hint {
  margin: 0;
  text-align: center;
  font-size: 14px;
  color: var(--on-bg-soft);
  transition: opacity .3s;
}
.hint.nudge { animation: nudge .4s ease; }
@keyframes nudge { 25% { translate: -5px 0; } 50% { translate: 4px 0; } 75% { translate: -2px 0; } }

/* Opening, in order: ribbon falls, seal lifts, envelope straightens, flap opens, letter rises. */
#intro:not([data-state="closed"]) .lane,
#intro:not([data-state="closed"]) .title,
#intro:not([data-state="closed"]) .hint,
#intro:not([data-state="closed"]) .treats { opacity: 0; }
#intro:not([data-state="closed"]) .ribbon { transform: translateY(14%) scaleY(.9); opacity: 0; }
#intro:not([data-state="closed"]) .bow { transform: translateY(30%) rotate(-24deg) scale(.5); opacity: 0; }
#intro:not([data-state="closed"]) .seal { transform: scale(1.3); opacity: 0; }
#intro:not([data-state="closed"]) .envelope { rotate: 0deg; transition-delay: .2s; }
#intro:not([data-state="closed"]) .env-flap { transform: rotateX(180deg); z-index: 0; transition-delay: .4s, .65s; }
/* The letter rises clear of the pocket, then comes forward to be read while the envelope falls away. */
#intro:not([data-state="closed"]) .letter { animation: letter-out 1.5s cubic-bezier(.45, 0, .25, 1) .7s both; }
/* Set by app.js once the letter has cleared the pocket. Kept out of the keyframes so the animation stays transform-only. */
#intro[data-front] .letter { z-index: 4; }
#intro:not([data-state="closed"]) :is(.env-back, .env-pocket, .env-flap) { animation: env-away .6s cubic-bezier(.4, 0, .6, 1) 1.5s both; }
@keyframes letter-out {
  48% { transform: translateY(-112%); }
  100% { transform: translateY(-24%) scale(1.14) rotate(-1.5deg); }
}
@keyframes env-away { to { translate: 0 18%; opacity: 0; } }


/* How it works: seals grow with the score along a dotted lane. */
.treats { margin: 12px 0 0; text-align: center; transition: opacity .3s; }
.treats h2 { margin: 0 auto 10px; font: 400 21px/1.2 var(--sans); text-wrap: balance; }
.treat-lane {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  margin: 0;
  padding: 0;
  list-style: none;
}
.treat-lane::before {
  content: '';
  position: absolute;
  left: 16%; right: 16%; top: 22px; height: 4px;
  translate: 0 -50%;
  background: radial-gradient(circle, var(--on-bg-line) 1.3px, transparent 1.7px) 0 50% / 11px 4px repeat-x;
  opacity: .5;
}
.treat-lane li {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  font-size: 13px;
  color: var(--on-bg-soft);
}
.treat-lane li:last-child { color: var(--on-bg); font-weight: 800; }
.medal {
  position: relative;
  display: block;
  width: var(--s);
  aspect-ratio: 1;
  margin-top: calc((44px - var(--s)) / 2);
  margin-bottom: calc((44px - var(--s)) / 2);
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #CDAE66, var(--gold) 55%, #9C7C38);
  box-shadow: 0 2px 0 #8C6F31, 0 5px 12px rgba(84, 66, 24, .22);
  color: #F6EED9;
}
.medal .gift { position: absolute; inset: 16%; width: 68%; height: 68%; }
.treats p { margin: 8px auto 0; font-size: 14px; line-height: 1.4; color: var(--on-bg-soft); text-wrap: balance; }

/* ---------- Quiz ---------- */

#quiz { justify-content: center; }
.sheet {
  margin-top: 4px;
  color: var(--ink);
  background: var(--pearl);
  border-radius: 24px;
  padding: 20px 18px 18px;
  box-shadow: 0 1px 2px rgba(54, 66, 42, .1), 0 18px 40px -24px rgba(54, 66, 42, .35);
}
.progress { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.progress i { height: 3px; border-radius: 2px; background: #DCE4D1; transition: background-color .3s; }
.progress i.done { background: var(--olive); }
.step { margin: 10px 0 0; font-size: 13px; color: var(--ink-soft); }

fieldset { border: 0; margin: 0; padding: 0; min-width: 0; }
.question {
  padding: 0;
  margin: 4px 0 16px;
  font: 400 clamp(16px, calc(3.4dvh - 2px), 21px)/1.22 var(--sans);
  text-wrap: pretty;
}
.options { display: grid; gap: 8px; margin-bottom: 18px; }
.option { position: relative; display: block; cursor: pointer; }
.option input { position: absolute; opacity: 0; inset: 0; margin: 0; cursor: pointer; }
.option span {
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 54px;
  padding: 8px 14px;
  border: 1.5px solid #D5DECA;
  border-radius: 12px;
  font-size: 17px;
  line-height: 1.35;
  transition: border-color .15s, background-color .15s, color .15s;
}
.option span::before {
  content: attr(data-letter);
  flex: none;
  display: grid;
  place-items: center;
  width: 32px; height: 32px;
  border-radius: 50%;
  border: 1.5px solid #C5D1B7;
  font-size: 14px;
  font-weight: 500;
  color: var(--olive);
}
.option:hover span { border-color: var(--satin); }
.option input:checked + span { background: var(--ink); border-color: var(--ink); color: var(--pearl); }
.option input:checked + span::before { background: var(--pearl); border-color: var(--pearl); color: var(--ink); }
.option input:focus-visible + span { outline: 3px solid var(--gold); outline-offset: 2px; }

.error { margin: -10px 0 16px; font-size: 15px; color: #8A3B2C; }
/* Very short screens (small phones with browser bars): tighter answers so the whole question still fits. */
@media (max-height: 560px) {
  .sheet { padding: 16px 16px 14px; }
  .question { margin-bottom: 12px; }
  .options { gap: 6px; margin-bottom: 14px; }
  .option span { min-height: 46px; padding: 6px 12px; font-size: 15px; }
  .option span::before { width: 28px; height: 28px; }
  .sheet .cta { min-height: 46px; }
}

/* ---------- Result ---------- */


/* The poster takes whatever height the note and button leave, keeping its shape. */
.poster { flex: 1; min-height: 0; margin: 0; display: flex; justify-content: center; }
.poster img, .typeset {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  aspect-ratio: 1020 / 1510;
  border-radius: 16px;
  box-shadow: 0 22px 44px -26px rgba(54, 66, 42, .55);
}
.poster img { object-fit: cover; background: #DDE6D2; }
.typeset { height: 100%; }

/* Stand-in poster for results without artwork yet (0/3). */
.typeset {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 12% 9% 9%;
  background: #E3EBD8;
  text-align: center;
  color: var(--ink);
}
.typeset .wordmark { width: 42%; }
.ts-sub { margin-top: 6px; font-size: 12px; letter-spacing: .2em; color: var(--ink-soft); }
.ts-score {
  margin-top: 9%;
  padding: 6px 26px;
  border: 1.5px solid var(--satin-deep);
  border-radius: 999px;
  font-size: 15px;
  letter-spacing: .04em;
}
.ts-head { margin-top: 6%; font: 400 clamp(38px, 12vw, 52px)/1.05 var(--sans); }
.ts-mark { width: 34%; margin: auto 0; color: var(--satin-deep); }
.ts-prize {
  width: 100%;
  padding: 8% 6%;
  border-radius: 999px;
  background: var(--pearl);
  box-shadow: 0 0 0 6px rgba(168, 187, 149, .45);
}
.ts-prize b { display: block; font: 800 clamp(22px, 6.6vw, 28px)/1.15 var(--sans); }
.ts-prize span { display: block; margin-top: 4px; font-size: 14px; letter-spacing: .08em; color: var(--ink-soft); }
.typeset.no-prize .ts-prize { background: none; box-shadow: none; }
.typeset.no-prize .ts-prize b { font: 400 20px/1.4 var(--sans); color: var(--ink-soft); }

/* Under the poster: the note for the beautician, then when it was won, small. */
#result { padding-top: calc(8px + env(safe-area-inset-top)); }
.claim { flex: none; margin-top: 16px; text-align: center; }
.claim-note { margin: 0; font-size: 17px; line-height: 1.35; color: var(--on-bg); }
.claim-time { margin: 4px 0 0; font-size: 13px; color: var(--on-bg-soft); }

/* ---------- Invalid link ---------- */

.invalid { padding-top: 12vh; }
.invalid .logo { width: 120px; margin-bottom: 36px; }

.invalid h1 { margin-top: 0; }

/* ---------- Motion ---------- */

.screen.enter { animation: rise .55s cubic-bezier(.2, .8, .2, 1) both; }
#result.enter .claim { animation: rise .55s cubic-bezier(.2, .8, .2, 1) .25s both; }
@keyframes rise { from { opacity: 0; transform: translateY(18px); } }
