.grove-canopy{position:absolute;inset:0;z-index:-2;pointer-events:none;background:url('assets/grove.png') center 52%/cover;transform-origin:50% 80%;will-change:transform}.canopy-left{mask-image:linear-gradient(90deg,#000,transparent 38%),linear-gradient(#000,transparent 80%);mask-composite:intersect;animation:canopy-sway 11s ease-in-out infinite alternate}.canopy-right{mask-image:linear-gradient(270deg,#000,transparent 38%),linear-gradient(#000,transparent 85%);mask-composite:intersect;animation:canopy-sway 14s -6s ease-in-out infinite alternate-reverse}.portal{animation:stone-hum 8s ease-in-out infinite}.portal-window{animation:rainbow-breathe 36s linear infinite}.portal-glow{animation:rainbow-halo 36s linear infinite}.motes{inset:0 -20%;height:100%;overflow:visible}.motes i,.motes i:nth-child(n){left:var(--x);top:auto;bottom:-110px;width:auto;height:auto;background:none;color:#eed77e;font:700 18px/1 serif;box-shadow:none;text-shadow:0 0 8px #ebc66b,0 0 18px #eacb7299;animation:gold-rise var(--duration) var(--delay) linear infinite}.preview-controls{display:flex;gap:18px;align-items:center;justify-content:center;padding:14px;flex-wrap:wrap;font-size:12px}.preview-controls .button{font-size:12px;min-height:36px;padding:8px 15px}@keyframes canopy-sway{from{transform:skewX(-.25deg) translateX(-2px)}to{transform:skewX(.3deg) translateX(3px)}}@keyframes stone-hum{0%,100%{transform:translateX(-50%) scale(1)}50%{transform:translateX(-50%) scale(1.005)}}@keyframes rainbow-breathe{0%{filter:blur(4px) hue-rotate(0deg) brightness(1);transform:scale(1)}12.5%{filter:blur(4px) hue-rotate(45deg) brightness(1.2);transform:scale(1.025)}25%{filter:blur(4px) hue-rotate(90deg) brightness(1);transform:scale(1)}37.5%{filter:blur(4px) hue-rotate(135deg) brightness(1.2);transform:scale(1.025)}50%{filter:blur(4px) hue-rotate(180deg) brightness(1);transform:scale(1)}62.5%{filter:blur(4px) hue-rotate(225deg) brightness(1.2);transform:scale(1.025)}75%{filter:blur(4px) hue-rotate(270deg) brightness(1);transform:scale(1)}87.5%{filter:blur(4px) hue-rotate(315deg) brightness(1.2);transform:scale(1.025)}100%{filter:blur(4px) hue-rotate(360deg) brightness(1);transform:scale(1)}}@keyframes rainbow-halo{0%{filter:hue-rotate(0deg);opacity:.65;transform:scale(1)}50%{filter:hue-rotate(180deg);opacity:1;transform:scale(1.07)}100%{filter:hue-rotate(360deg);opacity:.65;transform:scale(1)}}@keyframes gold-rise{0%{transform:translate(0,0);opacity:0}8%{opacity:.7}88%{opacity:.65}100%{transform:translate(var(--wander),-1050px);opacity:0}}@media(prefers-reduced-motion:reduce){body:not(.preview-motion) .grove-canopy,body:not(.preview-motion) .portal,body:not(.preview-motion) .portal-window,body:not(.preview-motion) .portal-glow,body:not(.preview-motion) .motes i{animation:none!important}body:not(.preview-motion) .motes i{bottom:35%;opacity:.5}}
/* Explicit preview opt-in overrides the browser's reduced-motion setting. */
body.preview-motion .canopy-left{animation:canopy-sway 11s ease-in-out infinite alternate!important}body.preview-motion .canopy-right{animation:canopy-sway 14s -6s ease-in-out infinite alternate-reverse!important}body.preview-motion .portal{animation:stone-hum 8s ease-in-out infinite!important}body.preview-motion .portal-window{animation:rainbow-breathe 36s linear infinite!important}body.preview-motion .portal-glow{animation:rainbow-halo 36s linear infinite!important}body.preview-motion .motes i{animation:gold-rise var(--duration) var(--delay) linear infinite!important}
/* Second preview: stronger canopy movement and faster, contained portal breath. */
.canopy-left{transform-origin:12% 74%}.canopy-right{transform-origin:88% 76%}
@keyframes canopy-sway{0%{transform:skewX(-.55deg) rotate(-.15deg) translateX(-3px)}50%{transform:skewX(.15deg) rotate(.05deg) translateX(1px)}100%{transform:skewX(.7deg) rotate(.2deg) translateX(5px)}}
.portal-window{overflow:hidden;clip-path:inset(0 round 48% 48% 5% 5%);transform:none;background:#8aaf7d;animation:none}
.portal-window:before{content:'';position:absolute;inset:-12%;border-radius:48% 48% 5% 5%;background:radial-gradient(ellipse at 50% 55%,#f2ffd9 0%,#d4f394 21%,#92c264bb 44%,#55915e77 65%,transparent 79%),repeating-conic-gradient(from 45deg,#a5d7a3,#d5efa7 32deg,#3e817960 72deg,#b3d0a9 100deg);transform-origin:50% 55%;animation:inner-breath 5.5s ease-in-out infinite,rainbow-current 16s linear infinite;will-change:transform,filter}
@keyframes inner-breath{0%,100%{transform:scale(.86);opacity:.7}50%{transform:scale(1.13);opacity:1}}
@keyframes rainbow-current{from{filter:hue-rotate(0deg) blur(4px) brightness(1.12) saturate(1.45)}to{filter:hue-rotate(360deg) blur(4px) brightness(1.12) saturate(1.45)}}
.portal-glow{animation:rainbow-halo 16s linear infinite}.portal{animation:none}
body.preview-motion .portal{animation:none!important}body.preview-motion .portal-window{animation:none!important}body.preview-motion .portal-window:before{animation:inner-breath 5.5s ease-in-out infinite,rainbow-current 16s linear infinite!important}body.preview-motion .portal-glow{animation:rainbow-halo 16s linear infinite!important}
@media(prefers-reduced-motion:reduce){body:not(.preview-motion) .portal-window:before{animation:none!important}}
/* Visible motion correction: portal artwork contains its own opaque light. */
.portal-window{z-index:3;left:34%;right:33%;top:25%;bottom:5%;background:transparent;filter:none;mix-blend-mode:screen;border-radius:48% 48% 4% 4%;clip-path:inset(0 round 48% 48% 4% 4%)}
.portal-window:before{inset:2%;background:radial-gradient(ellipse at 50% 53%,#fff8dd 0%,#e2ffa4ee 25%,#88e958aa 47%,#58b98955 63%,transparent 76%);transform-origin:50% 55%}
@keyframes inner-breath{0%,100%{transform:scale(.72,.8);opacity:.35}50%{transform:scale(1.17,1.12);opacity:.95}}
@keyframes rainbow-current{from{filter:hue-rotate(0deg) blur(6px) saturate(2)}to{filter:hue-rotate(360deg) blur(6px) saturate(2)}}
.canopy-left{mask-image:linear-gradient(90deg,#000 0%,#000 13%,transparent 39%),linear-gradient(#000 0%,#000 33%,transparent 83%);mask-composite:intersect;transform-origin:10% 90%}
.canopy-right{mask-image:linear-gradient(270deg,#000 0%,#000 14%,transparent 39%),linear-gradient(#000 0%,#000 33%,transparent 86%);mask-composite:intersect;transform-origin:90% 90%}
@keyframes canopy-sway{0%{transform:rotate(-1.1deg) skewX(-1deg) translateX(-8px)}50%{transform:rotate(.2deg) skewX(.3deg) translateX(2px)}100%{transform:rotate(1.2deg) skewX(1.1deg) translateX(9px)}}
body.preview-motion .canopy-left{animation:canopy-sway 7s ease-in-out infinite alternate!important}body.preview-motion .canopy-right{animation:canopy-sway 9s -3s ease-in-out infinite alternate-reverse!important}
/* Wider breathing range: 10% smaller to 150%, with a soft spill outside the arch. */
.portal-window{overflow:visible;clip-path:none}
@keyframes inner-breath{0%,100%{transform:scale(.9);opacity:.65}50%{transform:scale(1.5);opacity:.95}}
/* Local leafy branch-tip bending; trunks, scenery and stone stay stationary. */
.branch-tip{position:absolute;inset:0;z-index:-2;pointer-events:none;background:url('assets/grove.png') center 52%/cover}
.branch-tip-one{mask-image:radial-gradient(ellipse 13% 15% at 89% 19%,#000 40%,transparent 100%);filter:url('#branch-bend-a')}
.branch-tip-two{mask-image:radial-gradient(ellipse 10% 12% at 79% 35%,#000 40%,transparent 100%);filter:url('#branch-bend-b')}
.branch-tip-three{mask-image:radial-gradient(ellipse 9% 13% at 20% 28%,#000 40%,transparent 100%);filter:url('#branch-bend-a')}
@media(prefers-reduced-motion:reduce){body:not(.preview-motion) .branch-tip{filter:none}}
/* A shadowy dwarf waiting just inside the portal threshold. */
.portal-dwarf-silhouette{position:absolute;z-index:4;left:50%;bottom:4%;width:23%;height:44%;transform:translateX(-50%);background:#102022;opacity:.38;mask:url('assets/grovekeeper.png') center bottom/contain no-repeat;pointer-events:none;filter:drop-shadow(0 0 5px #09262b)}
.portal-dwarf-silhouette{mask-image:url('assets/warrior.svg?v=6a7573eee93a571a');width:32.5%;height:48.75%;opacity:.4}

.grove-controls{display:flex;justify-content:center;gap:8px;flex-wrap:wrap;margin-top:10px}.grove-controls .button{min-height:30px;padding:6px 10px;font-size:10px}#motion{display:none}@media(prefers-reduced-motion:reduce){#motion{display:inline-flex}}

/* Suspend invisible grove work, including explicit reduced-motion opt-in. */
.hero.grove-paused .portal-glow,.hero.grove-paused .portal-window:before,.hero.grove-paused .motes i{animation-play-state:paused!important}
.hero.grove-paused .branch-tip{filter:none}

/* Motion starts enabled; the viewer can pause the grove explicitly. */
#motion{display:inline-flex}
body:not(.preview-motion) .hero *,body:not(.preview-motion) .hero *:before,body:not(.preview-motion) .hero *:after{animation-play-state:paused!important}

/* Suspend every grove animation when the hero is hidden or outside view. */
.hero.grove-paused *, .hero.grove-paused *:before, .hero.grove-paused *:after{animation-play-state:paused!important}
