/* The room. Paper Pine, version 2: see docs/style-sheet.html (the reference) and docs/DESIGN.md.
   Everything inside .stage is placed by percentage and sized in cqw, so it is correct at any width.
   Animate transform and opacity only. */

.stage {
  /* scene constants: the room has its own light, independent of the app theme */
  --wall: #3B4856;  --wall-2: #2A3541;
  --floor: #5B3E2B; --floor-2: #43301F;
  --pine: #3E6B4F;  --pine-2: #2F5742;  --trunk: #6B4A33;
  --cream: #EFE6D0; --snow: #F4F7FB;
  /* time of day: --lit scales the fire and tree glow, --vig the dark edges, --lights the string lights */
  --lit: 1; --vig: 0.55; --lights: 1;
  /* arrival distances: cqw, so the same keyframes work at any size */
  --fall: 32cqw; --sx: 3cqw; --rise: 3cqw;

  position: relative;
  aspect-ratio: 16 / 10;
  width: 100%;
  max-width: 100%;
  container-type: inline-size;
  overflow: hidden;
  background: var(--wall);
  isolation: isolate;
  border-radius: 6px;
}
.stage .wall {
  position: absolute; inset: 0 0 32% 0;
  background:
    repeating-linear-gradient(90deg, rgba(255,255,255,0.03) 0 2.2cqw, transparent 2.2cqw 4.4cqw),
    linear-gradient(180deg, var(--wall-2) 0%, var(--wall) 100%);
}
.stage .floor {
  position: absolute; inset: 68% 0 0 0;
  background:
    repeating-linear-gradient(180deg, transparent 0 3.3cqw, rgba(0,0,0,0.22) 3.3cqw 3.42cqw),
    linear-gradient(180deg, var(--floor-2) 0%, var(--floor) 75%);
}
.stage .skirting {
  position: absolute; left: 0; right: 0; top: 67.2%;
  height: 1.5cqw;
  background: linear-gradient(180deg, #6A5340 0 12%, #4F3B2B 12% 100%);
  box-shadow: 0 0.5cqw 0.8cqw rgba(0,0,0,0.35);
}

/* things placed on the stage address their own centre */
.stage .place { position: absolute; translate: -50% -50%; line-height: 0; }
.stage .tree-wrap { left: 50%; top: 42%; width: 40cqw; }
.stage .fire-wrap { left: 82%; top: 55.5%; width: 25cqw; }
.stage .fire-wrap svg { width: 100%; height: auto; display: block; }
.stage .garland   { left: 25%; top: 12%; width: 44cqw; aspect-ratio: 400 / 90; }
.stage .win       { top: 36%; width: 13cqw; }
.stage .win-a     { left: 11%; }
.stage .win-b     { left: 28%; }

.stage .deco { width: calc(4.6cqw * var(--s, 1)); cursor: default; }
.stage .deco svg { width: 100%; height: auto; display: block; overflow: visible; }
.stage .deco.orn { transform-origin: 50% 14%; }
.stage .deco.card-deco { width: calc(5.6cqw * var(--s, 1)); }
.stage .deco.gift { width: calc(8.5cqw * var(--s, 1)); }
.stage .cast {
  position: absolute; left: 6%; top: 76%; width: 88%; height: 17%;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(0,0,0,0.6), rgba(0,0,0,0));
  transform-origin: 50% 50%;
}

/* ---------- time of day ----------
   A few lines of script in the page head set data-time="day" | "evening" | "night" on <html> from the viewer's own
   clock. Without it the room is evening, as drawn above. Only variables and which window artwork shows change. */
[data-time="day"] .stage {
  --wall: #8FA4B8; --wall-2: #7C91A5; --floor: #7D5D43; --floor-2: #68492F;
  --lit: 0.4; --vig: 0.26; --lights: 0.5;
}
[data-time="night"] .stage {
  --wall: #2B3642; --wall-2: #1D2630; --floor: #46301F; --floor-2: #33231A;
  --lit: 1.35; --vig: 0.75; --lights: 1;
}
.stage .tree-lights { opacity: var(--lights); }

/* the window: a sky that changes, a sun or a moon, stars, and dark or green pines */
.stage .win-sky   { fill: url(#g-night); }
.stage .win-pine  { fill: #0B1428; }
.stage .win-snow  { fill: #CBD7E6; }
.stage .win-sun   { opacity: 0; }
.stage .win-moon  { opacity: 1; }
.stage .win-stars { opacity: 0.55; }
[data-time="day"] .stage .win-sky   { fill: url(#g-day); }
[data-time="day"] .stage .win-sun   { opacity: 1; }
[data-time="day"] .stage .win-moon  { opacity: 0; }
[data-time="day"] .stage .win-stars { opacity: 0; }
[data-time="day"] .stage .win-pine  { fill: #2A4A3A; }
[data-time="day"] .stage .win-snow  { fill: #F4F8FB; }
[data-time="night"] .stage .win-stars { opacity: 1; }

/* ---------- the countdown ---------- */
/* A tear-off calendar pad hung on the wall above the fireplace. Drawn in em, where 1em is the sign's own width, so one number
   (--cd-w, in cqw) sizes the whole thing. wwwroot/countdown.js draws and ticks it; see docs/style-sheet.html section 10. */
.stage .cd-hang { position: absolute; left: 83%; top: 19.5%; translate: -50% -50%; line-height: 1; z-index: 120; }
.cd-sign {
  --paper: #F5EEDC; --paper-2: #E4D8BC; --ink-p: #3B3024; --ink-p2: #6F604B; --head: #9A2E43; --head-2: #6E1F31; --gold: #D9B65C;
  font-size: calc(var(--cd-w, 12) * 1cqw); width: 1em; height: 1.16em; position: relative; line-height: 1; isolation: isolate;
}
.cd-sign .cd-nail {
  position: absolute; left: 50%; top: -0.05em; width: 0.055em; height: 0.055em; border-radius: 50%; translate: -50% 0; z-index: 3;
  background: #C4BDAE; box-shadow: 0 0.012em 0.025em rgba(0,0,0,0.55);
}
.cd-sign .cd-under, .cd-sign .cd-pad { position: absolute; inset: 0; border-radius: 0.03em; }
.cd-sign .cd-under { background: var(--paper-2); translate: 0.02em 0.032em; box-shadow: 0 0.035em 0.09em rgba(0,0,0,0.4); }
.cd-sign .cd-pad { background: var(--paper); box-shadow: 0 0.02em 0.05em rgba(0,0,0,0.28); }
.cd-sign .cd-head { position: relative; height: 0.2em; background: var(--head); border-radius: 0.03em 0.03em 0 0; }
.cd-sign .cd-head i {
  position: absolute; top: -0.028em; width: 0.05em; height: 0.08em; border-radius: 0.03em; translate: -50% 0;
  background: #2A2520; box-shadow: inset 0 0 0 0.012em #9A958A;
}
.cd-sign .cd-head i:nth-child(1) { left: 27%; }
.cd-sign .cd-head i:nth-child(2) { left: 73%; }
.cd-sign .cd-sheet, .cd-sign .cd-torn {
  position: absolute; left: 0; right: 0; top: 0.2em; bottom: 0; background: var(--paper); border-radius: 0 0 0.03em 0.03em;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.035em;
}
.cd-sign .cd-num { font: 800 0.5em/1 var(--sans); letter-spacing: -0.03em; color: var(--ink-p); font-variant-numeric: tabular-nums; }
.cd-sign .cd-unit { white-space: nowrap; font: 500 max(7px, 0.118em)/1 var(--mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-p2); }
.cd-sign.cd-clock .cd-num { font-size: 0.3em; letter-spacing: 0; }
.cd-sign .cd-star { width: 0.42em; height: 0.42em; display: block; overflow: visible; }
.cd-sign .cd-hand { font: 600 max(8px, 0.16em)/0.95 "Caveat", "Segoe Print", "Bradley Hand", cursive; color: var(--head-2); text-align: center; }
.cd-sign.cd-done .cd-head { background: var(--gold); }
.cd-sign.cd-done::after {
  content: ""; position: absolute; inset: -0.3em; z-index: -1; pointer-events: none;
  background: radial-gradient(circle, rgba(255,226,168,0.6), rgba(255,208,138,0) 66%); animation: cdGlow 3.2s ease-in-out infinite;
}
@keyframes cdGlow { 0%, 100% { opacity: 0.55; } 50% { opacity: 1; } }
/* the page that comes off when the count changes: transform and opacity only */
.cd-sign .cd-torn { z-index: 2; transform-origin: 0 0; animation: cdTear 0.95s cubic-bezier(.45,0,.75,.35) forwards; }
@keyframes cdTear {
  0%   { transform: none; opacity: 1; }
  16%  { transform: rotate(-5deg) translate(-0.01em, 0.015em); opacity: 1; }
  100% { transform: translate(0.34em, 1em) rotate(28deg); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) { .cd-sign .cd-torn { display: none; } .cd-sign.cd-done::after { animation: none; opacity: 0.8; } }

/* the hover tooltip: a slip of paper at the item's own slot. Above the light layers, never catches the pointer. */
.stage .stage-tip {
  --tx: -50%; --ty: calc(-100% - 2.4cqw);
  position: absolute; z-index: 300; pointer-events: none; translate: var(--tx) var(--ty);
  width: max-content; max-width: min(max(15rem, 22cqw), 62cqw); padding: 0.4em 0.6em; border-radius: 0.4em;
  background: #FBF6EA; color: #3B3024; box-shadow: 0 6px 16px rgba(0,0,0,0.4); font-size: max(0.85rem, 1.1cqw); line-height: 1.3;
  animation: tipIn 0.12s ease-out both;
}
.stage .stage-tip.tip-l { --tx: -12%; }
.stage .stage-tip.tip-r { --tx: -88%; }
.stage .stage-tip.tip-below { --ty: 2.4cqw; }
.stage .stage-tip .tip-line span { font: 700 0.8em "JetBrains Mono", ui-monospace, Consolas, monospace; letter-spacing: 0.04em; text-transform: uppercase; color: #7A6A55; margin-right: 0.25rem; }
.stage .stage-tip .tip-line { font-weight: 600; }
.stage .stage-tip .tip-text { margin-top: 0.3rem; padding-top: 0.3rem; border-top: 1px solid #E3D8BE; white-space: pre-wrap; overflow-wrap: anywhere; }
.stage .stage-tip .tip-note { margin-top: 0.25em; font-size: 0.9em; color: #7A6A55; font-style: italic; }
@keyframes tipIn { from { opacity: 0; } to { opacity: 1; } }

/* light on top of everything: fire glow, tree glow, edge falloff, paper grain */
.stage .light { position: absolute; inset: 0; pointer-events: none; z-index: 200; }
.stage .light-fire {
  background: radial-gradient(ellipse 40cqw 28cqw at 82% 66%, rgba(255,140,50,calc(0.46 * var(--lit))), rgba(255,120,40,calc(0.13 * var(--lit))) 55%, transparent 78%);
  mix-blend-mode: screen;
  animation: glow 3.1s ease-in-out infinite;
}
.stage .light-tree { background: radial-gradient(ellipse 26cqw 32cqw at 50% 46%, rgba(255,214,150,calc(0.15 * var(--lit))), transparent 72%); mix-blend-mode: screen; }
.stage .light-edge { background: radial-gradient(ellipse 75% 80% at 50% 55%, transparent 58%, rgba(4,7,12,var(--vig)) 100%); }
.stage .grain {
  z-index: 210; opacity: 0.2; mix-blend-mode: overlay; background-size: 180px 180px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---------- colour contract: a swatch class sets every tone a shape needs ---------- */
.art { --c-main: #9A2E43; --c-shade: #6E1F31; --c-tint: #CB6A80; --pat: #F0C6CF; --rib: #D9B65C; --rib-shade: #A98A3A; }
.pt-stripe { --o-stripe: 1; }
.pt-dots   { --o-dots: 1; }
.pt-check  { --o-check: 1; }

/* ---------- snow: transform only, tile heights divide the travel distance exactly ---------- */
.snowwin { position: absolute; overflow: hidden; border-radius: 2px; }
.snowlayer {
  position: absolute; left: 0; right: 0; top: calc(var(--u, 1cqw) * -12); height: calc(var(--u, 1cqw) * 30);
  background-image:
    radial-gradient(circle at 30% 30%, var(--snow) 0 calc(var(--u, 1cqw) * 0.2), transparent calc(var(--u, 1cqw) * 0.26)),
    radial-gradient(circle at 70% 60%, rgba(244,247,251,0.8) 0 calc(var(--u, 1cqw) * 0.14), transparent calc(var(--u, 1cqw) * 0.2));
  background-size: calc(var(--u, 1cqw) * 4.4) calc(var(--u, 1cqw) * 6), calc(var(--u, 1cqw) * 3) calc(var(--u, 1cqw) * 4);
  animation: snowfall 7.5s linear infinite;
  will-change: transform;
}
.snowlayer.slow { animation-duration: 10.5s; }

/* ---------- ambient motion ---------- */
@keyframes sway    { 0%,100% { rotate: -2.2deg; } 50% { rotate: 2.2deg; } }
@keyframes twinkle { 0%,100% { opacity: 1; } 50% { opacity: 0.3; } }
@keyframes snowfall{ from { transform: translateY(0); } to { transform: translateY(calc(var(--u, 1cqw) * 12)); } }
@keyframes glow    { 0%,100% { opacity: 0.85; } 18% { opacity: 1; } 34% { opacity: 0.76; } 52% { opacity: 0.97; } 71% { opacity: 0.8; } }
@keyframes pulse   { 0%,100% { opacity: 0.62; } 40% { opacity: 1; } 70% { opacity: 0.78; } }
@keyframes breathe { 0%,100% { transform: scaleY(1); } 50% { transform: scaleY(1.045); } }
@keyframes lick    { 0% { transform: translate(0,0) scale(1); opacity: 0; }
                     14% { opacity: 1; }
                     100% { transform: translate(var(--dx, 0px), -26px) scale(0.1); opacity: 0; } }
@keyframes ember   { 0% { transform: translate(0,0) scale(1); opacity: 0; }
                     12% { opacity: 1; }
                     100% { transform: translate(var(--dx, 0px), -50px) scale(0.3); opacity: 0; } }
@keyframes swing   { 0%,100% { transform: rotate(-3.4deg); } 50% { transform: rotate(3.4deg); } }

.stage .sway    { animation: sway 5.5s ease-in-out infinite; animation-delay: calc(var(--i, 0) * -0.42s); }
.stage .twinkle { animation: twinkle 2.6s ease-in-out infinite; animation-delay: calc(var(--i, 0) * -0.37s); }
.stage .swing   { transform-origin: 50% 24%; animation: swing 4.6s ease-in-out infinite; animation-delay: calc(var(--i, 0) * -0.9s); }

/* ---------- arrivals: used when something is added while the room is open (phase 4) ---------- */
@keyframes hang    { 0% { transform: translateY(calc(var(--rise) * -1)) scale(0.6); opacity: 0; }
                     22% { transform: translateY(0) scale(1.04); opacity: 1; }
                     40% { transform: rotate(9deg); }
                     58% { transform: rotate(-5.5deg); }
                     76% { transform: rotate(2.6deg); }
                     100% { transform: rotate(0); opacity: 1; } }
@keyframes flutter { 0%   { transform: translate(calc(var(--sx) * -0.6), calc(var(--fall) * -1)) rotate(-26deg); opacity: 0; }
                     12%  { opacity: 1; }
                     30%  { transform: translate(var(--sx), calc(var(--fall) * -0.66)) rotate(20deg); }
                     50%  { transform: translate(calc(var(--sx) * -0.8), calc(var(--fall) * -0.36)) rotate(-14deg); }
                     70%  { transform: translate(calc(var(--sx) * 0.5), calc(var(--fall) * -0.13)) rotate(8deg); }
                     86%  { transform: translate(calc(var(--sx) * -0.15), calc(var(--fall) * -0.03)) rotate(-3deg); }
                     100% { transform: translate(0,0) rotate(0); opacity: 1; } }
@keyframes swingIn { 0% { transform: rotate(10deg); } 100% { transform: rotate(0); } }
@keyframes drop    { 0%   { transform: translateY(calc(var(--fall) * -1)) rotate(-5deg); }
                     52%  { transform: translateY(0) rotate(0); animation-timing-function: ease-out; }
                     66%  { transform: translateY(calc(var(--fall) * -0.06)) scale(0.98, 1.03); }
                     80%  { transform: translateY(0) scale(1.05, 0.93); }
                     100% { transform: translateY(0) scale(1); } }
@keyframes castIn  { 0% { transform: scale(0.2); opacity: 0; } 52% { transform: scale(1); opacity: 1; } 80% { transform: scale(1.08); } 100% { transform: scale(1); opacity: 1; } }

.stage .hang svg { transform-origin: 50% 14%; animation: hang 1.9s ease-out both; }
.stage .flutter-in { animation: flutter 2.4s cubic-bezier(.4,.1,.4,1) both; }
.stage .flutter-in .swing { animation: swingIn 1.2s ease-out 2.2s both, swing 4.6s ease-in-out 3.4s infinite; }
.stage .gift.dropping svg { transform-origin: 50% 90%; animation: drop 1.15s cubic-bezier(.5,0,.9,.5) both; }
.stage .gift.dropping .cast { animation: castIn 1.15s cubic-bezier(.5,0,.9,.5) both; }

/* ---------- fire ---------- */
.fire .tongue { transform-box: fill-box; transform-origin: 50% 100%; animation: lick var(--d, 1.4s) ease-out infinite; animation-delay: var(--w, 0s); }
.fire .ember  { opacity: 0; animation: ember var(--d, 3s) ease-out infinite; animation-delay: var(--w, 0s); }
.fire .breath { transform-box: fill-box; transform-origin: 50% 100%; animation: breathe 2.7s ease-in-out infinite; }
.fire .edge, .fire .coals { animation: pulse 2.3s ease-in-out infinite; }
.fire .coals { animation-duration: 1.9s; animation-delay: -0.6s; }
.fire .boxglow, .fire .spill { animation: glow 3.1s ease-in-out infinite; }

/* Ship the guard with the first animation. The delay and iteration rules also make a long open sequence jump to its end state. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0s !important;
  }
}

/* ---------- swatches 0-7 heritage, 8-15 bright. Static on purpose: do not generate these from script. ---------- */
.sw0 { --c-main: #9A2E43; --c-shade: #6E1F31; --c-tint: #CB6A80; --pat: #F0C6CF; --rib: #D9B65C; --rib-shade: #A98A3A; }
.sw1 { --c-main: #2F5D50; --c-shade: #1F4036; --c-tint: #6A9A8A; --pat: #BFE0D3; --rib: #D9B65C; --rib-shade: #A98A3A; }
.sw2 { --c-main: #C9A24B; --c-shade: #9A7A30; --c-tint: #E8D08F; --pat: #7A5C1E; --rib: #2F5D50; --rib-shade: #1F4036; }
.sw3 { --c-main: #2E4468; --c-shade: #1E2D48; --c-tint: #6B8AB8; --pat: #B9CBE6; --rib: #D9B65C; --rib-shade: #A98A3A; }
.sw4 { --c-main: #6B4A68; --c-shade: #4A3048; --c-tint: #A07E9E; --pat: #DCC3DA; --rib: #D9B65C; --rib-shade: #A98A3A; }
.sw5 { --c-main: #D49AA0; --c-shade: #B07078; --c-tint: #EDC8CC; --pat: #FBEAEC; --rib: #9A2E43; --rib-shade: #6E1F31; }
.sw6 { --c-main: #EDE3CE; --c-shade: #C9BC9E; --c-tint: #FBF6EA; --pat: #B7A57E; --rib: #2F5D50; --rib-shade: #1F4036; }
.sw7 { --c-main: #B8895A; --c-shade: #8C6339; --c-tint: #D8B58C; --pat: #F4EAD6; --rib: #F1E7D0; --rib-shade: #CFC2A2; }
.sw8 { --c-main: hsl(354 62% 52%); --c-shade: hsl(354 58% 38%); --c-tint: hsl(354 72% 74%); --pat: hsl(354 85% 92%); --rib: #D9B65C; --rib-shade: #A98A3A; }
.sw9 { --c-main: hsl(22 62% 52%); --c-shade: hsl(22 58% 38%); --c-tint: hsl(22 72% 74%); --pat: hsl(22 85% 92%); --rib: #D9B65C; --rib-shade: #A98A3A; }
.sw10 { --c-main: hsl(43 62% 52%); --c-shade: hsl(43 58% 38%); --c-tint: hsl(43 72% 74%); --pat: hsl(43 70% 26%); --rib: #2F5D50; --rib-shade: #1F4036; }
.sw11 { --c-main: hsl(142 62% 52%); --c-shade: hsl(142 58% 38%); --c-tint: hsl(142 72% 74%); --pat: hsl(142 85% 92%); --rib: #D9B65C; --rib-shade: #A98A3A; }
.sw12 { --c-main: hsl(187 62% 52%); --c-shade: hsl(187 58% 38%); --c-tint: hsl(187 72% 74%); --pat: hsl(187 85% 92%); --rib: #D9B65C; --rib-shade: #A98A3A; }
.sw13 { --c-main: hsl(214 62% 52%); --c-shade: hsl(214 58% 38%); --c-tint: hsl(214 72% 74%); --pat: hsl(214 85% 92%); --rib: #D9B65C; --rib-shade: #A98A3A; }
.sw14 { --c-main: hsl(274 62% 52%); --c-shade: hsl(274 58% 38%); --c-tint: hsl(274 72% 74%); --pat: hsl(274 85% 92%); --rib: #D9B65C; --rib-shade: #A98A3A; }
.sw15 { --c-main: hsl(330 62% 52%); --c-shade: hsl(330 58% 38%); --c-tint: hsl(330 72% 74%); --pat: hsl(330 85% 92%); --rib: #D9B65C; --rib-shade: #A98A3A; }

/* ---------- decorations are buttons: reachable by keyboard, and one can be picked ---------- */
.stage button.deco { background: none; border: 0; padding: 0; margin: 0; font: inherit; color: inherit; cursor: pointer; }
.stage button.deco:focus-visible { outline: 2px solid #FFD9A0; outline-offset: 3px; border-radius: 12%; }
.stage button.deco.selected::before {
  content: ""; position: absolute; inset: -12%; border: 2px solid #FFD9A0; border-radius: 50%;
  opacity: 0.9; pointer-events: none; box-shadow: 0 0 1.2cqw rgba(255, 217, 160, 0.6);
}

/* ---------- reading and adding ---------- */
/* the composer and the reader live in the sheet: see shell.css */

/* ================= phase 5: reveal and opening ================= */

/* ---------- the one that is yours: a small shake every few seconds, and a glint across the bow ---------- */
@keyframes nudge { 0%,80%,100% { transform: rotate(0); } 83% { transform: rotate(-3deg); } 87% { transform: rotate(3deg); } 91% { transform: rotate(-2deg); } 95% { transform: rotate(1.2deg); } }
@keyframes glint { 0%,70%,100% { opacity: 0; transform: scale(0.3) rotate(0); } 82% { opacity: 1; transform: scale(1) rotate(25deg); } 92% { opacity: 0; transform: scale(0.4) rotate(50deg); } }

.stage .gift.yours svg { transform-origin: 50% 90%; animation: nudge 5.5s ease-in-out infinite; }
.stage .gift.yours::after {
  content: ""; position: absolute; right: 14%; top: 22%; width: 22%; aspect-ratio: 1; pointer-events: none;
  background: var(--cream); clip-path: polygon(50% 0, 60% 40%, 100% 50%, 60% 60%, 50% 100%, 40% 60%, 0 50%, 40% 40%);
  animation: glint 5.5s ease-in-out infinite;
}

/* ---------- a present that opens: untie, lid off, light, card rises and turns ---------- */
.giftscene { position: relative; width: 100%; max-width: 260px; margin-inline: auto; }
.giftscene svg { width: 100%; height: auto; display: block; overflow: visible; }

.giftscene .g-box, .giftscene .g-lid, .giftscene .g-bow, .giftscene .g-beam,
.giftscene .g-back, .giftscene .g-face, .giftscene .g-bob { transform-box: fill-box; }
.giftscene .g-box  { transform-origin: 50% 90%; }
.giftscene .g-lid  { transform-origin: 50% 100%; }
.giftscene .g-bow  { transform-origin: 50% 100%; }
.giftscene .g-beam { transform-origin: 50% 100%; opacity: 0; }
.giftscene .g-card { transform: translateY(16px); }
.giftscene .g-back, .giftscene .g-face { transform-origin: 50% 50%; }
.giftscene .g-face { transform: scaleX(0); }

.giftscene.ready:not(.is-open) .g-box { animation: nudge 5.5s ease-in-out infinite; }
.giftscene.ready:not(.is-open)::after {
  content: ""; position: absolute; right: 30%; top: 33%; width: 11%; aspect-ratio: 1; pointer-events: none;
  background: var(--cream); clip-path: polygon(50% 0, 60% 40%, 100% 50%, 60% 60%, 50% 100%, 40% 60%, 0 50%, 40% 40%);
  animation: glint 5.5s ease-in-out infinite;
}
.giftscene.waiting svg { filter: saturate(0.5) brightness(0.88); }
.giftscene .sticker {
  position: absolute; right: 6%; top: 50%; width: 3rem; height: 3rem; border-radius: 50%;
  background: #EFE6D0; color: #8E2B3A; display: grid; place-items: center; rotate: 8deg;
  font: 0.62rem/1.1 ui-monospace, "Cascadia Mono", Consolas, monospace; text-align: center;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}

.giftscene.is-open .g-bow  { animation: bowUntie 0.75s ease-in 0.15s forwards; }
.giftscene.is-open .g-lid  { animation: lidLift 1s cubic-bezier(.3,.7,.3,1) 0.8s forwards; }
.giftscene.is-open .g-beam { animation: beam 0.9s ease-out 1.25s forwards; }
.giftscene.is-open .g-card { animation: cardRise 1s cubic-bezier(.2,.8,.2,1) 1.4s forwards; }
.giftscene.is-open .g-bob  { animation: bob 3s ease-in-out 2.6s infinite; }
.giftscene.is-open .g-back { animation: flipOut 0.22s ease-in 2.25s forwards; }
.giftscene.is-open .g-face { animation: flipIn 0.3s ease-out 2.45s forwards; }

@keyframes bowUntie { 0% { transform: rotate(0); } 20% { transform: rotate(-8deg); } 40% { transform: rotate(7deg); } 60% { transform: rotate(-4deg); opacity: 1; }
                      100% { transform: translateY(7px) scale(0.55); opacity: 0; } }
@keyframes lidLift  { 0% { transform: translate(0,0) rotate(0); opacity: 1; }
                      45% { transform: translate(-5px,-34px) rotate(-7deg); opacity: 1; }
                      100% { transform: translate(40px,-58px) rotate(15deg); opacity: 0; } }
@keyframes beam     { from { opacity: 0; transform: scaleY(0.2); } to { opacity: 1; transform: scaleY(1); } }
@keyframes cardRise { from { transform: translateY(16px); } to { transform: translateY(-46px); } }
@keyframes bob      { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-2.5px); } }
@keyframes flipOut  { to { transform: scaleX(0); } }
@keyframes flipIn   { to { transform: scaleX(1); } }

/* seen again later: jump straight to the end of the sequence instead of replaying it */
.giftscene.is-open.instant *, .giftscene.is-open.instant .gift-note { animation-duration: 0.01ms !important; animation-delay: 0s !important; animation-iteration-count: 1 !important; transition: none !important; }

.gift-note {
  font-family: "Caveat", "Segoe Print", "Bradley Hand", cursive; font-size: 1.3rem; line-height: 1.12; color: #3B3024;
  background: #FBF6EA; padding: 0.7rem 0.9rem; border-radius: 2px; rotate: -1.2deg; margin: 0.9rem auto 0; max-width: 28ch;
  white-space: pre-wrap; overflow-wrap: anywhere;
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.25), 0 8px 18px rgba(0, 0, 0, 0.28);
}
/* An animation, not a transition: the note is inserted already in its final state, so there is nothing to
   transition from. Fill-mode both holds the first frame through the delay. */
.giftscene.is-open .gift-note { animation: noteIn 0.5s ease 2.7s both; }
@keyframes noteIn { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }

/* ---------- a card that opens: envelope, card, message. Real HTML so the handwriting is readable. ---------- */
/* --rd scales the whole thing. Narrower screens get a smaller one. */
.card-reader { --rd: 1.7; width: 100%; display: flex; flex-direction: column; align-items: center; gap: 0.75rem; }
@media (max-width: 760px) { .card-reader { --rd: 1.3; } }
@media (max-width: 480px) { .card-reader { --rd: 1.05; } }

.card-reader .rd-room { padding-top: calc(var(--rd) * 112px); }
.card-reader .rd-stage { position: relative; width: calc(var(--rd) * 260px); height: calc(var(--rd) * 170px); perspective: 1000px; }
.card-reader .rd-back { position: absolute; inset: 0; border-radius: 4px; background: var(--c-shade); box-shadow: 0 12px 26px rgba(0,0,0,0.38); }
.card-reader .rd-card { position: absolute; left: calc(var(--rd) * 75px); top: calc(var(--rd) * 14px); width: calc(var(--rd) * 110px); height: calc(var(--rd) * 150px); z-index: 1; transform-style: preserve-3d; }
.card-reader .rd-page {
  position: absolute; inset: 0; background: #FBF6EA; border-radius: 0 3px 3px 0; padding: calc(var(--rd) * 9px);
  font-family: "Caveat", "Segoe Print", "Bradley Hand", cursive; font-size: var(--rd-font, 16px); line-height: 1.12; color: #3B3024;
  box-shadow: 0 1px 2px rgba(0,0,0,0.3); white-space: pre-wrap; overflow-wrap: anywhere; overflow-y: auto;
}
.card-reader .rd-cover { position: absolute; inset: 0; transform-origin: 0 50%; transform-style: preserve-3d; }
.card-reader .rd-face { position: absolute; inset: 0; backface-visibility: hidden; border-radius: 3px; display: grid; place-items: center; box-shadow: 0 1px 2px rgba(0,0,0,0.3); }
.card-reader .rd-front {
  background: var(--c-main); background-image: radial-gradient(circle, var(--pat) 0 1.6px, transparent 1.9px);
  background-size: calc(var(--rd) * 11px) calc(var(--rd) * 11px); background-blend-mode: soft-light; align-content: center; gap: calc(var(--rd) * 10px);
}
.card-reader .rd-front::before { content: ""; width: calc(var(--rd) * 40px); height: calc(var(--rd) * 46px); background: var(--c-tint); clip-path: polygon(50% 0, 100% 100%, 0 100%); opacity: 0.9; }
.card-reader .rd-front span { font-family: "Caveat", "Segoe Print", "Bradley Hand", cursive; font-size: calc(var(--rd) * 20px); line-height: 0.9; color: #fff; text-align: center; text-shadow: 0 1px 1px rgba(0,0,0,0.25); }
.card-reader .rd-inside { transform: rotateY(180deg); background: #F3EBD6; font-family: "Caveat", "Segoe Print", "Bradley Hand", cursive; font-size: calc(var(--rd) * 16px); color: #6E1F31; text-align: center; padding: calc(var(--rd) * 8px); overflow-wrap: anywhere; }
.card-reader .rd-pocket {
  position: absolute; inset: 0; z-index: 2; border-radius: 4px;
  background: linear-gradient(180deg, rgba(0,0,0,0) 40%, rgba(0,0,0,0.18)), var(--c-main);
  clip-path: polygon(0 0, 50% 56%, 100% 0, 100% 100%, 0 100%);
}
.card-reader .rd-flap { position: absolute; left: 0; top: 0; width: 100%; height: 62%; z-index: 3; background: var(--c-tint); clip-path: polygon(0 0, 100% 0, 50% 100%); transform-origin: 50% 0; }

.card-reader.is-open .rd-flap  { animation: flapOpen 0.6s ease-in-out forwards; }
.card-reader.is-open .rd-card  { animation: cardOut 1.7s cubic-bezier(.3,.7,.2,1) 0.5s forwards; }
.card-reader.is-open .rd-cover { animation: coverOpen 1s cubic-bezier(.5,.1,.2,1) 2.15s forwards; }
.card-reader.is-open.instant *  { animation-duration: 0.01ms !important; animation-delay: 0s !important; }

@keyframes flapOpen  { 0% { transform: rotateX(0); z-index: 3; } 49% { z-index: 3; } 50% { z-index: 0; } 100% { transform: rotateX(180deg); z-index: 0; } }
@keyframes cardOut   { 0%   { transform: translate(0,0) scale(1); z-index: 1; }
                       45%  { transform: translate(0, calc(var(--rd) * -118px)) scale(1); z-index: 1; }
                       46%  { z-index: 4; }
                       100% { transform: translate(calc(var(--rd) * 55px), calc(var(--rd) * -96px)) scale(1.25); z-index: 4; } }
@keyframes coverOpen { to { transform: rotateY(-172deg); } }

/* The message appears twice in the markup, once on the card page (decoration for sighted people) and once in .card-note
   (the real copy). Wide screens show the card page and hide the note visually; a phone shows the note under the card,
   because the card page is too small to hold up to 280 characters. */
.card-reader .card-note { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; margin: 0; padding: 0; }
@media (max-width: 480px) {
  .card-reader .rd-page { color: transparent; overflow: hidden;
    background-image: repeating-linear-gradient(180deg, transparent 0 17px, rgba(120, 100, 70, 0.18) 17px 18px); background-position: 0 8px; }
  .card-reader .card-note { position: static; width: auto; height: auto; overflow: visible; clip: auto; white-space: pre-wrap; padding: 0.7rem 0.9rem; margin: 0.9rem auto 0; display: none; }
  .card-reader.is-open .card-note { display: block; animation: noteIn 0.5s ease 3.2s both; }
  .card-reader.is-open.instant .card-note { animation-delay: 0s; }
}
