:root{color-scheme:dark;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;background:#291b36;color:#fff5f0}*{box-sizing:border-box}body{margin:0;min-height:100svh;background:radial-gradient(ellipse at 18% 18%,#76547535,transparent 55%),radial-gradient(ellipse at 95% 75%,#99707724,transparent 45%);display:grid;place-items:center;padding:max(28px,env(safe-area-inset-top)) max(24px,env(safe-area-inset-right)) max(28px,env(safe-area-inset-bottom)) max(24px,env(safe-area-inset-left))}main{max-width:440px;width:100%;text-align:center;padding:30px 0}.orbit{margin:0 auto 42px;width:118px;height:118px;border:1px solid #e7c98b66;border-radius:50%;outline:1px solid #e7c98b19;outline-offset:12px;display:grid;place-items:center;color:#e7c98b;background:radial-gradient(circle,#e7c98b0d,transparent);font:52px Georgia,serif}.eyebrow{font-size:.8rem;text-transform:uppercase;letter-spacing:.17em;color:#e7c98b}h1{font:400 clamp(2.4rem,7vw,3.3rem)/1.13 Georgia,serif;letter-spacing:-.025em;margin:20px 0}h1 em{color:#f5d0de;font-weight:400}.intro{color:#dbc9df;line-height:1.7;font-size:1.125rem}.schedule{font-size:.9rem;color:#e7c98b;line-height:1.6;min-height:24px}form{margin-top:32px;text-align:left}label{display:block;font-size:1rem;margin-bottom:10px}.password-row{display:flex;border:1px solid #d9c8f075;border-radius:14px;background:#ffffff06}.password-row:focus-within{outline:2px solid #e7c98b;outline-offset:3px}input{font:inherit;color:inherit;background:none;border:0;width:100%;min-width:0;padding:15px;outline:none;font-size:1rem}button{font:inherit;cursor:pointer;min-height:48px;border:0;color:inherit}.password-row button{border-radius:12px;background:transparent;padding:10px 15px;font-size:.9rem}.primary{display:flex;align-items:center;justify-content:space-between;width:100%;padding:17px 20px;margin-top:18px;background:#f5d0de;color:#38283f;border-radius:14px;font-weight:600}.primary:active{transform:scale(.985)}button:disabled{opacity:.6;cursor:wait}button:focus-visible{outline:3px solid #e7c98b;outline-offset:4px}#status{font-size:1rem;line-height:1.6;color:#f5d0de;min-height:25px;margin:18px 0 0}.quiet{background:none;text-decoration:underline;text-underline-offset:5px;font-size:.9rem;padding:12px}.footer{font:italic 1rem/1.6 Georgia,serif;color:#bda7c6;margin-top:36px}[hidden]{display:none!important}@media(prefers-reduced-motion:reduce){*,*:before,*:after{transition:none!important;transform:none!important;animation:none!important}}

/* The entrance used to be a still form on a flat panel, which promised nothing
   about the sky behind it. It now carries the same drifting aurora and
   stardust as the gift, in pure CSS and with no gift content of any kind:
   whoever lands here without the password still learns nothing. Both layers
   are fixed and out of flow, so the grid that centres `main` is unaffected,
   and neither uses transform for layout, because the reduced-motion rule above
   strips transforms outright. */
body:before,body:after{content:"";position:fixed;inset:0;pointer-events:none}
body:before{z-index:0;
  background:radial-gradient(ellipse 70% 55% at 78% 18%,#cc86b53d,transparent 70%),
             radial-gradient(ellipse 66% 50% at 12% 86%,#7a5bb04d,transparent 70%),
             radial-gradient(ellipse 90% 40% at 50% 108%,#dac29c26,transparent 68%);
  filter:blur(26px);animation:gate-drift 26s ease-in-out infinite alternate}
body:after{z-index:0;opacity:.55;
  background-image:radial-gradient(circle at 12% 23%,#e8d0b8 0 .8px,transparent 1.7px),
    radial-gradient(circle at 81% 14%,#e8d0b8 0 .8px,transparent 1.7px),
    radial-gradient(circle at 42% 75%,#e8d0b8 0 .7px,transparent 1.5px),
    radial-gradient(circle at 86% 84%,#d4b2d2 0 .9px,transparent 1.8px),
    radial-gradient(circle at 29% 63%,#e8d0b8 0 .75px,transparent 1.6px),
    radial-gradient(circle at 53% 35%,#e8d0b8 0 .8px,transparent 1.7px),
    radial-gradient(circle at 67% 52%,#f0d9c4 0 .7px,transparent 1.5px),
    radial-gradient(circle at 22% 41%,#d4b2d2 0 .75px,transparent 1.6px);
  animation:gate-twinkle 9s ease-in-out infinite alternate}
main{position:relative;z-index:1}
@keyframes gate-drift{0%{opacity:.72;background-position:0 0,0 0,0 0}100%{opacity:1;background-position:3% -2%,-3% 2%,0 1%}}
@keyframes gate-twinkle{0%{opacity:.4}100%{opacity:.72}}
/* The mark at the door: the ring breathes and its star turns, slowly enough to
   read as patient rather than busy. */
.orbit{animation:gate-halo 6.5s ease-in-out infinite alternate}
.orbit span{display:block;animation:gate-spin 34s linear infinite}
@keyframes gate-halo{0%{box-shadow:0 0 0 0 #e7c98b00,0 0 22px -6px #e7c98b1f}100%{box-shadow:0 0 0 9px #e7c98b09,0 0 34px -4px #e7c98b3d}}
@keyframes gate-spin{to{transform:rotate(360deg)}}
/* The content settles in rather than snapping into place. */
main>*{animation:gate-rise .8s cubic-bezier(.2,.7,.2,1) both}
main>.eyebrow{animation-delay:.06s}main>h1{animation-delay:.12s}main>.intro{animation-delay:.18s}
main>.schedule{animation-delay:.22s}main>form{animation-delay:.26s}main>.footer{animation-delay:.34s}
@keyframes gate-rise{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}

/* Item 8: the wait, and the refusal. The schedule line used to be one static
   timestamp; it now carries a live countdown, the exact moment underneath, and
   one aside. */
.schedule b{display:block;font:400 1.2rem/1.4 Georgia,serif;color:#f5d0de;letter-spacing:-.01em}
.schedule .schedule-when{display:block;font-size:.82rem;color:#c8b2cf;margin-top:4px}
.schedule .schedule-tease{display:block;font:italic 1rem/1.6 Georgia,serif;color:#e7c98b;margin-top:12px}
/* A wrong password moves the field it was typed into. It says nothing about
   the guess -- only that the door is still shut. */
.password-row.is-wrong{animation:gateShake .42s cubic-bezier(.36,.07,.19,.97) both;border-color:#f0a9b8a0}
@keyframes gateShake{
  10%,90%{transform:translateX(-2px)}
  20%,80%{transform:translateX(4px)}
  30%,50%,70%{transform:translateX(-7px)}
  40%,60%{transform:translateX(7px)}
}

/* The home page before the day. For the fortnight between the link being sent
   and the window opening, `scheduled` was one gold line of text under a form
   that was not there. It is now the page itself: a date plate naming the day,
   with the live countdown directly under it. The plate is hidden the moment the
   gift is open or closed, so the door is never dressed as a save-the-date. */
.dayplate{margin:20px auto 0;max-width:330px;padding:22px 24px 20px;border:1px solid #e7c98b3d;border-radius:20px;
  background:linear-gradient(#ffffff0c,#ffffff03);box-shadow:0 18px 40px -28px #0d0616}
.dayplate-eyebrow{margin:0;font-size:.66rem;text-transform:uppercase;letter-spacing:.2em;color:#e7c98bb3;padding-left:.2em}
.dayplate-date{margin:10px 0 0;display:flex;flex-direction:column;align-items:center;gap:3px;line-height:1}
.dayplate-day{font:400 4.1rem/1 Georgia,serif;color:#f5d0de;letter-spacing:-.045em;text-shadow:0 0 26px #f5d0de2e}
.dayplate-month{font-size:.76rem;text-transform:uppercase;letter-spacing:.32em;color:#dbc9df;padding-left:.32em}
.dayplate-name{margin:13px 0 0;padding-top:12px;border-top:1px solid #e7c98b29;font:italic 1.14rem/1.5 Georgia,serif;color:#e7c98b}
/* Under the plate the countdown is the only thing still moving, so it is given
   the room to be read as the live half of the page. */
.dayplate:not([hidden])+.schedule{margin-top:14px}
.dayplate:not([hidden])+.schedule b{font-size:1.32rem}
main>.dayplate{animation-delay:.2s}
/* Measured at 375x667: with the plate at full height the countdown began 25px
   above the fold and its aside fell 112px below it, which is the one line on
   this page that has to be seen without scrolling. The ring and the heading
   give way instead -- the plate itself is not reduced. */
main:has(.dayplate:not([hidden])){padding-top:18px}
main:has(.dayplate:not([hidden])) .orbit{width:86px;height:86px;font-size:40px;margin-bottom:24px}
main:has(.dayplate:not([hidden])) h1{margin:14px 0}
