:root {
  --bg: #ffd9c2;
  --accent: #ff6b3d;
  --ink: #2a1410;
  --paper: #fffaf5;
  --radius: 20px;
  font-family: 'Bricolage Grotesque', system-ui, -apple-system, sans-serif;
}
[data-theme='peach'] { --bg: #ffd9c2; --accent: #ff6b3d; --ink: #2a1410; }
[data-theme='grape'] { --bg: #e3d4ff; --accent: #7a3cff; --ink: #1c1033; }
[data-theme='lime'] { --bg: #ddf7b5; --accent: #2e9e3f; --ink: #10240f; }
[data-theme='berry'] { --bg: #ffc9dd; --accent: #e0246b; --ink: #2e0a1b; }
[data-theme='red'] { --bg: #ffd3cc; --accent: #d92b2b; --ink: #2e0a0a; }
[data-theme='sky'] { --bg: #cfe4ff; --accent: #1f7ae0; --ink: #0b1f3a; }
[data-theme='teal'] { --bg: #c8f1ea; --accent: #0e9e8e; --ink: #06302b; }
/* A colour picked on the wheel: --accent is set on the page, the tint and the dark text are mixed from it. */
[data-theme='custom'] { --bg: color-mix(in srgb, var(--accent) 20%, white); --ink: color-mix(in srgb, var(--accent) 22%, #14110f); }

* { box-sizing: border-box; }
html, body { margin: 0; }
body { background: var(--bg); color: var(--ink); min-height: 100dvh; animation: drift 48s linear infinite; }
/* The page background drifts slowly through the card colours on a loop. Cards and the opening keep their own colour. */
@keyframes drift {
  0%, 100% { background-color: #ffd9c2; }
  16% { background-color: #ffc9dd; }
  33% { background-color: #e3d4ff; }
  50% { background-color: #cfe4ff; }
  66% { background-color: #c8f1ea; }
  83% { background-color: #ddf7b5; }
}
@media (prefers-reduced-motion: reduce) { body { animation: none; } }
.hidden { display: none !important; }

.wrap { max-width: 560px; margin: 0 auto; padding: 24px 16px 64px; }
.wrap.wide { max-width: 980px; }
.brand { font-weight: 800; font-size: 20px; letter-spacing: -0.02em; color: var(--ink); text-decoration: none; }
/* The icon sits before the name wherever the name is a link: the header, the footer and the top of the card pages.
   Its tile takes the page's own colour (the heart is a hole that shows it through), so it never clashes with a
   blue or green page the way a fixed orange tile does. The browser tab and social files keep the orange one. */
a.brand::before { content: ''; display: inline-block; width: 1.5em; height: 1.5em; margin-right: 0.4em; vertical-align: -0.38em; border-radius: 24%; background: var(--accent) url(/mark.svg) center / contain no-repeat; transition: background-color 0.6s; }
h1 { font-size: clamp(36px, 9vw, 56px); line-height: 1; letter-spacing: -0.04em; margin: 28px 0 12px; }
h2 { font-size: 22px; letter-spacing: -0.02em; margin: 0 0 12px; }
p.lead { font-size: 18px; margin: 0 0 24px; opacity: 0.8; }
.muted { opacity: 0.65; font-size: 14px; }

.panel { background: var(--paper); border-radius: var(--radius); padding: 20px; margin-bottom: 16px; box-shadow: 0 2px 0 rgba(0, 0, 0, 0.08); }
label { display: block; font-weight: 600; font-size: 14px; margin: 14px 0 6px; }
label:first-child { margin-top: 0; }
input, textarea, select {
  width: 100%; font: inherit; font-size: 16px; padding: 12px 14px; border-radius: 12px;
  border: 2px solid rgba(0, 0, 0, 0.12); background: #fff; color: var(--ink);
}
input:focus, textarea:focus { outline: none; border-color: var(--accent); }
textarea { min-height: 110px; resize: vertical; }

button, .btn {
  font: inherit; font-weight: 700; font-size: 16px; border: 0; border-radius: 999px; padding: 14px 22px;
  background: var(--accent); color: var(--on-accent, #fff); cursor: pointer; text-decoration: none; display: inline-block; text-align: center;
}
button:disabled { opacity: 0.5; cursor: default; }
button.full, .btn.full { width: 100%; margin-top: 18px; }
button.ghost, .btn.ghost { background: transparent; color: var(--ink); border: 2px solid rgba(0, 0, 0, 0.15); padding: 10px 16px; font-size: 14px; }
.row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
input.invalid, textarea.invalid { border-color: #c62828; background: #fff6f5; }
.field-error { color: #c62828; font-weight: 600; font-size: 13px; }
.field-error:not(:empty) { margin-top: 6px; }
dialog.ask { border: 0; border-radius: var(--radius); padding: 24px; max-width: min(380px, calc(100vw - 32px)); background: var(--paper); color: var(--ink); box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25); font: inherit; }
dialog.ask::backdrop { background: rgba(20, 10, 10, 0.45); }
dialog.ask p { margin: 0 0 20px; font-size: 18px; font-weight: 600; line-height: 1.35; }
dialog.ask .row { justify-content: flex-end; }
dialog.ask .ghost { padding: 14px 22px; font-size: 16px; }
.toast { position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 20; max-width: calc(100vw - 32px); background: var(--ink); color: #fff; padding: 14px 20px; border-radius: 14px; font-weight: 600; font-size: 15px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25); }
.mail { border: 2px solid rgba(0, 0, 0, 0.1); border-radius: 14px; background: #fff; margin-top: 8px; overflow: hidden; }
.mail .meta { padding: 12px 14px; font-size: 13px; border-bottom: 2px solid rgba(0, 0, 0, 0.06); line-height: 1.5; overflow-wrap: anywhere; }
.mail .meta b { font-weight: 700; }
.mail .body { padding: 22px 16px; text-align: center; }
.mail .body h3 { margin: 0 0 8px; font-size: 20px; letter-spacing: -0.02em; }
.mail .body p { margin: 0 0 16px; font-size: 14px; line-height: 1.5; opacity: 0.8; white-space: pre-wrap; overflow-wrap: anywhere; }
.mail .body span.cta { display: inline-block; background: var(--accent); color: var(--on-accent, #fff); font-weight: 700; font-size: 14px; padding: 10px 20px; border-radius: 999px; }
/* The date and time picker. */
.when-trigger { width: 100%; text-align: left; background: #fff; color: var(--ink); border: 2px solid rgba(0, 0, 0, 0.12); border-radius: 12px; padding: 12px 14px; font-weight: 600; }
.when-trigger.empty { font-weight: 400; opacity: 0.7; }
.when-panel { margin-top: 8px; max-width: 340px; padding: 14px; background: #fff; border: 2px solid rgba(0, 0, 0, 0.12); border-radius: 16px; }
.when-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.when-head b { font-size: 16px; }
.when button.step { width: 36px; height: 36px; padding: 0 0 2px; border-radius: 50%; background: var(--bg); color: var(--ink); font-size: 20px; line-height: 1; }
.when-days { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; text-align: center; }
.when-days .dow { font-size: 12px; font-weight: 700; opacity: 0.5; padding: 4px 0; }
.when-days button { aspect-ratio: 1; padding: 0; border-radius: 50%; background: transparent; color: var(--ink); font-size: 15px; font-weight: 600; }
.when-days button:hover:not(:disabled) { background: var(--bg); }
.when-days button.today { box-shadow: inset 0 0 0 2px var(--ink); }
.when-days button[aria-pressed='true'] { background: var(--accent); color: var(--on-accent, #fff); box-shadow: none; }
.when-days button:disabled { opacity: 0.25; }
.when-foot { display: flex; align-items: flex-end; gap: 8px; margin-top: 14px; }
.when-foot label { flex: 1; margin: 0; font-size: 13px; }
.when-foot select { margin-top: 4px; padding: 10px 12px; font-weight: 600; }
.when-foot button { padding: 11px 18px; font-size: 15px; }
.gone { text-align: center; padding: 18dvh 16px 0; max-width: 520px; margin: 0 auto; }
.error { color: #b00020; font-weight: 600; font-size: 14px; margin-top: 10px; min-height: 18px; }
.ok { color: #0a7a2f; font-weight: 600; font-size: 14px; margin-top: 10px; }

.swatches { display: flex; flex-wrap: wrap; gap: 10px; }
.swatches button { width: 44px; height: 44px; padding: 0; border-radius: 50%; border: 3px solid transparent; }
.swatches button[aria-pressed='true'], .swatches .wheel[aria-pressed='true'] { border-color: var(--ink); }
.swatches .wheel {
  position: relative; display: block; width: 44px; height: 44px; margin: 0; border-radius: 50%; border: 3px solid transparent; cursor: pointer;
  background: conic-gradient(hsl(8 90% 62%), hsl(42 96% 58%), hsl(95 55% 50%), hsl(172 72% 40%), hsl(214 78% 55%), hsl(264 88% 64%), hsl(332 78% 56%), hsl(8 90% 62%)) padding-box;
}
/* The middle of the ring: a plus until a custom colour is picked, then that colour. */
.swatches .wheel::after { content: '+'; position: absolute; inset: 7px; border-radius: 50%; background: var(--paper); color: var(--ink); display: grid; place-items: center; font-size: 18px; font-weight: 800; line-height: 1; pointer-events: none; }
.swatches .wheel[aria-pressed='true']::after { content: ''; background: var(--accent); }
.swatches .wheel input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; padding: 0; border: 0; cursor: pointer; }

.wall { columns: 2 240px; column-gap: 14px; }
.note { break-inside: avoid; background: var(--paper); border-radius: 16px; padding: 14px; margin-bottom: 14px; box-shadow: 0 2px 0 rgba(0, 0, 0, 0.08); }
.note img { width: 100%; border-radius: 10px; display: block; margin-bottom: 10px; }
.note p { margin: 0 0 8px; white-space: pre-wrap; overflow-wrap: anywhere; }
.note .who { font-weight: 700; font-size: 14px; color: var(--accent); }
.note .acts { display: flex; gap: 6px; justify-content: flex-end; margin-bottom: 10px; }
.note .acts button { padding: 6px 12px; font-size: 13px; }

.gifgrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; max-height: 260px; overflow: auto; margin-top: 10px; }
.gifgrid img { width: 100%; height: 90px; object-fit: cover; border-radius: 8px; cursor: pointer; }
.preview { max-width: 160px; border-radius: 10px; margin-top: 10px; display: block; }
.linkbox { display: flex; gap: 8px; }
.linkbox input { font-size: 14px; }

/* The intro: cream screen, the icon pops in, the card rises out of the envelope, the name fades up, the heart
   beats twice, then it all lifts away. About two and a half seconds. */
.splash { position: fixed; inset: 0; z-index: 100; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 16px; background: var(--paper); animation: splash-out 0.5s ease-in 2.05s forwards; }
.splash-icon { width: 112px; height: 112px; overflow: hidden; border-radius: 24px; animation: splash-pop 0.6s cubic-bezier(0.2, 1.5, 0.4, 1) both; }
.splash-card { animation: splash-rise 0.8s cubic-bezier(0.2, 1.35, 0.4, 1) 0.45s both; }
.splash-heart { transform-box: fill-box; transform-origin: center; animation: splash-beat 0.6s ease-in-out 1.3s 2; }
.splash-name { font-size: 30px; font-weight: 800; letter-spacing: -0.03em; color: #2a1410; animation: splash-up 0.5s ease-out 0.9s both; }
@keyframes splash-beat { 30% { transform: scale(1.22); } 60% { transform: scale(0.95); } }
@keyframes splash-pop { from { transform: scale(0.4) rotate(-8deg); opacity: 0; } }
@keyframes splash-rise { from { transform: translateY(26px); } }
@keyframes splash-up { from { transform: translateY(10px); opacity: 0; } }
@keyframes splash-out { to { opacity: 0; transform: scale(1.04); visibility: hidden; } }

/* The nav and footer on the site's own pages. */
.nav { display: flex; align-items: center; justify-content: space-between; gap: 12px; max-width: 1040px; margin: 0 auto; padding: 18px 20px; }
.nav nav { display: flex; align-items: center; gap: 20px; }
.nav nav a:not(.btn), .foot a { color: var(--ink); font-weight: 600; font-size: 15px; text-decoration: none; }
.nav nav a:not(.btn):hover, .foot a:hover, .nav nav a[aria-current]:not(.btn) { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 5px; }
.nav .btn { padding: 10px 18px; font-size: 15px; white-space: nowrap; }
.foot { text-align: center; padding: 32px 16px 44px; font-size: 15px; line-height: 2; }
.foot .brand { font-size: inherit; font-weight: 800; }
@media (max-width: 420px) {
  .nav { padding: 14px 14px; gap: 8px; }
  .nav .brand { font-size: 17px; }
  .nav nav { gap: 10px; }
  .nav nav a:not(.btn) { font-size: 14px; }
  .nav .btn { padding: 9px 12px; font-size: 14px; }
}

/* The home page is cream, in bands that alternate with a tint. Only the block at the top (the nav and the hero)
   changes colour, following the card showing in the hero. */
body.matched { animation: none; background: var(--paper); }
body.matched .masthead { background: var(--bg); transition: background-color 0.6s; }
body.matched .foot { color: var(--ink); }
/* The tag above the headline: a small label stuck on at an angle, its line written out by hand from left to right. */
.pill { display: inline-block; margin: 0 0 16px; padding: 3px 16px 5px; border-radius: 10px; text-align: left; background: var(--paper); box-shadow: 0 2px 0 rgba(0, 0, 0, 0.08); transform: rotate(-2deg); font-family: 'Caveat', cursive; font-weight: 700; font-size: 23px; line-height: 1.2; white-space: nowrap; }
#written { display: inline-block; animation: write 1.3s cubic-bezier(0.45, 0, 0.55, 1) both; transition: opacity 0.4s; }
#written.fading { opacity: 0; }
@keyframes write { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 -4px 0 0); } }
@media (prefers-reduced-motion: reduce) { #written { animation: none; } }
.hero {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 320px); grid-template-areas: 'text card' 'modes card';
  column-gap: 64px; align-items: center; max-width: 960px; margin: 0 auto; padding: 40px 20px 64px;
}
.hero-text { grid-area: text; align-self: end; }
.hero h1 { font-size: clamp(44px, 7.4vw, 80px); margin: 0 0 16px; }
.hero .lead { font-size: 20px; margin: 0 0 26px; max-width: 30em; }
.hero-foot { grid-area: modes; align-self: start; }
.modes { display: grid; gap: 12px; max-width: 440px; }
.modes button { display: flex; align-items: center; gap: 16px; text-align: left; background: var(--paper); color: var(--ink); border-radius: 22px; padding: 16px 20px; box-shadow: 0 4px 0 rgba(0, 0, 0, 0.1); border: 3px solid transparent; transition: transform 0.15s, border-color 0.15s; }
.modes button:hover, .modes button:focus-visible { border-color: var(--ink); transform: translateY(-3px); outline: none; }
.modes .mode-icon { flex: 0 0 52px; height: 52px; }
.modes .mode-icon svg { display: block; width: 100%; height: 100%; }
.modes b { display: block; font-size: 20px; letter-spacing: -0.02em; margin-bottom: 2px; }
.modes span { display: block; font-weight: 400; font-size: 15px; line-height: 1.35; opacity: 0.75; }
.hero-foot .muted { margin: 16px 0 0; font-size: 15px; }
/* The card beside the headline. It turns over to the next one, like a card in your hand. */
.hero-side { grid-area: card; text-align: center; }
.hero-card { width: 100%; margin: 0 auto 16px; perspective: 1200px; }
.hero-card .cover { animation: turn-in 0.3s ease-out; transition: transform 0.3s ease-in; }
.hero-card.turn .cover { transform: rotateY(90deg); }
@keyframes turn-in { from { transform: rotateY(-90deg); } }
@media (prefers-reduced-motion: reduce) { .hero-card .cover { animation: none; transition: none; } }
.hero-side b { display: block; font-size: 18px; margin-bottom: 10px; }
/* "Start with this one": a ring pulses out from it and the arrow nudges, so it reads as the thing to press. */
.pick-btn { padding: 12px 20px; font-size: 15px; transition: transform 0.15s, background-color 0.6s; animation: ring 2s ease-out infinite; }
.pick-btn:hover, .pick-btn:focus-visible { transform: translateY(-2px) scale(1.04); outline: none; }
.pick-btn span { display: inline-block; margin-left: 4px; animation: arrow 0.7s ease-in-out infinite alternate; }
@keyframes ring { from { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 55%, transparent); } to { box-shadow: 0 0 0 14px transparent; } }
@keyframes arrow { to { transform: translateX(5px); } }
@media (prefers-reduced-motion: reduce) { .pick-btn, .pick-btn span { animation: none; } }
@media (max-width: 760px) {
  .hero { grid-template-columns: minmax(0, 1fr); grid-template-areas: 'text' 'card' 'modes'; row-gap: 18px; padding: 12px 16px 44px; }
  .hero .lead { font-size: 18px; margin-bottom: 0; }
  .hero-card { width: clamp(170px, 52vw, 320px); margin-bottom: 12px; }
  .hero-side b { display: inline; font-size: 15px; margin: 0 8px 0 0; }
  .pick-btn { padding: 8px 14px; font-size: 14px; }
  .modes { max-width: none; }
  .modes button { padding: 13px 16px; }
}
/* On a phone the card stays small enough that both buttons are on the first screen. */
@media (max-width: 460px) { .hero-card { width: 170px; } }

/* The screen every "Start a card" button lands on: the two choices and nothing else. */
.choose { max-width: 640px; margin: 0 auto; padding: 9dvh 16px 72px; text-align: center; }
.choose h1 { margin: 0 0 28px; }
.choose .modes { max-width: none; grid-template-columns: 1fr 1fr; gap: 16px; }
.choose .modes button { flex-direction: column; gap: 14px; text-align: center; padding: 32px 18px 28px; border-radius: 26px; }
.choose .modes .mode-icon { flex: 0 0 76px; width: 76px; }
.choose .modes b { font-size: 24px; margin-bottom: 6px; }
.choose .muted { margin: 22px 0 0; font-size: 15px; }
@media (max-width: 460px) { .choose .modes { grid-template-columns: 1fr; } }

.band { padding: 64px 0; text-align: center; color: var(--ink); }
/* The tinted bands fade slowly through the card colours, all in step: out through the six and back the same way,
   so the loop never jumps from green straight to peach. The block at the foot of the page runs the same loop. */
.band.tint { background: var(--bg); animation: fade-tint 90s linear infinite; }
@keyframes fade-tint {
  0%, 100% { background-color: #ffd9c2; }
  10%, 90% { background-color: #ffc9dd; }
  20%, 80% { background-color: #e3d4ff; }
  30%, 70% { background-color: #cfe4ff; }
  40%, 60% { background-color: #c8f1ea; }
  50% { background-color: #ddf7b5; }
}
@media (prefers-reduced-motion: reduce) { .band.tint { animation: none; } }
.band.cream { background: var(--paper); }
/* The close: a rounded block, like a card laid on the cream page, in the same soft tint as the bands above. */
.band.last { padding: 28px 20px 36px; }
.closer { max-width: 1000px; margin: 0 auto; padding: 76px 20px; border-radius: 36px; background: var(--bg); animation: fade-tint 90s linear infinite; }
.closer h2 { margin-bottom: 14px; }
.closer .lead { margin: 0 20px 26px; }
@media (prefers-reduced-motion: reduce) { .closer { animation: none; } }
.band > .in { max-width: 1000px; margin: 0 auto; padding: 0 20px; }
.band h2 { font-size: clamp(28px, 5vw, 42px); letter-spacing: -0.035em; line-height: 1.05; margin: 0 20px 28px; }
.band .lead { margin: 20px 20px 0; }
/* A strip of finished cards that drifts sideways and stops under a finger or a pointer. */
.strip-wrap { overflow: hidden; }
.strip { display: flex; width: max-content; padding: 8px 0 12px; animation: strip 70s linear infinite; }
.strip:hover, .strip.held { animation-play-state: paused; }
@keyframes strip { to { transform: translateX(-50%); } }
.tile { flex: 0 0 auto; width: 168px; margin-right: 20px; padding: 0; border-radius: 12px; background: none; color: inherit; font-size: 15px; transition: transform 0.15s; }
.tile:hover, .tile:focus-visible { transform: translateY(-4px); outline: none; }
.tile span { display: block; margin-top: 12px; }
@media (max-width: 600px) { .tile { width: 132px; margin-right: 14px; } }
@media (prefers-reduced-motion: reduce) {
  .strip-wrap { overflow-x: auto; }
  .strip { animation: none; padding-left: 20px; }
}
/* The switch above the sample phone: group card or a card from one person. */
.switch { display: inline-flex; gap: 4px; margin: 0 0 24px; padding: 5px; border-radius: 999px; background: var(--paper); box-shadow: 0 2px 0 rgba(0, 0, 0, 0.08); }
.switch button { padding: 10px 18px; font-size: 15px; background: transparent; color: var(--ink); }
.switch button[aria-pressed='true'] { background: var(--accent); color: var(--on-accent, #fff); }
/* The sample opening, in a frame the shape of a phone. */
.phone { width: min(320px, 82vw); aspect-ratio: 9 / 16; margin: 0 auto; border-radius: 30px; overflow: hidden; background: var(--paper); box-shadow: 0 0 0 6px var(--ink), 0 24px 50px rgba(0, 0, 0, 0.22); }
.phone iframe { display: block; width: 100%; height: 100%; border: 0; }
.counter { display: flex; justify-content: center; gap: clamp(28px, 8vw, 80px); }
.counter b { display: block; font-size: clamp(44px, 9vw, 76px); letter-spacing: -0.05em; line-height: 1; }
.counter span { display: block; margin-top: 6px; font-weight: 600; }
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; text-align: left; }
.steps .panel { margin: 0; padding: 24px; }
.steps .top { display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 14px; }
.steps i { display: grid; place-items: center; width: 36px; height: 36px; border-radius: 50%; background: var(--accent); color: var(--on-accent, #fff); font-style: normal; font-weight: 800; }
.step-icon { width: 64px; height: 64px; }
.step-icon svg { display: block; width: 100%; height: 100%; }
/* The steps slide up one after another when the section is first scrolled to, and each number pops as it lands. */
.steps .panel { transition: opacity 0.5s ease-out, transform 0.5s cubic-bezier(0.2, 1.3, 0.4, 1), box-shadow 0.15s; }
.steps .panel:nth-child(2) { transition-delay: 0.15s; }
.steps .panel:nth-child(3) { transition-delay: 0.3s; }
.steps .panel i { transition: transform 0.4s cubic-bezier(0.2, 1.8, 0.4, 1) 0.25s; }
.steps .panel:nth-child(2) i { transition-delay: 0.4s; }
.steps .panel:nth-child(3) i { transition-delay: 0.55s; }
.steps.wait .panel { opacity: 0; transform: translateY(32px); }
.steps.wait .panel i { transform: scale(0); }
.steps:not(.wait) .panel:hover { transform: translateY(-4px); transition-delay: 0s; }
.steps h3 { font-size: 22px; letter-spacing: -0.02em; margin: 0 0 8px; }
.steps p { margin: 0; line-height: 1.45; opacity: 0.8; }
@media (max-width: 700px) { .steps { grid-template-columns: 1fr; } }
.swap { display: inline-block; color: var(--accent); animation: swap-in 0.35s ease-out; }
@keyframes swap-in { from { opacity: 0; transform: translateY(0.4em); } }
.band .btn.big, .page .btn.big { padding: 17px 30px; font-size: 18px; }

/* The "who's it from" box that follows picking a card off the home page. */
dialog.chooser { width: 400px; text-align: center; }
dialog.chooser .cover { width: 120px; margin: 0 auto 16px; }
dialog.chooser .modes { margin-bottom: 14px; }
dialog.chooser .modes button { box-shadow: none; border-color: rgba(0, 0, 0, 0.12); background: #fff; }
dialog.chooser .modes button:hover, dialog.chooser .modes button:focus-visible { border-color: var(--ink); }

/* Pricing and help. */
.page { max-width: 760px; margin: 0 auto; padding: 24px 16px 40px; }
.page > h1, .page > .lead { text-align: center; }
.page > .lead { margin-bottom: 32px; }
.page section { margin-top: 44px; }
.page section > h2 { font-size: 26px; }
.page .panel p { line-height: 1.5; margin: 0 0 12px; }
.page .panel p:last-child { margin-bottom: 0; }
.plans { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.plans .panel { margin: 0; display: flex; flex-direction: column; padding: 26px; }
.plans .cost { font-size: 40px; font-weight: 800; letter-spacing: -0.04em; line-height: 1; margin: 6px 0 18px; }
.plans .cost small { font-size: 16px; font-weight: 600; letter-spacing: 0; opacity: 0.7; }
.ticks { list-style: none; margin: 0 0 auto; padding: 0; }
.ticks li { position: relative; padding: 0 0 10px 28px; line-height: 1.35; }
.ticks li::before { content: '✓'; position: absolute; left: 0; color: var(--accent); font-weight: 800; }
@media (max-width: 600px) { .plans { grid-template-columns: 1fr; } }
/* The note on the pricing page about why a card from one person is free. */
.care { text-align: center; padding: 40px 28px 36px; }
.care-heart { width: 56px; height: 56px; margin: 0 auto 14px; }
.care-heart svg { display: block; width: 100%; height: 100%; }
.care h2 { font-size: clamp(26px, 5vw, 34px); letter-spacing: -0.03em; line-height: 1.1; margin: 0 0 14px; }
.page .care p { font-size: 18px; max-width: 32em; margin: 0 auto 10px; }
.qa { padding: 6px 20px; }
.qa details { border-bottom: 2px solid rgba(0, 0, 0, 0.07); }
.qa details:last-child { border-bottom: 0; }
.qa summary { display: flex; justify-content: space-between; gap: 16px; padding: 16px 0; font-weight: 700; font-size: 17px; cursor: pointer; list-style: none; }
.qa summary::-webkit-details-marker { display: none; }
.qa summary::after { content: '+'; font-size: 22px; line-height: 1; color: var(--accent); }
.qa details[open] summary::after { content: '–'; }
.qa details p { margin: 0 0 18px; line-height: 1.5; opacity: 0.85; }
.qa a, .page .panel p a, .page > p a { color: inherit; font-weight: 700; }
.inline-form { display: flex; gap: 8px; }
.inline-form button { flex: 0 0 auto; }
@media (max-width: 460px) { .inline-form { flex-direction: column; } }

/* The manage page: the card stays in view on one side while the steps scroll on the other. Stacks on a phone. */
.manage { display: grid; grid-template-columns: 280px minmax(0, 560px); gap: 40px; align-items: start; justify-content: center; margin-top: 24px; }
.manage aside { position: sticky; top: 24px; }
.manage aside .hero-cover { max-width: none; margin-top: 0; }
/* The card's journey, like a parcel tracker: filled dots are done, the pulsing one is where it's at. */
.track { list-style: none; margin: 20px 0 14px; padding: 0; }
.track li { position: relative; padding: 0 0 18px 32px; opacity: 0.45; }
.track li.done, .track li.current { opacity: 1; }
.track li::before { content: ''; position: absolute; left: 0; top: 2px; width: 16px; height: 16px; border-radius: 50%; border: 3px solid var(--ink); box-sizing: border-box; background: transparent; }
.track li::after { content: ''; position: absolute; left: 7px; top: 20px; bottom: 0; width: 2px; background: var(--ink); opacity: 0.2; }
.track li:last-child { padding-bottom: 0; }
.track li:last-child::after { display: none; }
.track li.done::before { background: var(--accent); border-color: var(--accent); }
.track li.done::after { background: var(--accent); opacity: 1; }
.track li.current::before { border-color: var(--accent); animation: here 1.6s ease-out infinite; }
.track b { display: block; font-size: 15px; line-height: 1.3; }
.track span { display: block; font-size: 13px; opacity: 0.7; min-height: 0; }
@keyframes here { from { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 60%, transparent); } to { box-shadow: 0 0 0 10px transparent; } }
@media (prefers-reduced-motion: reduce) { .track li.current::before { animation: none; } }
.manage aside .lead { font-size: 16px; margin: 16px 0 8px; }
@media (min-width: 861px) { .manage .look-preview { display: none; } }
@media (max-width: 860px) {
  .manage { grid-template-columns: minmax(0, 560px); gap: 8px; }
  .manage aside { position: static; }
  .manage aside .hero-cover { max-width: 200px; }
}

/* Background and icon pickers scroll sideways. */
.scroll-wrap { position: relative; }
.designs, .icons { display: flex; gap: 10px; overflow-x: auto; padding: 6px 4px 10px; scroll-padding: 0 4px; scroll-snap-type: x proximity; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.designs::-webkit-scrollbar, .icons::-webkit-scrollbar { display: none; }
.designs button, .icons button { flex: 0 0 auto; scroll-snap-align: start; }
.designs button { width: 84px; }
.nudge { position: absolute; top: 50%; z-index: 2; width: 34px; height: 34px; margin-top: -19px; padding: 0 0 3px; border-radius: 50%; background: var(--paper); color: var(--ink); box-shadow: 0 2px 10px rgba(0, 0, 0, 0.22); font-size: 22px; line-height: 1; }
.nudge.prev { left: -12px; }
.nudge.next { right: -12px; }
.nudge[hidden] { display: none; }
@media (hover: none) { .nudge { display: none; } }

/* The solo card's "how it'll look" preview: the cover beside the message as it appears in the opening. */
.mini-stage { display: flex; gap: 16px; align-items: center; flex-wrap: wrap; background: var(--bg); border-radius: 18px; padding: 18px; }
.mini-stage .mini-cover { flex: 0 0 104px; }
.mini-stage .slide { flex: 1 1 180px; animation: none; }
.mini-stage .bubble p { font-size: 17px; }
.mini-stage .bubble p.empty { opacity: 0.45; }

.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chips button { background: #fff; color: var(--ink); border: 2px solid rgba(0, 0, 0, 0.12); padding: 9px 14px; font-size: 14px; }
.chips button[aria-pressed='true'] { background: var(--ink); color: #fff; border-color: var(--ink); }
.designs button { padding: 0; background: none; border-radius: 8px; outline: 3px solid transparent; outline-offset: 3px; }
.designs button[aria-pressed='true'] { outline-color: var(--ink); }
.hero-cover { max-width: 220px; margin: 20px 0 8px; }

/* Card covers. Everything is in cqw (percent of the cover's own width) so a cover scales to any size. */
/* Restated on anything with its own theme, so a card can sit on a page of a different colour. */
:root, [data-theme] { --i1: var(--accent); --i2: var(--ink); --i3: var(--bg); --face: var(--paper); }
svg .a { fill: var(--i1); }
svg .b { fill: var(--i2); }
svg .c { fill: var(--i3); }
svg .y { fill: #ffc93c; }
svg .f { fill: var(--face); }
svg .sa, svg .sb, svg .sc { fill: none; }
svg .sa { stroke: var(--i1); }
svg .sb { stroke: var(--i2); }
svg .sc { stroke: var(--i3); }
svg .sy { stroke: #ffc93c; fill: none; }

.cover { container-type: inline-size; position: relative; width: 100%; aspect-ratio: 5 / 7; }
.face { position: absolute; inset: 0; display: flex; border-radius: 5cqw; overflow: hidden; background: var(--face); color: var(--ink); box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1), 0 1.6cqw 0 rgba(0, 0, 0, 0.12); }
.cover[data-base='bold'] .face { --face: var(--accent); --i1: var(--paper); color: var(--on-accent, #fff); }
.cover .layer, .cover .pattern { position: absolute; inset: 0; width: 100%; height: 100%; }
.inner { position: relative; flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4cqw; padding: 17cqw; text-align: center; }
.cover .icon svg { display: block; width: 36cqw; height: 36cqw; }
.cover[data-noicon] .icon { display: none; }
.cover .line { font-size: calc(11cqw * var(--fit, 1)); font-weight: 800; letter-spacing: -0.03em; line-height: 1; overflow-wrap: anywhere; }
.cover[data-noicon] .line { font-size: calc(14cqw * var(--fit, 1)); }
.cover[data-font='serif'] .line, .font-serif { font-family: 'Fraunces', Georgia, serif; letter-spacing: -0.02em; }
.cover[data-font='hand'] .line, .font-hand { font-family: 'Caveat', cursive; letter-spacing: 0; }
.cover[data-font='hand'] .line { font-size: calc(15cqw * var(--fit, 1)); line-height: 0.9; }
.cover[data-font='round'] .line, .font-round { font-family: 'Fredoka', system-ui, sans-serif; letter-spacing: -0.01em; }
.cover[data-font='poster'] .line, .font-poster { font-family: 'Anton', Impact, sans-serif; font-weight: 400; text-transform: uppercase; letter-spacing: 0.01em; }
.cover[data-font='poster'] .line { font-size: calc(12.5cqw * var(--fit, 1)); line-height: 1.05; }
.cover[data-font='poster'][data-noicon] .line { font-size: calc(16cqw * var(--fit, 1)); }
.cover[data-font='hand'][data-noicon] .line { font-size: calc(19cqw * var(--fit, 1)); }

/* Background motion. Small and slow on purpose. Thumbnails in the picker stay still. */
.pattern .mv { transform-box: fill-box; transform-origin: center; animation: 4s ease-in-out infinite; }
.pattern .float { animation-name: float; }
.pattern .twinkle { animation-name: twinkle; animation-duration: 2.6s; }
.pattern .pulse { animation-name: pulse; animation-duration: 3.2s; }
.pattern .sway { animation-name: sway; animation-duration: 5s; }
.pattern .breathe { animation-name: breathe; animation-duration: 6s; }
.pattern .blink { animation-name: pulse; animation-duration: 1.8s; }
.pattern .slide { transform-box: view-box; animation: slide 7s linear infinite; }
.pattern .slide2 { animation-duration: 10s; }
.pattern .slide3 { animation-duration: 14s; }
@keyframes float { 50% { transform: translateY(-2.4px) rotate(16deg); } }
@keyframes twinkle { 50% { opacity: 0.25; transform: scale(0.7); } }
@keyframes pulse { 50% { opacity: 0.35; } }
@keyframes sway { 50% { transform: translate(1.6px, 3px); } }
@keyframes breathe { 50% { transform: scale(1.1); } }
@keyframes slide { to { transform: translateX(-25px); } }
.pattern .slide-s { transform-box: view-box; animation: slide-s 3.5s linear infinite; }
.pattern .slide-z { transform-box: view-box; animation: slide-z 4s linear infinite; }
@keyframes slide-s { to { transform: translateX(12px); } }
@keyframes slide-z { to { transform: translateX(-10px); } }
@media (prefers-reduced-motion: reduce) { .pattern .mv { animation: none; } }

/* Icon motion, also small and slow. The cake's flame flickers and the sun's rays turn on their own. */
[data-motion] > svg { animation: 3.2s ease-in-out infinite; transform-origin: center; overflow: visible; }
[data-motion='bob'] > svg { animation-name: i-bob; }
[data-motion='float'] > svg { animation-name: i-float; animation-duration: 4.5s; }
[data-motion='beat'] > svg { animation-name: i-beat; animation-duration: 1.8s; }
[data-motion='swing'] > svg { animation-name: i-swing; animation-duration: 2.4s; transform-origin: 50% 12%; }
svg .flick { transform-box: fill-box; transform-origin: 50% 100%; animation: i-flick 0.45s ease-in-out infinite alternate; }
svg .spin { transform-box: view-box; transform-origin: center; animation: i-spin 16s linear infinite; }
@keyframes i-bob { 50% { transform: translateY(-4%); } }
@keyframes i-float { 50% { transform: translate(3%, -7%) rotate(4deg); } }
@keyframes i-beat { 50% { transform: scale(1.08); } }
@keyframes i-swing { 25% { transform: rotate(7deg); } 75% { transform: rotate(-7deg); } }
@keyframes i-flick { to { transform: scale(0.82, 1.15); } }
@keyframes i-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { [data-motion] > svg, svg .flick, svg .spin { animation: none; } }


.look-preview { max-width: 240px; margin: 0 auto 6px; }
.icons button { background: #fff; color: var(--ink); border: 2px solid rgba(0, 0, 0, 0.12); border-radius: 14px; padding: 8px; width: 62px; height: 62px; font-size: 13px; }
.icons button svg { display: block; width: 100%; height: 100%; }
.icons button[aria-pressed='true'] { border-color: var(--ink); background: var(--bg); }
.chips button.font-hand { font-size: 18px; padding-top: 6px; padding-bottom: 6px; }

/* The opening page is one colour edge to edge, the card's own, so the stage doesn't sit in a box of another colour. */
body.opening-page { animation: none; background: var(--bg); }
#scene-cover.opening .hint { opacity: 0; animation: none; transition: opacity 0.2s; }

/* The opening: a 9:16 stage so a screen recording is already a vertical video. */
.stage {
  position: relative; height: 100dvh; aspect-ratio: 9 / 16; max-width: 100vw; margin: 0 auto;
  overflow: hidden; background: var(--bg); user-select: none; -webkit-tap-highlight-color: transparent;
}
.scene { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 56px 24px 32px; text-align: center; }
.for { font-size: 22px; margin: 0 0 28px; }
.hint { margin-top: 28px; font-weight: 600; animation: pulse 1.4s infinite; }
@keyframes pulse { 50% { opacity: 0.35; } }

.envelope {
  position: relative; width: 240px; height: 160px; padding: 0; border-radius: 14px; background: var(--paper);
  box-shadow: 0 14px 0 rgba(0, 0, 0, 0.1); animation: bob 2.2s ease-in-out infinite;
}
.envelope::before {
  content: ''; position: absolute; inset: 0 0 auto 0; height: 0; border-left: 120px solid transparent; border-right: 120px solid transparent;
  border-top: 92px solid var(--accent); transform-origin: top; transition: transform 0.5s; border-radius: 14px;
}
.envelope.open { animation: none; }
.envelope.open::before { transform: rotateX(180deg); }
.envelope.open { transition: transform 0.6s 0.35s, opacity 0.6s 0.35s; transform: scale(1.6) translateY(40px); opacity: 0; }
@keyframes bob { 50% { transform: translateY(-8px) rotate(-1.5deg); } }

.bars { position: absolute; top: 16px; left: 12px; right: 12px; display: flex; gap: 4px; z-index: 2; }
.bars i { flex: 1; height: 3px; border-radius: 3px; background: rgba(0, 0, 0, 0.15); overflow: hidden; }
.bars i b { display: block; height: 100%; width: 0; background: var(--ink); }
.bars i.done b { width: 100%; }

.slide { width: 100%; animation: pop 0.45s cubic-bezier(0.2, 1.4, 0.4, 1); }
@keyframes pop { from { transform: scale(0.86) translateY(18px); opacity: 0; } }
.slide .bubble { background: var(--paper); border-radius: 24px; padding: 22px; box-shadow: 0 6px 0 rgba(0, 0, 0, 0.1); text-align: left; }
.slide .bubble img { width: 100%; max-height: 38dvh; object-fit: cover; border-radius: 14px; margin-bottom: 14px; display: block; }
.slide .bubble p { margin: 0; font-size: clamp(18px, 4.6vw, 24px); line-height: 1.3; white-space: pre-wrap; overflow-wrap: anywhere; }
.slide .who { margin-top: 14px; font-weight: 800; font-size: 18px; color: var(--accent); }
.slide h1 { margin: 0; }
.names { font-size: 18px; line-height: 1.5; margin: 14px 0 26px; }
.endbrand { position: absolute; bottom: 22px; left: 0; right: 0; z-index: 3; display: none; font-size: 13px; font-weight: 700; text-align: center; }
/* "Made with CardAround" and its button show on the last frame, and under the page of a card from one person. */
.stage:has(#scene-end:not(.hidden)) .endbrand, .stage:has(#scene-letter:not(.hidden)) .endbrand { display: block; }
.endbrand .brand { font-size: inherit; }
/* The name at the foot of the sample opening's screen. The last frame has its own, so it steps aside there. */
.stage-brand { position: absolute; bottom: 20px; left: 0; right: 0; z-index: 2; text-align: center; pointer-events: none; }
.stage-brand .brand { font-size: 17px; }
/* It also steps aside while messages play, where a tall message with a photo would run into it. The icon at the top stays. */
.stage:has(#scene-end:not(.hidden)) .stage-brand, .stage:has(#scene-play:not(.hidden)) .stage-brand, .stage:has(#scene-letter:not(.hidden)) .stage-brand { display: none; }
/* The icon on the sample's envelope, like a seal where the flap closes. */
.seal { position: absolute; left: 50%; top: 66px; width: 50px; height: 50px; margin-left: -25px; border-radius: 24%; box-shadow: 0 3px 0 rgba(0, 0, 0, 0.15); transition: opacity 0.2s; }
.envelope.open .seal { opacity: 0; }

/* The last frame of a group card: the title, then the inside of the card to scroll through. */
#scene-end { justify-content: flex-start; padding: 60px 20px 108px; }
#scene-end h1 { font-size: clamp(26px, 4.4dvh, 36px); line-height: 1.05; margin: 0 0 14px; }
.inside { flex: 1; min-height: 0; width: 100%; overflow-y: auto; text-align: left; background: var(--paper); border-radius: 18px; padding: 20px 20px 4px; box-shadow: 0 6px 0 rgba(0, 0, 0, 0.1); font-family: 'Caveat', cursive; font-weight: 700; color: var(--ink); -webkit-mask-image: linear-gradient(#000 calc(100% - 28px), transparent); mask-image: linear-gradient(#000 calc(100% - 28px), transparent); }
.sig { margin: 0 0 22px; transform: rotate(var(--tilt, 0deg)); }
.sig img { display: block; width: 100%; max-height: 16dvh; object-fit: cover; border-radius: 10px; margin-bottom: 8px; }
.sig p { margin: 0; font-size: clamp(19px, 3.3dvh, 23px); line-height: 1.2; white-space: pre-wrap; overflow-wrap: anywhere; }
.sig b { display: block; margin-top: 4px; text-align: right; font-size: clamp(22px, 3.8dvh, 27px); color: var(--accent); }
.sig:last-child { margin-bottom: 0; padding-bottom: 36px; }

/* A card from one person, opened: one page of cream card, written by hand. */
#scene-letter { padding-bottom: 104px; }
.letter { width: 100%; min-height: 0; overflow-y: auto; text-align: left; background: var(--paper); border-radius: 18px; padding: 22px 22px 18px; box-shadow: 0 6px 0 rgba(0, 0, 0, 0.1); animation: pop 0.5s cubic-bezier(0.2, 1.4, 0.4, 1); font-family: 'Caveat', cursive; font-weight: 700; color: var(--ink); }
.letter p { margin: 0; }
.letter .dear { font-size: clamp(24px, 4.6dvh, 32px); line-height: 1.1; margin-bottom: 12px; }
.letter img { display: block; width: 100%; max-height: 17dvh; object-fit: cover; border-radius: 12px; margin-bottom: 12px; }
.letter .words { font-size: clamp(19px, 3.5dvh, 25px); line-height: 1.22; white-space: pre-wrap; overflow-wrap: anywhere; }
.letter .from { margin-top: 12px; text-align: right; font-size: clamp(17px, 3dvh, 22px); line-height: 1.1; }
.letter .from b { display: block; font-size: clamp(26px, 4.8dvh, 34px); color: var(--accent); }
.endbrand .btn { display: block; width: max-content; margin: 10px auto 0; }
#confetti { position: absolute; inset: 0; pointer-events: none; z-index: 3; }
.mute { position: absolute; top: 28px; right: 12px; z-index: 4; background: rgba(0, 0, 0, 0.12); color: var(--ink); padding: 6px 10px; font-size: 13px; }

#scene-cover .cover { width: 72%; animation: rise 0.8s cubic-bezier(0.2, 1.3, 0.4, 1); transform-origin: left center; transition: transform 0.7s ease-in, opacity 0.5s 0.2s; }
#scene-cover { perspective: 1200px; }
#scene-cover.opening .cover { transform: rotateY(-105deg); opacity: 0; }
@keyframes rise { from { transform: translateY(60%) scale(0.5); opacity: 0; } }
