:root {
--font: "Fredoka", "Nunito", "Trebuchet MS", system-ui, sans-serif; /* font used everywhere */

--heading-size: clamp(2.2rem, 3rem, 4.2rem);  /* heading text size */
--heading-max-width: 16em;                   /* heading wraps after this width */
--image-width: min(78vw, 380px);             /* image width */
--image-radius: 28px;                        /* image corner roundness */
--image-border: 6px;                         /* image frame thickness */
--image-tilt: -2deg;                         /* image tilt, it sways between this and the opposite (0deg = no sway) */
--image-sway-time: 6s;                       /* time of one image sway */
--button-size: 1.25rem;                      /* button text size */
--content-gap: 28px;                         /* space between heading, image and button */
--content-offset-y: 0px;                     /* move all content up (negative) or down (positive) */

--dots-top: 18px;                            /* distance of the dots from the top edge */
--dot-size: 10px;                            /* size of a dot */
--dot-active-width: 30px;                    /* width of the current slide's dot */
--dot-gap: 10px;                             /* space between dots */

--slide-fade: .7s;                           /* crossfade time between slides */
--slide-move: .9s;                           /* sideways movement time between slides */
--slide-shift: 6%;                           /* how far slides travel sideways */
--bg-fade: .9s;                              /* background color change time */
--enter-delay: .3s;                          /* wait before heading, image and button appear */
--stagger: .14s;                             /* delay between heading, image and button */
--enter-time: .9s;                           /* how long the content takes to appear */
--float-distance: 10px;                      /* how far background icons bob up and down */

--heart-size: clamp(130px, 28vh, 230px);     /* love calculator: heart size */
--love-scale: 1.35;                          /* love calculator: how much bigger the heart gets at 100% */
--jump-height: 14%;                          /* love calculator: how high the heart jumps at 100% */
--jump-time: .8s;                            /* love calculator: time of one jump */
}

/* slide colors: bg = background, ink = background icons, text = heading, frame = image border,
    btn-bg / btn-text = button, shadow = button + image shadow, dots = top dots,
    ph-bg / ph-fg = placeholder image, firework = animated fireworks */
.theme-celebration { --bg:#14110a; --ink:#40350f; --firework:#85701d; --text:#ffd43b; --frame:#ffd43b; --btn-bg:#ffd43b; --btn-text:#14110a; --shadow:#b58f12; --dots:#ffd43b; --ph-bg:#2b2410; --ph-fg:#ffd43b; }
.theme-love        { --bg:#6a1327; --ink:#802142; --text:#ffdfe7; --frame:#ffdfe7; --btn-bg:#ffdfe7; --btn-text:#6a1327; --shadow:#d98ba0; --dots:#ffdfe7; --ph-bg:#8a1f42; --ph-fg:#ffdfe7; }
.theme-lemon       { --bg:#fff3b0; --ink:#f3dc72; --text:#5a4a06; --frame:#ffffff; --btn-bg:#f7d33c; --btn-text:#4a3d02; --shadow:#c9a51c; --dots:#5a4a06; --ph-bg:#ffe98a; --ph-fg:#5a4a06; }
.theme-oreo        { --bg:#f6f4ef; --ink:#dedbd2; --text:#141414; --frame:#141414; --btn-bg:#141414; --btn-text:#ffffff; --shadow:#7a7a7a; --dots:#141414; --ph-bg:#e6e3da; --ph-fg:#141414; }
/* slide 5 extra colors: input-bg / input-text / placeholder = name fields, heart-line = heart outline, heart-empty = unfilled heart, liquid = heart fill, pct = percentage text */
.theme-calc        { --bg:#d81e3b; --ink:#ea5268; --text:#fff3f5; --btn-bg:#fff3f5; --btn-text:#b3122d; --shadow:#f0a3ae; --dots:#fff3f5;
                    --input-bg:#fff3f5; --input-text:#6d0a1e; --placeholder:#c98891; --heart-line:#fff3f5; --heart-empty:#e2495e; --liquid:#fff3f5; --pct:#5e0717; }

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; height: 100%; overflow: hidden; background: #14110a; }
body { font-family: var(--font); -webkit-font-smoothing: antialiased; }

.stage {
position: fixed; inset: 0; overflow: hidden; touch-action: pan-y;
background-color: var(--stage-bg, #14110a);
transition: background-color var(--bg-fade) ease;
}

.slide {
position: absolute; inset: 0;
display: flex; align-items: center; justify-content: center;
color: var(--text);
opacity: 0; visibility: hidden; pointer-events: none;
--play: paused;
transition:
    opacity var(--slide-fade) ease,
    transform var(--slide-move) cubic-bezier(.22, 1, .36, 1),
    visibility 0s linear var(--slide-fade);
}
.slide.is-before { transform: translateX(calc(var(--slide-shift) * -1)); }
.slide.is-after  { transform: translateX(var(--slide-shift)); }
.slide.is-active {
opacity: 1; visibility: visible; pointer-events: auto; transform: none;
--play: running;
transition:
    opacity var(--slide-fade) ease,
    transform var(--slide-move) cubic-bezier(.22, 1, .36, 1),
    visibility 0s;
}

.slide-content {
position: relative; z-index: 2; top: var(--content-offset-y);
width: 100%;
padding: calc(56px + env(safe-area-inset-top, 0px)) 24px calc(24px + env(safe-area-inset-bottom, 0px));
display: flex; flex-direction: column; align-items: center;
gap: var(--content-gap); text-align: center;
}
.slide-header { display: flex; flex-direction: column; align-items: center; gap: var(--content-gap); }

.el {
opacity: 0;
transform: translateY(30px) scale(.92);
transition: opacity .35s ease, transform .35s ease;
}
.slide.is-active .el {
opacity: 1; transform: none;
transition:
    opacity calc(var(--enter-time) * .8) ease calc(var(--enter-delay) + var(--i) * var(--stagger)),
    transform var(--enter-time) cubic-bezier(.34, 1.5, .64, 1) calc(var(--enter-delay) + var(--i) * var(--stagger));
}
h1.el { --i: 0; }
.slide-figure { --i: 1; margin: 0; }
.slide-action { --i: 2; }

h1.el {
margin: 0;
max-width: var(--heading-max-width);
font-weight: 600; font-size: var(--heading-size);
line-height: 1.08;
letter-spacing: .01em;
color: var(--text); text-wrap: balance;
}

h1.huge-text {
    font-size: clamp(1rem, 2rem, 4.2rem);
}

.slide-img {
display: block;
width: var(--image-width);
object-fit: cover;
border: var(--image-border) solid var(--frame); border-radius: var(--image-radius);
box-shadow: 0 8px 0 var(--shadow);
transform: rotate(var(--image-tilt));
animation: sway var(--image-sway-time) ease-in-out infinite;
animation-play-state: var(--play);
}
@keyframes sway {
0%, 100% { transform: translateY(0) rotate(var(--image-tilt)); }
50%      { transform: translateY(-8px) rotate(calc(var(--image-tilt) * -1)); }
}

.edit-img {
    width: min(78vw, 1000px);
}

.btn {
display: inline-flex; align-items: center; gap: .55em;
padding: .85em 1.7em; border: 0; border-radius: 999px; cursor: pointer;
font: 500 var(--button-size)/1 var(--font);
color: var(--btn-text); background: var(--btn-bg);
box-shadow: 0 6px 0 var(--shadow);
-webkit-tap-highlight-color: transparent;
transition: transform .25s cubic-bezier(.34, 1.56, .64, 1), box-shadow .25s ease;
}
@media (hover: hover) {
.btn:hover { transform: translateY(-3px) scale(1.04); box-shadow: 0 9px 0 var(--shadow); }
}
.btn:active { transform: translateY(4px) scale(.98); box-shadow: 0 2px 0 var(--shadow); }
.btn:focus-visible { outline: 3px solid var(--text); outline-offset: 4px; }
.btn .arrow {
width: 1.2em; height: 1.2em; fill: none; stroke: currentColor; stroke-width: 3;
stroke-linecap: round; stroke-linejoin: round;
animation: nudge 1.6s ease-in-out infinite; animation-play-state: var(--play);
}
@keyframes nudge { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(4px); } }

.dots {
position: fixed; z-index: 10; left: 50%;
top: calc(env(safe-area-inset-top, 0px) + var(--dots-top));
display: flex; align-items: center;
transform: translateX(-50%);
animation: dots-in .9s cubic-bezier(.34, 1.4, .64, 1) .2s both;
}
@keyframes dots-in {
from { opacity: 0; transform: translate(-50%, -20px); }
to   { opacity: 1; transform: translate(-50%, 0); }
}
.dot {
display: grid; place-items: center; border: 0; background: none; cursor: pointer;
padding: 10px calc(var(--dot-gap) / 2);
-webkit-tap-highlight-color: transparent;
}
.dot-shape {
display: block; width: var(--dot-size); height: var(--dot-size); border-radius: 999px;
background-color: var(--dot-color, #fff); opacity: .35;
transition: width .5s cubic-bezier(.34, 1.4, .64, 1), opacity .4s ease, background-color var(--bg-fade) ease, transform .25s ease;
}
@media (hover: hover) {
.dot:hover .dot-shape { opacity: .7; transform: scale(1.15); }
}
.dot:active .dot-shape { transform: scale(.85); }
.dot.is-active .dot-shape { width: var(--dot-active-width); opacity: 1; transform: none; }
.dot:focus-visible { outline: none; }
.dot:focus-visible .dot-shape { outline: 2px solid var(--dot-color); outline-offset: 3px; }

.bg { position: absolute; inset: 0; overflow: hidden; pointer-events: none; color: var(--ink); }
.bg-item {
position: absolute; opacity: 0; transform: scale(.3) rotate(-20deg);
transition: opacity .5s ease, transform .5s ease;
}
.slide.is-active .bg-item {
opacity: 1; transform: none;
transition: opacity .9s ease var(--in), transform 1.1s cubic-bezier(.34, 1.56, .64, 1) var(--in);
}
.bg-glyph {
display: block; width: 100%; height: 100%; overflow: visible;
fill: none; stroke: currentColor; stroke-width: 3.5; stroke-linecap: round; stroke-linejoin: round;
transform: rotate(var(--rot));
animation: float var(--dur) ease-in-out var(--delay) infinite;
animation-play-state: var(--play);
}
@keyframes float {
0%, 100% { transform: translateY(0) rotate(var(--rot)); }
50%      { transform: translateY(calc(var(--float-distance) * -1)) rotate(calc(var(--rot) + 8deg)); }
}

.fireworks { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.firework {
position: absolute; left: var(--x); top: var(--y);
width: var(--size); height: var(--size);
transform: translate(-50%, -50%);
color: var(--firework);
}
.firework svg { display: block; width: 100%; height: 100%; overflow: visible; fill: none; stroke: currentColor; stroke-width: 3.2; stroke-linecap: round; }
.fw-trail, .fw-ray, .fw-spark, .fw-core { animation-duration: var(--dur); animation-delay: var(--delay); animation-iteration-count: infinite; animation-timing-function: linear; animation-play-state: var(--play); opacity: 0; }
.fw-trail { stroke-dasharray: 20px 300px; animation-name: fw-trail; }
.fw-ray   { stroke-dasharray: var(--dash) 300px; animation-name: fw-ray; }
.fw-spark { fill: currentColor; stroke: none; transform-box: fill-box; transform-origin: center; animation-name: fw-spark; }
.fw-core  { fill: currentColor; stroke: none; transform-box: fill-box; transform-origin: center; animation-name: fw-core; }
@keyframes fw-trail {
0%   { stroke-dashoffset: 20px; opacity: 0; }
2%   { stroke-dashoffset: 20px; opacity: 1; animation-timing-function: cubic-bezier(.25, .6, .4, 1); }
21%  { stroke-dashoffset: -76px; opacity: 1; }
24%, 100% { stroke-dashoffset: -96px; opacity: 0; }
}
@keyframes fw-ray {
0%, 22% { stroke-dashoffset: var(--dash); opacity: 0; }
23%  { stroke-dashoffset: var(--dash); opacity: 1; animation-timing-function: cubic-bezier(.12, .8, .3, 1); }
52%  { stroke-dashoffset: calc(var(--dash) - var(--len)); opacity: 1; animation-timing-function: ease-in; }
76%, 100% { stroke-dashoffset: calc(0px - var(--len)); opacity: 0; }
}
@keyframes fw-spark {
0%, 44% { opacity: 0; transform: translateY(0) scale(.2); }
52%  { opacity: 1; transform: translateY(0) scale(1); }
84%, 100% { opacity: 0; transform: translateY(-10px) scale(.5); }
}
@keyframes fw-core {
0%, 21% { opacity: 0; transform: scale(0); }
25%  { opacity: 1; transform: scale(1.6); }
40%, 100% { opacity: 0; transform: scale(2.6); }
}

.calc-heart  { --i: 1; }
.calc-form   { --i: 2; }
.calc-action { --i: 3; }

.rise { position: absolute; inset: 0; overflow: hidden; pointer-events: none; color: var(--ink); }
.rise-heart { position: absolute; top: 100%; }
.rise-glyph { display: block; width: 100%; height: 100%; overflow: visible; fill: none; stroke: currentColor; stroke-width: 3.5; stroke-linecap: round; stroke-linejoin: round; }

.heart-box { position: relative; width: var(--heart-size); height: var(--heart-size); margin-block: calc(var(--heart-size) * .2) calc(var(--heart-size) * .1); }
.heart-grow { position: absolute; inset: 0; transform-origin: 50% 50%; transition: transform .9s cubic-bezier(.34, 1.56, .64, 1); }
.heart-box.is-love .heart-grow { transform: scale(var(--love-scale)); }
.heart-jump { position: absolute; inset: 0; transform-origin: 50% 88%; }
.heart-svg, .heart-ring { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.heart-empty { fill: var(--heart-empty); }
.liquid path { fill: var(--liquid); }
.wave { animation: wave 2.4s linear infinite; animation-play-state: var(--play); }
.heart-line { fill: none; stroke: var(--heart-line); stroke-width: 3; stroke-linejoin: round; }
.heart-ring { opacity: 0; pointer-events: none; fill: none; stroke: var(--heart-line); stroke-width: 1.6; stroke-linejoin: round; transform-origin: 50% 48%; }
.heart-shadow { position: absolute; left: 18%; right: 18%; top: 89%; height: 6%; border-radius: 50%; background: rgba(94, 7, 23, .35); opacity: 0; transition: opacity .6s ease .4s; }
.heart-box.is-love .heart-shadow { opacity: 1; animation: shadow-jump var(--jump-time) ease-in-out .7s infinite var(--play); }
.pct {
position: absolute; inset: 0; display: grid; place-items: center; padding-bottom: 8%;
font-weight: 600; font-size: calc(var(--heart-size) * .27); line-height: 1; color: var(--pct);
font-variant-numeric: tabular-nums; pointer-events: none;
}
.heart-box.is-calculating .heart-jump { animation: beat .7s ease-in-out infinite var(--play); }
.heart-box.is-pop  .heart-jump { animation: pop .9s ease-out var(--play); }
.heart-box.is-pop  .heart-ring { animation: ring 1s ease-out var(--play); }
.heart-box.is-sad  .heart-jump { animation: sad .8s ease-in-out var(--play); }
.heart-box.is-love .heart-jump { animation: jump var(--jump-time) linear .7s infinite var(--play); }
.heart-box.is-love .heart-ring { animation: ring calc(var(--jump-time) * 2) ease-out .7s infinite var(--play); }
@keyframes wave { to { transform: translateX(-64px); } }
@keyframes beat { 0%, 60%, 100% { transform: scale(1); } 15% { transform: scale(1.08); } 30% { transform: scale(1); } 45% { transform: scale(1.05); } }
@keyframes pop  { 0% { transform: scale(1); } 30% { transform: scale(1.22); } 55% { transform: scale(.94); } 75% { transform: scale(1.05); } 100% { transform: scale(1); } }
@keyframes sad  {
0%, 100% { transform: translateX(0) rotate(0); }
15% { transform: translateX(-4%) rotate(-5deg); }
30% { transform: translateX(4%) rotate(5deg); }
45% { transform: translateX(-3%) rotate(-3deg); }
60% { transform: translateX(2%) rotate(2deg); }
80% { transform: translateX(0) rotate(0) scale(.94); }
}
@keyframes jump {
0%   { transform: translateY(0) scale(1.08, .9); animation-timing-function: cubic-bezier(.2, .7, .4, 1); }
50%  { transform: translateY(calc(var(--jump-height) * -1)) scale(.95, 1.06); animation-timing-function: cubic-bezier(.6, 0, .8, .4); }
100% { transform: translateY(0) scale(1.08, .9); }
}
@keyframes shadow-jump { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(.6); opacity: .5; } }
@keyframes ring { from { opacity: .8; transform: scale(1); } to { opacity: 0; transform: scale(1.7); } }

.calc-form { display: flex; flex-direction: column; align-items: center; }
.calc-fields { display: flex; flex-wrap: wrap; justify-content: center; gap: 14px; }
.calc-input {
width: min(240px, 78vw); padding: .8em 1.1em; border: 0; border-radius: 999px; outline: none;
font: 500 1.15rem/1 var(--font); text-align: center;
color: var(--input-text); background: var(--input-bg); box-shadow: 0 5px 0 var(--shadow);
transition: transform .25s cubic-bezier(.34, 1.56, .64, 1), box-shadow .25s ease;
}
.calc-input::placeholder { color: var(--placeholder); opacity: 1; }
.calc-input:focus { transform: translateY(-2px) scale(1.03); box-shadow: 0 8px 0 var(--shadow), 0 0 0 4px rgba(255, 255, 255, .45); }
.calc-input.is-invalid { animation: shake .45s ease; box-shadow: 0 5px 0 var(--shadow), 0 0 0 4px var(--pct); }
@keyframes shake { 0%, 100% { transform: translateX(0); } 20% { transform: translateX(-8px); } 40% { transform: translateX(8px); } 60% { transform: translateX(-5px); } 80% { transform: translateX(5px); } }
.calc-msg {
margin: 12px 0 0; min-height: 1.4em; font-size: 1.05rem; font-weight: 500; color: var(--text);
opacity: 0; transform: translateY(-6px);
transition: opacity .3s ease, transform .4s cubic-bezier(.34, 1.5, .64, 1);
}
.calc-msg.is-visible { opacity: 1; transform: none; }
.btn:disabled { cursor: progress; transform: none; box-shadow: 0 3px 0 var(--shadow); opacity: .85; }

@media (max-height: 640px) {
:root { --image-width: min(52vw, 260px); --content-gap: 16px; --heading-size: clamp(1.8rem, 5.5vw, 2.6rem); }
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; transition-delay: 0s !important; }
}


/* =====================================================================
   PHONE LAYOUT (desktop is untouched by everything below)
   ===================================================================== */

/* portrait phones + landscape phones: scrolling fallback and bigger tap targets */
@media (max-width: 600px), (orientation: landscape) and (max-height: 500px) and (pointer: coarse) {
/* if a slide is taller than the screen, let it scroll instead of cutting it off */
.slide { overflow-x: hidden; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none; }
.slide::-webkit-scrollbar { display: none; }
.slide-content { margin-block: auto; }   /* keeps content centered when it fits */

/* keep the decorative layers in place while a slide scrolls */
.bg, .fireworks, .rise { position: fixed; }

/* bigger tap targets for the dots (about 44px tall) */
:root { --dot-gap: 14px; }
.dot { padding-block: 17px; }
}

/* portrait phones: sizing */
@media (max-width: 600px) {
:root {
    --heading-size: clamp(1.75rem, 8vw, 2.4rem);
    --image-width: min(80vw, 340px);
    --image-radius: 22px;
    --image-border: 5px;
    --content-gap: 20px;
    --button-size: 1.15rem;
    --heart-size: clamp(120px, 22vh, 200px);
    --dots-top: 12px;
}
h1.el { overflow-wrap: break-word; }
h1.huge-text { font-size: calc(var(--heading-size) * .67); }  /* same 2:3 ratio as desktop */
.slide-content {
    padding: calc(52px + env(safe-area-inset-top, 0px)) 20px calc(32px + env(safe-area-inset-bottom, 0px));
}
.slide-img { max-height: 38vh; max-height: 38dvh; }   /* tall photos get cropped instead of pushing the button off-screen */
.edit-img { width: min(88vw, 1000px); }
/* YouTube embed: keep it square like on desktop, but never wider than the screen */
.slide-figure iframe { display: block; width: min(88vw, 540px); height: auto; aspect-ratio: 1 / 1; }
.calc-input { width: min(280px, 82vw); }
}

/* landscape phones: sizing */
@media (orientation: landscape) and (max-height: 500px) and (pointer: coarse) {
:root {
    --heading-size: clamp(1.4rem, 4vw, 1.9rem);
    --image-width: min(36vw, 200px);
    --content-gap: 10px;
    --heart-size: clamp(90px, 32vh, 140px);
    --dots-top: 6px;
}
h1.huge-text { font-size: calc(var(--heading-size) * .67); }
.slide-content {
    padding: calc(44px + env(safe-area-inset-top, 0px)) max(24px, env(safe-area-inset-right, 0px)) 24px max(24px, env(safe-area-inset-left, 0px));
}
.slide-img { max-height: 44vh; }
.edit-img { width: min(78vw, calc(44vh * 16 / 9)); }
.slide-figure iframe { display: block; width: min(78vw, 56vh); height: auto; aspect-ratio: 1 / 1; }
}