/* Motion: one rhythm for the whole studio.
   One curve, three durations. Things arrive from where they belong and
   leave the same way. Everything here switches off under reduced motion. */
:root {
  --ease: cubic-bezier(.2, .7, .2, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --t-fast: 140ms;
  --t-base: 260ms;
  --t-slow: 420ms;
}

/* Pressing anything gives back a little. */
.quiet, .primary, .secondary, .icon-button, .size-card, .choice-card, .wish-chip, .tile-mark, .add-tile, .feedback-fab, .feedback-faces button, .shape-tabs button {
  transition: transform var(--t-fast) var(--ease), background-color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease), opacity var(--t-fast) var(--ease);
}
.quiet:active, .primary:active, .secondary:active, .icon-button:active, .size-card:active, .choice-card:active, .wish-chip:active, .add-tile:active, .feedback-fab:active, .shape-tabs button:active { transform: scale(.97); }
.primary:active { transform: scale(.98); }
.feedback-faces button:active { transform: scale(.92); }
.quiet:disabled, .primary:disabled, .secondary:disabled { transition: opacity var(--t-base) var(--ease), background-color var(--t-base) var(--ease); }

/* First arrival: the book rises into the light, the sheet settles beneath it,
   the words follow one line at a time. */
body.arriving .studio-visual .studio-book { animation: book-rise var(--t-slow) var(--ease-out) both; }
body.arriving .studio-visual .intake-prints img { animation: fade-in var(--t-slow) var(--ease) both; animation-delay: 240ms; }
body.arriving .studio-sheet { animation: sheet-settle var(--t-slow) var(--ease-out) both; animation-delay: 80ms; }
body.arriving .book-summary { animation: rise-in var(--t-base) var(--ease-out) both; animation-delay: 220ms; }
body.arriving .intake-heading > * { animation: rise-in var(--t-base) var(--ease-out) both; }
body.arriving .intake-heading > :nth-child(1) { animation-delay: 260ms; }
body.arriving .intake-heading > :nth-child(2) { animation-delay: 320ms; }
body.arriving .intake-heading > :nth-child(3) { animation-delay: 380ms; }
body.arriving .request-photos { animation: rise-in var(--t-base) var(--ease-out) both; animation-delay: 440ms; }
body.arriving .intake-wishes, body.arriving .intake-promise, body.arriving .intake-links { animation: rise-in var(--t-base) var(--ease-out) both; animation-delay: 520ms; }
body.arriving .sheet-footer { animation: fade-in var(--t-base) var(--ease) both; animation-delay: 560ms; }
@keyframes book-rise { from { opacity: 0; transform: translateY(18px) scale(.97); } to { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes sheet-settle { from { opacity: 0; transform: translateY(28px); } to { opacity: 1; transform: translateY(0); } }
@keyframes rise-in { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

/* Changing between designing it ourselves and letting the studio design. */
.view-enter { animation: view-in var(--t-base) var(--ease-out) both; }
@keyframes view-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }

/* Photographs land one after another, like prints laid on a table. */
.intake-tile { animation: tile-land var(--t-base) var(--ease-out) both; animation-delay: calc(min(var(--i, 0), 14) * 24ms); }
.intake-tile.reading { animation-delay: 0ms; }
@keyframes tile-land { from { opacity: 0; transform: translateY(14px) scale(.96); } to { opacity: 1; transform: translateY(0) scale(1); } }
.add-tile { transition: transform var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease), background-color var(--t-fast) var(--ease); }

/* The book on the stage follows the chosen size as one continuous shape. */
.studio-visual .studio-book { transition: width var(--t-slow) var(--ease), height var(--t-slow) var(--ease), box-shadow var(--t-base) var(--ease); will-change: width, height; }
.studio-visual .studio-book img { transition: transform var(--t-slow) var(--ease); }
.size-card[aria-pressed=true] { animation: card-pick var(--t-base) var(--ease-out); }
.choice-card[aria-pressed=true] { animation: card-pick var(--t-base) var(--ease-out); }
@keyframes card-pick { from { box-shadow: inset 0 0 0 0 var(--ink); } to { box-shadow: inset 0 0 0 1px var(--ink); } }
.size-shape i { transition: width var(--t-base) var(--ease), height var(--t-base) var(--ease), background-color var(--t-fast) var(--ease); }

/* Sheets slide up over a page that steps back a little. */
dialog#review-dialog, dialog#upload-dialog { transition: opacity var(--t-base) var(--ease), transform var(--t-base) var(--ease); }
dialog#review-dialog[open]::backdrop, dialog#upload-dialog[open]::backdrop { animation: dim-in var(--t-base) var(--ease) both; }
dialog#review-dialog.closing { animation: sheet-away 200ms var(--ease) both; }
dialog#review-dialog.closing::backdrop { animation: dim-out 200ms var(--ease) both; }
@keyframes dim-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes dim-out { from { opacity: 1; } to { opacity: 0; } }
@keyframes sheet-away { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(18px); } }
body:has(dialog#review-dialog[open]:not(.closing)) #app, body:has(dialog#upload-dialog[open]) #app { transform: scale(.985); transform-origin: 50% 40%; filter: saturate(.92); }
#app { transition: transform var(--t-base) var(--ease), filter var(--t-base) var(--ease); }
dialog#review-dialog[open]:not(.photo-sheet):not(.design-request):not(.book-sheet):not(.feedback-sheet):not(.material-preview) { animation: dialog-in var(--t-base) var(--ease-out) both; }
@keyframes dialog-in { from { opacity: 0; transform: translateY(12px) scale(.98); } to { opacity: 1; transform: translateY(0) scale(1); } }

/* A notice drops in from above and lifts away. */
#notice { animation: notice-drop var(--t-base) var(--ease-out) both; }
#notice.leaving { animation: notice-lift 200ms var(--ease) both; }
@keyframes notice-drop { from { opacity: 0; transform: translate(-50%, 8px); } to { opacity: 1; transform: translate(-50%, 0); } }
@keyframes notice-lift { from { opacity: 1; transform: translate(-50%, 0); } to { opacity: 0; transform: translate(-50%, 6px); } }

/* Upload progress breathes instead of ticking. */
.send-bar span { transition: width var(--t-slow) var(--ease); background: linear-gradient(90deg, var(--ink) 0%, #4a4c50 50%, var(--ink) 100%); background-size: 200% 100%; animation: shimmer 1.6s linear infinite; }
@keyframes shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
.send-progress { animation: rise-in var(--t-base) var(--ease-out) both; }
.send-error { animation: rise-in var(--t-base) var(--ease-out) both; }

/* The ceremony: the photographs become the book, and the book is handed over. */
.ceremony { position: fixed; inset: 0; z-index: 60; display: grid; place-items: center; background: var(--paper, #f1efea); color: var(--ink, #1c1c1b); overflow: hidden; animation: fade-in var(--t-slow) var(--ease) both; }
.ceremony-stage { position: relative; width: min(100vw, 560px); height: min(60svh, 420px); }
.ceremony-print { position: absolute; left: 50%; top: 50%; width: 92px; height: 115px; margin: -57px 0 0 -46px; object-fit: cover; border: 4px solid #fff; border-radius: 1px; box-shadow: 0 10px 24px -8px #0006; background: #e8e5de; opacity: 0; }
.ceremony-book { position: absolute; left: 50%; top: 50%; width: 200px; height: 200px; margin: -100px 0 0 -100px; border-radius: 1px 3px 3px 1px; background: #e9e6df; box-shadow: inset 8px 0 0 #2a2927, inset 9px 0 0 #4e4b46, 2px 2px 0 #f7f5f0, 4px 4px 0 #dad6cd, 6px 6px 0 #f7f5f0, 8px 8px 0 #cfcac0, 0 30px 50px -22px #00000055; overflow: hidden; opacity: 0; transform: scale(.92); }
.ceremony-book img { position: absolute; inset: 0 0 0 9px; width: calc(100% - 9px); height: 100%; object-fit: cover; display: block; }
.ceremony-book span { position: absolute; left: 22px; bottom: 12px; font: italic 400 14px/1.3 var(--serif); color: #fff; text-shadow: 0 1px 6px #0009; }
.ceremony-book .cover-placeholder { position: absolute; inset: 0 0 0 9px; display: grid; place-items: center; border: 0; color: #8c8980; font: 400 13px/1.4 var(--sans); }
.ceremony-words { position: absolute; left: 0; right: 0; top: calc(50% + 130px); text-align: center; padding: 0 24px; }
.ceremony-words h2 { margin: 0; font: 400 clamp(24px, 4.6vw, 34px)/1.15 var(--serif); letter-spacing: -.01em; color: var(--ink, #1c1c1b); opacity: 0; }
.ceremony-words p { margin: 12px auto 0; max-width: 420px; font: 400 15px/1.55 var(--sans); color: var(--ink-2, #4b4a47); opacity: 0; }
.ceremony-words .ceremony-ref { margin-top: 18px; font-size: 13px; color: var(--muted, #76746e); letter-spacing: .02em; }
.ceremony-words .ceremony-ref strong { color: var(--ink, #1c1c1b); font-weight: 500; letter-spacing: .06em; margin-left: 6px; }
.ceremony-actions { display: flex; justify-content: center; gap: 10px; margin-top: 26px; opacity: 0; }
.ceremony-actions a, .ceremony-actions button { border-radius: 2px; padding: 11px 18px; font-size: 14px; text-decoration: none; }
.ceremony-actions .secondary { background: transparent; color: var(--ink, #1c1c1b); border-color: #cfccc4; }
.ceremony.settled .ceremony-words h2, .ceremony.settled .ceremony-words p, .ceremony.settled .ceremony-actions { opacity: 1; }
.ceremony.settled .ceremony-book { opacity: 1; transform: scale(1); }
@media (max-width: 760px) {
  .ceremony-stage { height: 46svh; }
  .ceremony-book { width: 160px; height: 160px; margin: -80px 0 0 -80px; }
  .ceremony-print { width: 72px; height: 90px; margin: -45px 0 0 -36px; }
  .ceremony-words { top: calc(50% + 104px); }
  .ceremony-actions { flex-direction: column; align-items: stretch; padding: 0 8px; }
}

@media (prefers-reduced-motion: reduce) {
  body.arriving *, .view-enter, .intake-tile, .size-card, .choice-card, dialog, dialog::backdrop, #notice, .send-bar span, .send-progress, .send-error, .feedback-fab, .ceremony, .ceremony::before { animation: none !important; }
  .studio-visual .studio-book, .studio-visual .studio-book img, .size-shape i, #app, .send-bar span { transition: none !important; }
  body:has(dialog[open]) #app { transform: none; filter: none; }
  .ceremony-print { display: none; }
  .ceremony-book, .ceremony-words h2, .ceremony-words p, .ceremony-actions { opacity: 1; transform: none; }
}

/* Ceremony headings follow the display cut (see studio.css). */
.ceremony-words h2 { font-weight: 500; letter-spacing: -.025em; }
.ceremony-book span { font-style: normal; font-weight: 500; }
