/* Site-wide motion, shared by every page. Entrances are pure CSS (they play
   even if the script fails); scroll reveals, the floating bubbles and the
   stagger are added by motion.js. Everything animates transform/opacity only,
   so it stays smooth on low-end phones. */

/* ── Floating bubbles behind the page ─────────────────────────────── */
.bubbles{position:fixed;inset:0;z-index:-1;pointer-events:none;overflow:hidden;}
.bubbles i{
  position:absolute;border-radius:50%;opacity:.4;
  animation:bubble linear infinite;will-change:transform;
}
@keyframes bubble{
  0%{transform:translate3d(0,0,0) scale(1);}
  50%{transform:translate3d(var(--dx,30px),-68vh,0) scale(1.15);}
  100%{transform:translate3d(0,-140vh,0) scale(1);}
}

/* ── Entrances: one line after another ────────────────────────────── */
@keyframes rise{from{opacity:0;transform:translateY(22px);}to{opacity:1;transform:none;}}
@keyframes pop{
  0%{opacity:0;transform:scale(.55) rotate(-8deg);}
  60%{opacity:1;transform:scale(1.08) rotate(3deg);}
  100%{opacity:1;transform:none;}
}
@keyframes float{0%,100%{transform:translateY(0);}50%{transform:translateY(-7px);}}
@keyframes shine{0%{background-position:120% 0;}60%,100%{background-position:-60% 0;}}

/* Homepage hero. The icon pops in, then keeps floating; one animation
   property for both, or the float would cancel the pop. */
.card > .pad:first-child .icon{
  animation:pop .8s cubic-bezier(.2,.8,.3,1.2) .05s both,
            float 4.5s ease-in-out 1s infinite;
}
.card > .pad:first-child .wm{animation:rise .8s cubic-bezier(.2,.7,.2,1) .25s both;}
.card > .pad:first-child .tag .lead{animation:rise .8s cubic-bezier(.2,.7,.2,1) .42s both;}
.card > .pad:first-child .tag span:not(.lead){animation:rise .8s cubic-bezier(.2,.7,.2,1) .56s both;}
.card > .pad:first-child .stores.top{animation:rise .8s cubic-bezier(.2,.7,.2,1) .63s both;}
.card > .pad:first-child .peek{animation:rise .8s cubic-bezier(.2,.7,.2,1) .75s both;}
.spot{animation:rise 1s cubic-bezier(.2,.7,.2,1) .8s both;}
.shots{animation:rise 1s cubic-bezier(.2,.7,.2,1) .8s both;}
.spot .big{animation:float 6s ease-in-out 2s infinite;}

/* A gentle colour pulse on the headline. SOLID colour on purpose — it used to
   be a gradient clipped to the letters, and Samsung Internet (which tells the
   site "light" and then darkens the page itself) turned it invisible on the
   owner's phone, 2026-10-10. Never use background-clip:text on this site. */
.tag .lead{color:#2E0249;}
.card > .pad:first-child .tag .lead{
  animation:rise .8s cubic-bezier(.2,.7,.2,1) .42s both,
            leadPulse 5s ease-in-out 1.6s infinite;
}
@keyframes leadPulse{0%,100%{color:#2E0249;}50%{color:#A80077;}}

/* Thumbnails drop in one by one */
.thumbs button{animation:rise .6s cubic-bezier(.2,.7,.2,1) both;}
.thumbs button:nth-child(1){animation-delay:1.05s}
.thumbs button:nth-child(2){animation-delay:1.13s}
.thumbs button:nth-child(3){animation-delay:1.21s}
.thumbs button:nth-child(4){animation-delay:1.29s}
.thumbs button:nth-child(5){animation-delay:1.37s}
.thumbs button:nth-child(6){animation-delay:1.45s}

/* Store buttons: lift + glow */
.store{transition:transform .2s ease,box-shadow .2s ease,opacity .15s ease;}
.store:hover{transform:translateY(-3px);box-shadow:0 10px 22px rgba(168,0,119,.3);}

/* Policy pages: the coloured header rises in, its colours slowly drift and
   a soft light passes over it. */
header{
  position:relative;overflow:hidden;
  background-size:180% 180% !important;
  animation:rise .8s cubic-bezier(.2,.7,.2,1) both,
            drift 14s ease-in-out 1s infinite alternate;
}
@keyframes drift{from{background-position:0% 30%;}to{background-position:100% 70%;}}
header::after{
  content:"";position:absolute;top:0;bottom:0;left:-60%;width:45%;pointer-events:none;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.22),transparent);
  transform:skewX(-18deg);animation:sweep 6s ease-in-out 1.4s infinite;
}
@keyframes sweep{0%{left:-60%;}45%,100%{left:130%;}}
header > *{animation:rise .7s cubic-bezier(.2,.7,.2,1) both;}
header > *:nth-child(1){animation-delay:.2s}
header > *:nth-child(2){animation-delay:.32s}
header > *:nth-child(3){animation-delay:.44s}

/* Section titles get a bar that grows in when the section arrives */
section h2::after{
  content:"";display:block;width:0;height:3px;margin-top:8px;border-radius:2px;
  /* Solid, not a gradient: Samsung Internet's own darkening dimmed the
     gradient bar to almost nothing (owner's phone, 2026-10-10). */
  background:#E91E8C;
  transition:width .9s cubic-bezier(.2,.7,.2,1) .25s;
}
/* List bullets in a clear brand pink — the default dots went almost
   invisible under Samsung Internet's darkening. */
li::marker{color:#E91E8C;}
section.in h2::after{width:56px;}
section{transition:transform .3s cubic-bezier(.2,.7,.2,1),box-shadow .3s;}
@media(hover:hover){
  section:hover{transform:translateY(-3px);box-shadow:var(--surface-hover-shadow,0 12px 30px rgba(74,20,140,.12));}
}

/* 404 */
body > main > .icon{
  animation:pop .8s cubic-bezier(.2,.8,.3,1.2) both,float 4.5s ease-in-out 1s infinite;
}
body > main > h1{animation:rise .8s cubic-bezier(.2,.7,.2,1) .25s both;}
body > main > p{animation:rise .8s cubic-bezier(.2,.7,.2,1) .4s both;}
body > main > a.home{animation:rise .8s cubic-bezier(.2,.7,.2,1) .55s both;}

/* ── Scroll reveal (classes set by motion.js) ─────────────────────── */
.reveal{opacity:0;transform:translateY(26px);
  transition:opacity .7s ease,transform .7s cubic-bezier(.2,.7,.2,1) !important;}
.reveal.in{opacity:1;transform:none;}

/* ── Calm mode ────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation:none !important;transition:none !important;}
  .reveal{opacity:1 !important;transform:none !important;}
  .bubbles{display:none;}
  section h2::after{width:56px;}
  .tag .lead{background:none;color:#2E0249;}
}

/* ── Dark scheme ──────────────────────────────────────────────────── */
/* The headline is gradient-clipped text; the light gradient is deep purple,
   which disappears on the dark background. */

  :root[data-theme="dark"] .tag .lead {color:#E7C6EE;}
  :root[data-theme="dark"] .card > .pad:first-child .tag .lead {
    animation:rise .8s cubic-bezier(.2,.7,.2,1) .42s both,
              leadPulseDark 5s ease-in-out 1.6s infinite;
  }
  :root[data-theme="dark"] .store:hover {box-shadow:0 0 0 1px rgba(225,190,231,.3),0 10px 24px rgba(233,30,140,.35);}
  /* softer bubbles: at full strength their white highlight reads as grey balls on dark */
  :root[data-theme="dark"] .bubbles i {opacity:.28;filter:saturate(1.8);}

@keyframes leadPulseDark{0%,100%{color:#E7C6EE;}50%{color:#F7A8D8;}}
@media (prefers-reduced-motion: reduce){
  :root[data-theme="dark"] .tag .lead {background:none;color:#E7C6EE;}
}

/* ── Theme button (assets/theme.js): small, top corner, scrolls away with the page ── */
.theme-btn{
  position:absolute;top:10px;right:10px;z-index:50;
  width:32px;height:32px;padding:0;border-radius:50%;
  display:flex;align-items:center;justify-content:center;cursor:pointer;
  border:1px solid rgba(46,2,73,.14);background:rgba(255,255,255,.82);color:#2E0249;
  box-shadow:0 2px 8px rgba(46,2,73,.12);
  -webkit-tap-highlight-color:transparent;transition:transform .15s ease;
}
.theme-btn:hover{transform:scale(1.08);}
.theme-btn:focus-visible{outline:2px solid #E91E8C;outline-offset:2px;}
:root[data-theme="dark"] .theme-btn{background:rgba(35,18,54,.85);border-color:rgba(225,190,231,.22);color:#F7D774;box-shadow:0 2px 8px rgba(0,0,0,.35);}