/* ══════════════════════════════════════════════════════════════
   MOTUS.LOVE — THE LOVE OF THE MOVE
   The symbol is not decoration. One world wakes many worlds,
   and nothing wakes at all until the visitor actually MOVES.
   ══════════════════════════════════════════════════════════ */
:root{
  --void:#06030e; --void-2:#0d0618;
  --ink:#ffffff;
  --ink-2:rgba(255,255,255,.88);
  --rose:#ff4d8d; --rose-hot:#ffdcea; --magenta:#ff2d78;
  --violet:#a78bfa; --gold:#ffc46b;
  --cyan:#5cf3ff; --cyan-glow:rgba(92,243,255,.72);
  --edge:rgba(255,140,190,.18); --edge-hi:rgba(255,150,195,.46);
  --glass:rgba(255,255,255,.045); --glass-2:rgba(255,255,255,.085);
  --blur:blur(22px) saturate(180%);
  --love-glow:0 0 22px rgba(255,77,141,.55), 0 0 64px rgba(167,139,250,.26);
  --text-glow:0 0 18px rgba(255,77,141,.5), 0 0 44px rgba(167,139,250,.22);
  --pane-shadow:inset 0 1px 0 rgba(255,190,215,.13), 0 26px 68px rgba(0,0,0,.6);
  --f-display:'Sora',system-ui,sans-serif;
  --f-body:'Inter',system-ui,sans-serif;
  --f-mono:'JetBrains Mono',ui-monospace,monospace;
  /* THE RADIUS SCALE — every rounded thing takes its value from here */
  --r-sm:14px; --r-ctl:20px; --r-pane:24px; --r-hero:30px; --r-pill:999px;
  --ease:cubic-bezier(.16,1,.3,1);        /* decisive, then dead still */
  --ease-io:cubic-bezier(.65,0,.35,1);
  /* THE MOVEMENT ENGINE writes here. 0 = still. 1 = fully moved. */
  --energy:0;
  --wake:0;
}
*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{
  font-family:var(--f-body);background:var(--void);color:var(--ink);
  min-height:100svh;overflow-x:hidden;-webkit-font-smoothing:antialiased;
  line-height:1.6;
}
img,canvas{display:block;max-width:100%}
::selection{background:rgba(255,77,141,.4);color:#fff}
:focus-visible{outline:2px solid var(--rose);outline-offset:4px;border-radius:var(--r-sm)}

/* ── THE FIELD — the void the worlds burn through ── */
.field{position:fixed;inset:0;z-index:-3;pointer-events:none;
  background:
    radial-gradient(62vw 56vw at 14% -12%,rgba(255,45,120,.16),transparent 64%),
    radial-gradient(52vw 48vw at 90% 22%,rgba(167,139,250,.14),transparent 68%),
    radial-gradient(70vw 52vw at 50% 116%,rgba(255,140,190,.12),transparent 70%),
    var(--void);}
#worlds{position:fixed;inset:0;z-index:-2;pointer-events:none;opacity:.9}
.grain{position:fixed;inset:0;z-index:-1;pointer-events:none;opacity:.05;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E")}

/* ── LAYOUT ── */
.wrap{width:100%;max-width:1080px;margin:0 auto;padding:0 22px}
/* THE BREATH — he asked for several lines of air between every statement.
   Space is the loudest thing on the page when every line is shouting. */
section{position:relative;padding:180px 0}
@media(min-width:768px){section{padding:250px 0}}

/* ── TYPE ──
   The floor moved. Body copy no longer sits below its own headings:
   every line on this page is set at title weight, by his instruction. */
.eyebrow{font-family:var(--f-mono);font-size:clamp(.86rem,3.4vw,1.12rem);font-weight:700;
  letter-spacing:.3em;text-transform:uppercase;color:var(--rose);text-shadow:var(--text-glow)}
h1,h2,h3,.display{font-family:var(--f-display);font-weight:800;line-height:1.03;letter-spacing:-.025em}
h1{font-size:clamp(2.9rem,12vw,6.6rem)}
h2{font-size:clamp(2.4rem,8.6vw,4.4rem);line-height:1.05}
h3{font-size:clamp(1.9rem,7vw,3rem);font-weight:800;line-height:1.12}
p{font-size:clamp(1.5rem,5.8vw,2.1rem);color:var(--ink);line-height:1.42;
  font-family:var(--f-display);font-weight:600;letter-spacing:-.018em}
.lead{font-size:clamp(1.66rem,6.4vw,2.5rem);line-height:1.36;color:var(--ink);
  font-family:var(--f-display);font-weight:700;letter-spacing:-.022em}
.hot{color:var(--rose-hot);text-shadow:var(--text-glow)}
.rose{color:var(--rose);text-shadow:var(--text-glow)}
.gold{color:var(--gold);text-shadow:0 0 18px rgba(255,196,107,.45)}
.violet{color:var(--violet);text-shadow:0 0 18px rgba(167,139,250,.5)}
.mono{font-family:var(--f-mono);font-variant-numeric:tabular-nums}

/* ── REVEAL ── */
[data-reveal]{opacity:0;transform:translateY(24px);
  transition:opacity .85s var(--ease) var(--rd,0ms),transform .85s var(--ease) var(--rd,0ms)}
[data-reveal].seen{opacity:1;transform:none}

/* ══════════ HERO ══════════ */
.hero{min-height:100svh;display:flex;flex-direction:column;align-items:center;
  justify-content:center;text-align:center;padding:130px 0 110px}
.hero .wrap{display:flex;flex-direction:column;align-items:center;gap:52px}

/* THE WORLD — one world, brightened by your own movement */
.world{position:relative;width:min(60vw,238px);aspect-ratio:1;flex:0 0 auto;
  border-radius:50%;
  transform:scale(calc(1 + var(--energy) * .085));
  transition:transform .5s var(--ease)}
.world__core{position:absolute;inset:0;border-radius:50%;
  background:
    radial-gradient(circle at 40% 34%,var(--rose-hot) 0 6%,var(--rose) 26%,var(--magenta) 52%,#5b1240 76%,#180520 100%);
  box-shadow:
    inset -14px -18px 44px rgba(0,0,0,.62),
    inset 10px 12px 34px rgba(255,220,234,.16),
    0 0 calc(28px + var(--energy) * 80px) rgba(255,77,141,calc(.34 + var(--energy) * .5)),
    0 0 calc(70px + var(--energy) * 170px) rgba(167,139,250,calc(.16 + var(--energy) * .34));
  transition:box-shadow .55s var(--ease)}
/* -26%, not -32%: the gradient is already transparent past 74%, so the outer
   band was invisible glow that still widened the box past a 390px phone. */
.world__aura{position:absolute;inset:-26%;border-radius:50%;pointer-events:none;
  background:radial-gradient(closest-side,rgba(255,77,141,.4),rgba(167,139,250,.12) 58%,transparent 74%);
  filter:blur(10px);opacity:calc(.32 + var(--energy) * .68);
  animation:breathe 5.6s ease-in-out infinite;transition:opacity .55s var(--ease)}
.world__ring{position:absolute;inset:-9%;border-radius:50%;pointer-events:none;
  background:conic-gradient(from 200deg,transparent 0 8%,var(--violet) 26%,var(--rose-hot) 50%,var(--rose) 72%,transparent 92%);
  -webkit-mask:radial-gradient(circle,transparent calc(50% - 3px),#000 calc(50% - 2px));
  mask:radial-gradient(circle,transparent calc(50% - 3px),#000 calc(50% - 2px));
  opacity:calc(.28 + var(--energy) * .72);
  animation:revolve 26s linear infinite}
@keyframes revolve{to{transform:rotate(360deg)}}
@keyframes breathe{0%,100%{opacity:.72}50%{opacity:1}}

/* ── THE ARRIVAL ──
   Two staggered rings, once, at the moment one becomes many. Staggered so
   the moment reads as PROPAGATION and not as a pop. Nothing overshoots:
   the rings leave at speed and stop dead, they never spring back. */
.world__flare{position:absolute;inset:0;border-radius:50%;pointer-events:none;opacity:0;
  border:2px solid var(--rose-hot);
  box-shadow:0 0 30px rgba(255,77,141,.65),inset 0 0 26px rgba(255,77,141,.35)}
/* No fill-mode: the resting state is ALREADY invisible, so letting the ring
   fall back to scale(1) costs nothing visually and is the whole point —
   `forwards` would freeze a 2.2x box on the layout forever and leave the
   phone scrollable sideways by 70px long after the ring is gone. */
html.woke .world__flare{animation:flare 1.5s var(--ease)}
html.woke .world__flare.b{animation-delay:.3s;border-color:var(--violet)}
@keyframes flare{from{opacity:.9;transform:scale(1)}to{opacity:0;transform:scale(2.2)}}

.hero h1{margin-top:4px}
.hero .sub{font-family:var(--f-display);font-weight:700;
  font-size:clamp(1.44rem,5.8vw,2.3rem);letter-spacing:-.022em;color:var(--ink);
  line-height:1.2;text-wrap:balance}

/* The line that CHANGES when you have moved enough.
   Both lines share ONE grid cell, so the box sizes to the taller of the two
   and they never mis-stack. The handoff is sequential, not simultaneous —
   one leaves completely before many arrives, so his two sentences are never
   smeared on top of each other. */
.titleflip{display:grid;justify-items:center}
/* balance, not <br> — the break point is the browser's problem to solve,
   so his sentence is never re-punctuated to make a line fit. */
.titleflip span{grid-area:1/1;text-wrap:balance}
.titleflip .one{opacity:1;transition:opacity .3s var(--ease),transform .3s var(--ease)}
.titleflip .many{opacity:0;transform:translateY(10px);
  transition:opacity .42s var(--ease) .3s,transform .42s var(--ease) .3s}
html.woke .titleflip .one{opacity:0;transform:translateY(-10px)}
html.woke .titleflip .many{opacity:1;transform:none}

.movecue{display:inline-flex;align-items:center;gap:10px;min-height:44px;padding:0 20px;
  border-radius:var(--r-pill);background:var(--glass);border:1px solid var(--edge);
  -webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
  font-family:var(--f-mono);font-size:.7rem;font-weight:700;letter-spacing:.2em;
  text-transform:uppercase;color:var(--rose-hot);
  box-shadow:0 0 calc(var(--energy) * 34px) rgba(255,77,141,.4);
  transition:box-shadow .5s var(--ease),border-color .5s var(--ease)}
.movecue .dot{width:8px;height:8px;border-radius:50%;background:var(--rose);
  box-shadow:0 0 12px var(--rose);animation:pulse 2.2s var(--ease-io) infinite}
@keyframes pulse{0%,100%{transform:scale(1);opacity:.7}50%{transform:scale(1.5);opacity:1}}
/* Twelve of twelve. The cue stops asking — the dot holds, because the
   instruction has been carried out and a page that keeps blinking at you
   after you have done the thing is a page that was not listening. */
html.full .movecue{border-color:var(--edge-hi)}
html.full .movecue .dot{animation:none;transform:none;opacity:1;
  background:var(--rose-hot);box-shadow:0 0 16px var(--rose),0 0 34px rgba(167,139,250,.6)}

/* ══════════ THE METER — the propagation made literal ══════════ */
.meter{border:1px solid var(--edge);border-radius:var(--r-hero);
  background:var(--glass);-webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
  box-shadow:var(--pane-shadow);padding:34px 24px;text-align:center}
@media(min-width:768px){.meter{padding:52px 44px}}
.meter__stat{font-family:var(--f-mono);font-weight:700;font-variant-numeric:tabular-nums;
  font-size:clamp(3.4rem,17vw,7rem);line-height:1;color:var(--rose-hot);
  text-shadow:0 0 26px rgba(255,77,141,.6),0 0 70px rgba(167,139,250,.34);letter-spacing:-.04em}
.meter__label{font-family:var(--f-mono);font-size:.68rem;font-weight:700;letter-spacing:.28em;
  text-transform:uppercase;color:var(--violet);margin-top:12px}
.meter__track{position:relative;height:8px;border-radius:var(--r-pill);margin:26px auto 0;
  max-width:520px;background:rgba(255,255,255,.07);overflow:hidden}
.meter__fill{position:absolute;inset:0 auto 0 0;width:calc(var(--wake) * 100%);
  border-radius:var(--r-pill);
  background:linear-gradient(90deg,var(--violet),var(--rose) 52%,var(--rose-hot));
  box-shadow:0 0 20px rgba(255,77,141,.7);transition:width .35s var(--ease)}
.meter__lines{display:grid;gap:14px;margin-top:34px}
.meter__lines b{font-family:var(--f-display);font-weight:800;
  font-size:clamp(1.16rem,5vw,2rem);line-height:1.14;letter-spacing:-.02em;display:block}
/* BOTH of these lines are his. Neither is ever allowed to become unreadable —
   the state is carried by GLOW, never by hiding the words. */
.line-one{color:var(--ink);opacity:calc(1 - var(--wake) * .42);
  transition:opacity .6s var(--ease)}
.line-many{color:var(--rose-hot);opacity:calc(.62 + var(--wake) * .38);
  text-shadow:
    0 0 calc(6px + var(--wake) * 24px) rgba(255,77,141,calc(.25 + var(--wake) * .55)),
    0 0 calc(18px + var(--wake) * 48px) rgba(167,139,250,calc(.1 + var(--wake) * .3));
  transition:opacity .6s var(--ease),text-shadow .6s var(--ease)}

/* Twelve of twelve — the count lands and his line takes the light.
   No `forwards`: both release back to the wake-driven values, so the page
   settles into its earned state instead of freezing on a peak. */
html.full .meter__stat{animation:land 1.2s var(--ease-io)}
@keyframes land{
  0%{transform:scale(1)}
  32%{transform:scale(1.07);
    text-shadow:0 0 44px rgba(255,220,234,.95),0 0 104px rgba(255,77,141,.72)}
  100%{transform:scale(1)}}
html.full .line-many{animation:ignite 1.5s var(--ease-io) .18s}
@keyframes ignite{
  0%,100%{text-shadow:0 0 30px rgba(255,77,141,.8),0 0 66px rgba(167,139,250,.4)}
  38%{text-shadow:0 0 34px rgba(255,220,234,.95),0 0 88px rgba(255,77,141,.85),
    0 0 150px rgba(167,139,250,.55)}}

/* ══════════ PANES ══════════ */
.pane{border:1px solid var(--edge);border-radius:var(--r-pane);
  background:var(--glass);-webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
  box-shadow:var(--pane-shadow);padding:30px 24px;
  transition:border-color .45s var(--ease),transform .45s var(--ease),box-shadow .45s var(--ease)}
@media(min-width:768px){.pane{padding:46px 44px}}
.pane:hover{border-color:var(--edge-hi);transform:translateY(-3px);
  box-shadow:var(--pane-shadow),0 0 48px rgba(255,77,141,.16)}
.beam{height:1px;border:0;width:min(560px,74%);margin:0 auto;
  background:linear-gradient(90deg,transparent,var(--rose),transparent);
  box-shadow:0 0 16px rgba(255,77,141,.55)}

/* ══════════ THE THREE — one becomes many, in type ══════════ */
.three{display:grid;gap:18px}
.three__row{display:flex;align-items:flex-start;gap:18px;
  padding:24px 22px;border-radius:var(--r-pane);
  border:1px solid var(--edge);background:var(--glass);
  -webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur)}
@media(min-width:768px){.three__row{padding:32px 34px;gap:26px}}
.three__orb{width:16px;height:16px;flex:0 0 auto;margin-top:.45em;border-radius:50%;
  background:radial-gradient(circle at 36% 32%,var(--rose-hot),var(--rose) 46%,var(--magenta));
  box-shadow:0 0 14px rgba(255,77,141,.8),0 0 34px rgba(167,139,250,.4)}
/* one becomes many — the trail must stay inside its own lane.
   At 44px the far satellite landed INSIDE his sentence; it now clears the
   text by 4px, and reads as propagation rather than a stray dot. */
.three__row:nth-child(2) .three__orb{box-shadow:0 0 14px rgba(255,77,141,.8),0 0 34px rgba(167,139,250,.4),
  11px 0 0 -4px var(--rose),20px 0 0 -6px var(--violet)}
.three__row:nth-child(3) .three__orb{background:radial-gradient(circle at 36% 32%,#fff,var(--gold) 46%,#e08a1e);
  box-shadow:0 0 18px rgba(255,196,107,.9),0 0 44px rgba(255,196,107,.42)}
.three__row p{font-family:var(--f-display);font-weight:700;color:var(--ink);
  font-size:clamp(1.1rem,4.4vw,1.62rem);line-height:1.22;letter-spacing:-.02em}

/* ══════════ THE STATEMENT ══════════ */
.statement{border-left:3px solid var(--rose);padding:6px 0 6px 22px;
  box-shadow:-14px 0 34px -18px rgba(255,77,141,.9)}
@media(min-width:768px){.statement{padding-left:34px}}

/* ══════════ THE CLUB ══════════ */
.club{text-align:center}
.badge{display:inline-flex;flex-direction:column;align-items:center;gap:6px;
  padding:26px 34px;border-radius:var(--r-hero);
  border:1px solid var(--edge-hi);background:var(--glass-2);
  -webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
  box-shadow:var(--pane-shadow),0 0 54px rgba(255,77,141,.2)}
.badge__mark{font-family:var(--f-display);font-weight:800;letter-spacing:-.03em;
  font-size:clamp(1.5rem,6vw,2.3rem);color:var(--rose-hot);text-shadow:var(--text-glow)}
.badge__sub{font-family:var(--f-mono);font-size:.66rem;font-weight:700;letter-spacing:.3em;
  text-transform:uppercase;color:var(--violet)}

/* ══════════ CLOSE ══════════ */
.close{text-align:center}
.close .stack{display:grid;gap:10px;margin:8px 0 0}
.close .stack b{font-family:var(--f-display);font-weight:800;letter-spacing:-.03em;
  font-size:clamp(1.9rem,8.4vw,3.6rem);line-height:1.04;display:block}
.sig{font-family:var(--f-mono);font-size:.68rem;letter-spacing:.26em;text-transform:uppercase;
  color:var(--violet)}

/* ══════════ THE DOOR ══════════ */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:12px;
  min-height:56px;padding:0 32px;border-radius:var(--r-ctl);cursor:pointer;
  font-family:var(--f-display);font-size:1.02rem;font-weight:700;letter-spacing:-.01em;
  border:1px solid transparent;text-decoration:none;position:relative;
  color:#2a0413;background:linear-gradient(135deg,var(--rose-hot),var(--rose) 46%,var(--magenta));
  box-shadow:var(--love-glow);
  transition:transform .28s var(--ease),box-shadow .34s var(--ease)}
.btn:hover{transform:translateY(-2px);
  box-shadow:0 0 36px rgba(255,77,141,.75),0 0 96px rgba(167,139,250,.36)}
.btn:active{transform:translateY(1px) scale(.99)}
.tag{font-family:var(--f-mono);font-size:.76rem;font-weight:700;letter-spacing:.24em;
  text-transform:uppercase;color:var(--rose);text-shadow:var(--text-glow);margin-top:20px;display:block}

footer{padding:56px 0 72px;text-align:center}
footer .mark{font-family:var(--f-display);font-weight:800;font-size:1.16rem;letter-spacing:-.02em;
  color:var(--rose-hot);text-shadow:var(--text-glow)}
footer .fine{font-family:var(--f-mono);font-size:.64rem;letter-spacing:.24em;text-transform:uppercase;
  color:var(--violet);margin-top:12px}

/* his casing is voice, not style — last word, so no transform can rewrite it */
.verbatim{text-transform:none;letter-spacing:.16em}

/* ══════════════════════════════════════════════════════════════
   THE GATE — his poster, unmodified, given motion.

   The artwork is never recoloured, overpainted, filtered or
   re-typeset. Every moving thing in here is an ADDITIVE light layer
   sitting ON TOP of it, in screen blend, so the pixels underneath
   are only ever brightened — never replaced.

   Portrait fills edge to edge. Anything squarer than the poster's own
   9:16 switches to contain over an ambient bleed of itself, because
   cropping his title off to force a full bleed would be modifying it.
   ══════════════════════════════════════════════════════════════ */
.gate{position:relative;width:100%;height:100svh;min-height:100svh;
  overflow:hidden;isolation:isolate;background:var(--void);
  display:flex;align-items:flex-end;justify-content:center}

/* THE STAGE — the box the artwork actually occupies. Every light layer
   is bound to it, never to the viewport, so no glow can wander off the
   poster and smear across the bleed on a wide screen. */
.gate__stage{position:absolute;inset:0;z-index:1;overflow:hidden}

/* the poster itself. breathe only — no translate, so the crop can never
   creep far enough to bite into his title. */
.gate__art{position:absolute;inset:0;width:100%;height:100%;
  max-width:none;object-fit:cover;object-position:50% 50%;
  animation:gate-breathe 19s ease-in-out infinite;will-change:transform}
@keyframes gate-breathe{0%,100%{transform:scale(1.004)}50%{transform:scale(1.034)}}

/* only ever visible when the screen is squarer than the poster */
.gate__bleed{position:absolute;inset:0;z-index:0;display:none;
  background:url(gate.jpg) center/cover no-repeat;
  filter:blur(64px) saturate(1.55) brightness(.46);transform:scale(1.18)}
/* Squarer than 9:16? Then a full-bleed cover would crop his title off the
   top. Instead the stage shrinks to the poster's exact ratio — so it is
   whole, uncropped — and an ambient blur of itself fills to the edges.
   Still edge to edge. Just never at the cost of his words. */
@media(min-aspect-ratio:720/1280){
  .gate__bleed{display:block}
  .gate__stage{left:50%;right:auto;width:calc(100svh * 720 / 1280);
    transform:translateX(-50%)}
}

/* parallax carrier — the light inside the window moves, the window doesn't */
.gate__par{position:absolute;inset:0;z-index:2;pointer-events:none;
  transform:translate3d(var(--gx,0px),var(--gy,0px),0);
  transition:transform .5s var(--ease);will-change:transform}

/* THE HEARTBEAT. Centred on the white-hot core of his nested heart
   (50% 38%), at ~58bpm, lub-dub. The single most earned animation on
   this page: the image is a heart, so the heart is what beats. */
.gate__pulse{position:absolute;inset:0;mix-blend-mode:screen;
  background:radial-gradient(34vmax 34vmax at 50% 38%,
    rgba(255,220,234,.30) 0%,rgba(255,77,141,.22) 15%,
    rgba(255,45,120,.12) 33%,rgba(167,139,250,.05) 55%,transparent 71%);
  animation:heartbeat 3.45s var(--ease-io) infinite;will-change:transform,opacity}
@keyframes heartbeat{
  0%  {opacity:.40;transform:scale(.965)}
  7%  {opacity:.95;transform:scale(1.052)}   /* lub */
  15% {opacity:.52;transform:scale(1.000)}
  23% {opacity:.76;transform:scale(1.030)}   /* dub */
  36% {opacity:.42;transform:scale(.978)}
  100%{opacity:.40;transform:scale(.965)}
}

/* the road, lit. a specular travelling along the light-trails that
   already converge at their feet — his composition, extended in time. */
.gate__sweep{position:absolute;left:-45%;right:-45%;bottom:0;height:54%;
  mix-blend-mode:screen;opacity:.85;
  background:linear-gradient(74deg,transparent 36%,rgba(255,190,215,.10) 46%,
    rgba(255,255,255,.20) 50%,rgba(255,120,175,.10) 54%,transparent 64%);
  /* The box's own top edge floats in the middle of his artwork, so a bright
     phase of the travelling gradient would cut a hard horizontal line across
     the heart. Feathering that edge makes the seam structurally impossible at
     every phase — and concentrates the specular on the road, where his
     light-trails already are. */
  -webkit-mask:linear-gradient(to top,#000 0 34%,transparent 96%);
  mask:linear-gradient(to top,#000 0 34%,transparent 96%);
  animation:gate-sweep 8.4s linear infinite;will-change:transform}
@keyframes gate-sweep{from{transform:translateX(-44%)}to{transform:translateX(44%)}}

/* embers + road-flow, additive */
.gate__embers{position:absolute;inset:0;z-index:3;pointer-events:none;
  width:100%;height:100%;mix-blend-mode:screen}

/* legibility scrim for the cue only — bottom quarter, where his art is
   already darkest. not a vignette; his image brought its own. */
.gate__scrim{position:absolute;left:0;right:0;bottom:0;height:26%;z-index:4;
  pointer-events:none;
  background:linear-gradient(to top,rgba(6,3,14,.74),rgba(6,3,14,.26) 48%,transparent)}

.gate__grain{position:absolute;inset:-40px;z-index:5;pointer-events:none;
  opacity:.05;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
  animation:gate-grain 1.05s steps(3) infinite}
@keyframes gate-grain{0%{transform:translate(0,0)}33%{transform:translate(-14px,9px)}
  66%{transform:translate(11px,-12px)}100%{transform:translate(0,0)}}

/* ONE door. the site's own verb, in the site's own glass. */
.gate__cue{position:relative;z-index:6;display:inline-flex;align-items:center;gap:11px;
  min-height:46px;padding:0 22px;margin-bottom:calc(30px + env(safe-area-inset-bottom));
  border-radius:var(--r-pill);background:rgba(255,255,255,.055);
  border:1px solid var(--edge-hi);
  -webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
  font-family:var(--f-mono);font-size:.72rem;font-weight:700;letter-spacing:.26em;
  text-transform:uppercase;color:var(--rose-hot);text-decoration:none;
  box-shadow:0 0 30px rgba(255,77,141,.26),inset 0 1px 0 rgba(255,190,215,.16);
  animation:gate-rise 1.5s var(--ease) .55s both;
  transition:box-shadow .45s var(--ease),border-color .45s var(--ease),transform .45s var(--ease)}
.gate__cue:hover{box-shadow:0 0 46px rgba(255,77,141,.5),inset 0 1px 0 rgba(255,190,215,.24);
  border-color:var(--rose);transform:translateY(-2px)}
.gate__cue .dot{width:8px;height:8px;border-radius:50%;background:var(--rose);
  box-shadow:0 0 12px var(--rose);animation:pulse 2.2s var(--ease-io) infinite}
.gate__cue svg{width:13px;height:13px;animation:gate-nudge 2.4s var(--ease-io) infinite}
@keyframes gate-nudge{0%,100%{transform:translateY(-2px);opacity:.6}50%{transform:translateY(3px);opacity:1}}
@keyframes gate-rise{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:none}}

/* ══════════════════════════════════════════════════════════════
   THE NAME — Motus.Love, at the scale of the thing it names.
   It is the first thing and the largest thing. It grows on arrival
   and never stops breathing, because a name that holds still is
   a name that has stopped meaning anything.
   ══════════════════════════════════════════════════════════ */
/* His name breaks out of the column's padding — nothing else on the page
   does — because it is the one thing meant to reach both edges. */
.lovetitle{font-family:var(--f-display);font-weight:800;
  line-height:.86;letter-spacing:-.05em;text-align:center;
  width:100vw;display:grid;justify-items:center;gap:0;
  margin:0 calc(50% - 50vw) 8px;
  transform-origin:50% 50%;
  animation:name-grow 1.9s var(--ease) both, name-breathe 7.4s ease-in-out 1.9s infinite}
.lovetitle__l{display:block;white-space:nowrap;
  font-size:clamp(3.9rem,26.2vw,13rem);
  color:var(--ink);
  text-shadow:0 0 38px rgba(255,77,141,.44),0 0 110px rgba(167,139,250,.26)}
.lovetitle__l--2{color:var(--rose-hot);
  text-shadow:0 0 34px rgba(255,77,141,.72),0 0 96px rgba(167,139,250,.4),
              0 0 180px rgba(255,45,120,.3)}
/* the period is its own signal — cyan, and the only cyan on the page */
.lovetitle .dot{font-style:normal;color:var(--cyan);
  text-shadow:0 0 22px var(--cyan-glow),0 0 62px var(--cyan-glow),0 0 120px rgba(79,240,255,.34);
  animation:dot-live 3.6s var(--ease-io) infinite}
@keyframes dot-live{
  0%,100%{opacity:.82;text-shadow:0 0 18px var(--cyan-glow),0 0 52px var(--cyan-glow)}
  50%{opacity:1;text-shadow:0 0 30px var(--cyan-glow),0 0 84px var(--cyan-glow),0 0 150px rgba(79,240,255,.4)}}
@keyframes name-grow{
  from{opacity:0;transform:scale(.62);letter-spacing:.06em;filter:blur(14px)}
  60%{opacity:1;filter:blur(0)}
  to{opacity:1;transform:scale(1);letter-spacing:-.045em;filter:blur(0)}}
@keyframes name-breathe{0%,100%{transform:scale(1)}50%{transform:scale(1.042)}}
/* it earns MORE light as the visitor moves */
.lovetitle__l--2{filter:brightness(calc(1 + var(--energy) * .22))}
/* Stacked, his name fills a phone (95% of 390px). On a landscape desktop the
   same stack only reached 38% of 1920px — the 13rem cap, and two short lines
   on a wide screen. Wide and short is the shape of the screen, so the lockup
   becomes the shape of the screen: one line, sized off the width it has to
   fill, held back by 34vh so a short laptop window can't let it overflow. */
@media (min-width:1100px) and (orientation:landscape){
  .lovetitle{grid-auto-flow:column;justify-content:center;align-items:baseline}
  .lovetitle__l{font-size:min(15.1vw,34vh)}
}

/* ══════════ EVERY LINE MOVES ══════════
   His instruction was every single line. So the reveal is no longer
   something a few elements opt into — it is the default state of text
   on this page, and it arrives with light, not just position. */
[data-reveal]{will-change:opacity,transform}
[data-reveal].seen{animation:line-land 1.15s var(--ease) var(--rd,0ms) both}
@keyframes line-land{
  from{opacity:0;transform:translateY(38px) scale(.965);filter:blur(7px)}
  to{opacity:1;transform:none;filter:blur(0)}}

/* Each sentence of his becomes its own line, so each one can arrive on its
   own and stand in its own air. Split at runtime — the markup keeps his
   paragraphs whole, and the words themselves are never touched. */
.ln{display:block}
.ln + .ln{margin-top:.86em}

/* the statement lines — his big single-sentence beats */
.beat{font-family:var(--f-display);font-weight:800;text-align:center;
  font-size:clamp(1.9rem,7.6vw,3.2rem);line-height:1.14;letter-spacing:-.03em;
  color:var(--ink);text-wrap:balance}
.beat--hot{color:var(--rose-hot);text-shadow:var(--text-glow)}
.beat--open{color:var(--ink);
  text-shadow:0 0 26px rgba(79,240,255,.34),0 0 70px rgba(167,139,250,.3)}
/* the last words on the page */
.finale{font-family:var(--f-display);font-weight:800;text-align:center;
  font-size:clamp(2.5rem,10.4vw,5rem);line-height:1.02;letter-spacing:-.035em;
  color:var(--rose-hot);text-wrap:balance;
  text-shadow:0 0 34px rgba(255,77,141,.7),0 0 96px rgba(167,139,250,.4)}

/* ══════════ THE ARRIVAL LINE ══════════
   Twelve of twelve no longer reports a number back at the visitor.
   It says the thing the whole page is for. */
.movecue{flex-direction:column;gap:6px;text-align:center;padding:16px 26px;
  transition:box-shadow .5s var(--ease),border-color .5s var(--ease),padding .5s var(--ease)}
.movecue .dot{flex:0 0 auto}
#cue{display:block;font-size:clamp(.78rem,2.9vw,.92rem);letter-spacing:.2em;line-height:1.5}
#cue b{display:block;font-family:var(--f-display);font-weight:800;text-transform:none;
  letter-spacing:-.02em;font-size:clamp(1.34rem,5.4vw,2rem);line-height:1.16;
  color:var(--rose-hot);margin-top:10px;text-shadow:var(--text-glow)}
html.full .movecue{padding:22px 30px}

/* ══════════ SOUND ══════════
   Off until asked. Browsers gate audio behind a gesture and so do we —
   nobody gets sound they did not choose. */
.sound{position:fixed;right:16px;bottom:calc(16px + env(safe-area-inset-bottom));z-index:40;
  width:52px;height:52px;border-radius:50%;cursor:pointer;display:grid;place-items:center;
  background:var(--glass-2);border:1px solid var(--edge-hi);color:var(--rose-hot);
  -webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
  box-shadow:0 8px 30px rgba(0,0,0,.5),inset 0 1px 0 rgba(255,190,215,.16);
  transition:transform .3s var(--ease),box-shadow .3s var(--ease),color .3s var(--ease)}
.sound:hover{transform:translateY(-2px);box-shadow:0 0 34px rgba(255,77,141,.5)}
.sound svg{width:22px;height:22px}
.sound .on{display:none}
.sound[aria-pressed="true"]{color:var(--cyan);border-color:rgba(79,240,255,.5);
  box-shadow:0 0 30px rgba(79,240,255,.34),inset 0 1px 0 rgba(255,255,255,.16)}
.sound[aria-pressed="true"] .on{display:block}
.sound[aria-pressed="true"] .off{display:none}

@media(prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation:none!important;transition:none!important}
  [data-reveal]{opacity:1;transform:none;filter:none}
}
