@font-face{font-family:'Aref Ruqaa';src:url('/lock/fonts/ruqaa-700-arabic.woff2') format('woff2');font-weight:700;font-display:swap;unicode-range:U+0600-06FF,U+0750-077F,U+0870-08FF,U+200C-200E,U+2010-2011,U+FB50-FDFF,U+FE70-FEFC}
@font-face{font-family:'IBM Plex Sans Arabic';src:url('/lock/fonts/ibm-plex-arabic-regular.woff2') format('woff2');font-weight:400;font-display:swap}
@font-face{font-family:'IBM Plex Sans Arabic';src:url('/lock/fonts/ibm-plex-arabic-semibold.woff2') format('woff2');font-weight:600;font-display:swap}
@font-face{font-family:'Manrope';src:url('/lock/fonts/manrope-semibold.woff2') format('woff2');font-weight:600;font-display:swap}

/* The front door: a ruby heart lock alone on the wine-velvet desk, waiting for one date. No names, no initials:
   whoever finds it learns nothing about whose it is. */
:root{
  --desk-1:#2b0d1b;--desk-2:#5a1f36;--lamp:#f2a7bf;
  --metal-1:#fff0dd;--metal-2:#e7b2aa;--metal-3:#ab576b;--metal-4:#f0cbbd;--metal-ink:#4f1429;
  --desk-ink:#f8e9ee;--desk-soft:#e7b2aa;--warn:#ffb8c8;--glow:#fff0dc;
  --lock-w:clamp(190px,min(80vw,calc((100svh - 250px) * .87)),360px);
  --cell-w:calc(var(--lock-w) * .071);
  --cell-h:calc(var(--cell-w) * 1.5);
}
html[data-mood="midnight"]{
  --desk-1:#12060f;--desk-2:#2a1028;--lamp:#a58bd0;
  --metal-1:#f6eaee;--metal-2:#d2b9c3;--metal-3:#7f5d6c;--metal-4:#e2ccd4;
  --desk-ink:#f3e3ea;--desk-soft:#cdb3c0;--glow:#f6e2f2
}
*{box-sizing:border-box}
/* Clipped sideways only, so the turning heart and its lamp light never widen the page. */
html{min-width:320px;background:var(--desk-1);overflow-x:hidden;overflow-x:clip}
body{margin:0;min-height:100vh;min-height:100svh;display:grid;place-items:center;position:relative;isolation:isolate;overflow:clip;
  font:400 16px/1.6 'IBM Plex Sans Arabic',system-ui,sans-serif;color:var(--desk-ink);
  background-color:var(--desk-1);
  background-image:radial-gradient(60% 40% at 50% 34%,color-mix(in srgb,var(--lamp) 17%,transparent),transparent 72%),radial-gradient(120% 80% at 50% 0%,var(--desk-2) 0%,var(--desk-1) 72%)}
/* The velvet pile: neutral grey under soft-light, so the desk keeps its own colour. */
body::before{content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;background:url('/lock/textures/velvet.png') 0 0/256px;opacity:.75;mix-blend-mode:soft-light}
::selection{background:color-mix(in srgb,var(--lamp) 35%,transparent)}
.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

.door{display:grid;justify-items:center;gap:clamp(14px,3.6svh,30px);padding:max(24px,env(safe-area-inset-top)) max(16px,env(safe-area-inset-right)) max(24px,env(safe-area-inset-bottom)) max(16px,env(safe-area-inset-left));text-align:center}
.door-title{margin:0 0 clamp(4px,1.4svh,14px);font:700 clamp(34px,9.6vw,50px)/1.25 'Aref Ruqaa','IBM Plex Sans Arabic',serif;color:var(--desk-ink);text-shadow:0 2px 16px rgba(0,0,0,.45);text-wrap:balance}

/* ——— The lock: slices in real depth, so the heart has a body when it turns ——— */
.lock{position:relative;width:var(--lock-w);aspect-ratio:288/330;perspective:640px;perspective-origin:50% 40%;cursor:text;touch-action:manipulation;-webkit-tap-highlight-color:transparent}
/* Its shadow on the desk, and the lamp light that spills out when it opens. */
.lock::before{content:"";position:absolute;left:14%;right:14%;bottom:-6%;height:11%;z-index:-1;border-radius:50%;background:radial-gradient(closest-side,rgba(10,0,4,.6),transparent);filter:blur(5px)}
.lock::after{content:"";position:absolute;inset:-30% -45%;z-index:-2;pointer-events:none;background:radial-gradient(closest-side,color-mix(in srgb,var(--glow) 42%,transparent),color-mix(in srgb,var(--glow) 12%,transparent) 55%,transparent 76%);opacity:0;transition:opacity 1s ease}
.lock-3d{position:absolute;inset:0;transform-style:preserve-3d;transform:rotateX(var(--rx,3deg)) rotateY(var(--ry,0deg));animation:sway 9s ease-in-out infinite alternate;view-transition-name:heart-lock}
.lock-3d>svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
.lock-shackle{transform:translateZ(-16px)}
.shackle-swing{transform-box:fill-box;transform-origin:91% 100%;transition:transform .65s cubic-bezier(.24,.75,.35,1)}
.lock-depth{transform:translateZ(var(--z))}
.lock-depth path{fill:var(--side)}
.lock-face{transform:translateZ(0)}
@keyframes sway{from{transform:rotateX(4deg) rotateY(-12deg)}to{transform:rotateX(1deg) rotateY(12deg)}}
/* On a computer the heart follows the pointer instead of swaying on its own. */
.is-tilting .lock-3d{animation:none;transition:transform .5s cubic-bezier(.2,.8,.2,1)}

/* ——— The combination: a brushed rose-gold plate with eight drums, day / month / year ——— */
.plate{position:absolute;left:12.5%;width:75%;top:46%;transform:translateZ(10px);display:grid;place-items:center;padding:calc(var(--cell-h) * .2) calc(var(--cell-w) * .3) calc(var(--cell-h) * .12);border-radius:calc(var(--cell-h) * .46);color:var(--metal-ink);
  background:url('/lock/textures/brushed.png') 0 0/96px,linear-gradient(170deg,var(--metal-1) 0%,var(--metal-2) 40%,var(--metal-3) 82%,var(--metal-4) 100%);background-blend-mode:soft-light,normal;
  box-shadow:0 7px 10px rgba(46,4,18,.55),0 1px 2px rgba(46,4,18,.45),inset 0 1px 0 rgba(255,255,255,.7),inset 0 -2px 5px rgba(60,10,25,.3);transition:box-shadow .3s}
/* An engraved line just inside the rim, like the plate on the keepsake box. */
.plate::before{content:"";position:absolute;inset:3px;border-radius:inherit;border:1px solid rgba(79,20,41,.28);box-shadow:0 1px 0 rgba(255,240,226,.45);pointer-events:none}
.dials{direction:ltr;display:flex;align-items:flex-start;gap:calc(var(--cell-w) * .14)}
.group{display:grid;justify-items:center;gap:calc(var(--cell-h) * .1)}
.drums{display:flex;gap:calc(var(--cell-w) * .1)}
.group-name{font:600 max(10px,calc(var(--cell-h) * .33))/1.25 'IBM Plex Sans Arabic',sans-serif;color:rgba(79,20,41,.82);text-shadow:0 1px 0 rgba(255,240,226,.5)}
.sep{height:var(--cell-h);display:grid;place-items:center;font:600 calc(var(--cell-h) * .5)/1 'Manrope',sans-serif;color:rgba(79,20,41,.62)}
.dial{position:relative;display:block;width:var(--cell-w);height:var(--cell-h);overflow:hidden;border-radius:calc(var(--cell-w) * .22);
  background:linear-gradient(180deg,#4a1027 0%,#ecccc1 24%,#fff8f1 50%,#ecccc1 76%,#4a1027 100%);
  box-shadow:inset 0 2px 3px rgba(40,6,18,.6),inset 0 -2px 3px rgba(40,6,18,.55),0 1px 0 rgba(255,240,226,.55)}
/* The drum's curve: what rolls away from the middle falls into shadow. */
.dial::after{content:"";position:absolute;inset:0;pointer-events:none;background:linear-gradient(180deg,rgba(40,6,18,.5),transparent 32%,transparent 68%,rgba(40,6,18,.5))}
/* The next drum to turn, while the lock is listening. */
.dial::before{content:"";position:absolute;inset:0;z-index:2;border-radius:inherit;pointer-events:none;box-shadow:inset 0 0 0 2px var(--glow),inset 0 0 8px color-mix(in srgb,var(--glow) 70%,transparent);opacity:0;transition:opacity .2s}
.lock:focus-within .dial.is-next::before{opacity:1;animation:beckon 1.3s ease-in-out infinite}
@keyframes beckon{50%{opacity:.35}}
.reel{display:grid;transform:translateY(calc((var(--d,-1) + 1) * var(--cell-h) * -1));transition:transform .45s cubic-bezier(.2,1.3,.4,1)}
.reel i{display:grid;place-items:center;height:var(--cell-h);font:600 calc(var(--cell-h) * .6)/1 'Manrope','IBM Plex Sans Arabic',sans-serif;font-style:normal;font-variant-numeric:tabular-nums lining-nums;color:var(--metal-ink)}
.reel i:first-child::before{content:"";width:calc(var(--cell-w) * .2);height:calc(var(--cell-w) * .2);border-radius:50%;background:rgba(79,20,41,.42)}

/* The field that listens: it covers the whole lock, so a tap anywhere on the heart opens the number pad. */
.date-input{position:absolute;inset:0;z-index:3;width:100%;height:100%;margin:0;padding:0;border:0;border-radius:0;opacity:0;font-size:16px;color:transparent;caret-color:transparent;background:transparent;cursor:text;-webkit-appearance:none;appearance:none}
.lock:has(.date-input:focus-visible) .plate{outline:2px solid var(--glow);outline-offset:4px}

.door-note{margin:0;min-height:1.7em;max-width:32ch;font-size:15px;line-height:1.7;color:var(--desk-soft);text-wrap:balance}
.door-note.is-warn{color:var(--warn)}

/* ——— Moments ——— */
.is-checking .shackle-swing{animation:jiggle .34s ease-in-out infinite}
@keyframes jiggle{50%{transform:translateY(-7px)}}
.is-wrong .lock{animation:refuse .52s cubic-bezier(.36,.07,.19,.97)}
@keyframes refuse{10%,90%{transform:translateX(-2px)}20%,80%{transform:translateX(4px)}30%,50%,70%{transform:translateX(-9px)}40%,60%{transform:translateX(9px)}}
.is-open .lock-3d{animation:none;transform:rotateX(0) rotateY(0);transition:transform .6s cubic-bezier(.2,.8,.2,1)}
.is-open .shackle-swing{transform:translateY(-46px) rotate(-17deg)}
.is-open .lock::after{opacity:1}
.is-open .dial{box-shadow:inset 0 2px 3px rgba(40,6,18,.6),inset 0 -2px 3px rgba(40,6,18,.55),0 0 0 1px color-mix(in srgb,var(--glow) 80%,transparent),0 0 10px color-mix(in srgb,var(--glow) 55%,transparent)}

/* Walking through: the heart carries over into the keepsake box behind the door. */
@view-transition{navigation:auto}

@media (prefers-reduced-motion:reduce){
  @view-transition{navigation:none}
  .lock-3d{animation:none}
  .lock-3d,.reel,.shackle-swing,.lock::after{transition:none}
  .is-checking .shackle-swing,.lock:focus-within .dial.is-next::before,.is-wrong .lock{animation:none}
  .is-wrong .plate{box-shadow:0 7px 10px rgba(46,4,18,.55),inset 0 1px 0 rgba(255,255,255,.7),0 0 0 2px var(--warn)}
}
