/* Animated warm background — .bg-stage + .bg-grain. Body stays transparent so
   the stage shows through. All texture layers opacity-tunable via --bg-* vars. */
:root{
  --bg-dot-opacity:0.04;
  --bg-dot-size:48px;
  --bg-dot-radius:4.7px;
  --bg-sheen-opacity:0.32;
  --bg-vignette-opacity:0.26;
  --bg-grain-opacity:0.66;
  --bg-blob-opacity:0.12;
}
.bg-stage{position:fixed;inset:0;z-index:-2;overflow:hidden;background:linear-gradient(115deg,transparent 0%,oklch(96% 0.012 80 / var(--bg-sheen-opacity)) 38%,transparent 62%),radial-gradient(ellipse at top left,oklch(88% 0.035 65) 0%,transparent 50%),radial-gradient(ellipse at bottom right,oklch(80% 0.040 55) 0%,transparent 60%),oklch(83% 0.030 60)}
.bg-stage::before{content:"";position:absolute;inset:0;pointer-events:none;background:radial-gradient(ellipse at center,transparent 50%,oklch(55% 0.040 55 / var(--bg-vignette-opacity)) 100%)}
.bg-stage::after{content:"";position:absolute;inset:0;pointer-events:none;background-image:radial-gradient(circle at 50% 50%,oklch(20% 0.025 60) 0,oklch(20% 0.025 60) var(--bg-dot-radius),transparent calc(var(--bg-dot-radius) + 0.6px));background-size:var(--bg-dot-size) var(--bg-dot-size);opacity:var(--bg-dot-opacity);mix-blend-mode:multiply}
.blob{position:absolute;border-radius:50%;filter:blur(70px);opacity:var(--bg-blob-opacity);will-change:transform}
.blob.b1{width:540px;height:540px;background:radial-gradient(circle,oklch(70% 0.22 140) 0%,transparent 70%);top:-10%;left:-8%;animation:drift1 28s ease-in-out infinite alternate}
.blob.b2{width:420px;height:420px;background:radial-gradient(circle,oklch(72% 0.18 85) 0%,transparent 70%);top:18%;right:-5%;animation:drift2 34s ease-in-out infinite alternate}
.blob.b3{width:480px;height:480px;background:radial-gradient(circle,oklch(60% 0.16 288) 0%,transparent 70%);bottom:-12%;left:22%;animation:drift3 40s ease-in-out infinite alternate}
.blob.b4{width:360px;height:360px;background:radial-gradient(circle,oklch(58% 0.18 25) 0%,transparent 70%);top:50%;right:28%;animation:drift4 32s ease-in-out infinite alternate;opacity:calc(var(--bg-blob-opacity) * 0.76)}
@keyframes drift1{0%{transform:translate(0,0) scale(1)}100%{transform:translate(140px,100px) scale(1.15)}}
@keyframes drift2{0%{transform:translate(0,0) scale(1)}100%{transform:translate(-160px,160px) scale(0.92)}}
@keyframes drift3{0%{transform:translate(0,0) scale(1)}100%{transform:translate(180px,-120px) scale(1.08)}}
@keyframes drift4{0%{transform:translate(0,0) scale(1)}100%{transform:translate(-100px,-180px) scale(1.2)}}
@media (prefers-reduced-motion:reduce){.blob{animation:none !important}}
.bg-grain{position:fixed;inset:0;z-index:-1;pointer-events:none;opacity:var(--bg-grain-opacity);mix-blend-mode:overlay;background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='320' height='320'><filter id='n2'><feTurbulence type='fractalNoise' baseFrequency='0.32' numOctaves='1' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.30 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n2)' opacity='0.55'/></svg>"),url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.45 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)' opacity='0.6'/></svg>");background-size:320px 320px,180px 180px}
