/* vo-smooth.css — loaded LAST on every page, so it wins over the inline styles.
 *
 * Measured 2026-11-14 on the live home page: one 27.8 s main-thread task, 4
 * painted frames while scrolling the whole page, and ~4.8 s of blocked time per
 * 10 s with nobody touching it. The JavaScript was cheap (~300 ms); the time
 * was raster. Causes, each fixed below:
 *   1. 41 decorative shapes animating forever, on and off screen, many of them
 *      under frosted-glass (backdrop-filter) cards that must re-blur every frame.
 *   2. Every link click waited 350 ms to fade the page out before the next one
 *      even started loading, then <body> itself slid in for 600 ms.
 *   3. The tabs animated max-height 0 -> 1000px, a full re-layout per frame.
 */

/* ── 2. Page to page: the browser cross-fades, the click never waits ───────── */
@view-transition { navigation: auto; }
::view-transition-group(root) { animation-duration: .22s; }

/* A transform left on <body> (the old entrance's fill) makes it the containing
   block for every position:fixed child, and sliding it rasterises the whole
   page. Fade only, and only where the browser has no cross-fade of its own. */
body { animation: voSmoothIn .25s ease-out both !important; transform: none !important; }
@supports (view-transition-name: none) { body { animation: none !important; } }
.vo { animation: none !important; }
body.vo-page-leaving, .vo.vo-leaving { opacity: 1 !important; transform: none !important; }
@keyframes voSmoothIn { from { opacity: 0 } to { opacity: 1 } }

/* ── 1. Decoration moves on its own layer, and only while you can see it ───── */
[style*="infinite"] { will-change: transform; }
.vo-still, .vo-scrolling .vo-loop { animation-play-state: paused !important; }

/* Frosted glass re-blurs everything behind it on every scrolled frame. With
   GPU rendering on, removing it alone took scrolling from 10 to 23 fps. The
   cards keep their translucent fill and border, so they still read as glass
   over the green sections. */
*, *::before, *::after { -webkit-backdrop-filter: none !important; backdrop-filter: none !important; }

/* ── 3. Tabs: swap instantly, then ease in with opacity + transform only ──── */
.ws-panel { max-height: none !important; display: none; transition: none !important; }
#ws0:checked ~ .ws-p0, #ws1:checked ~ .ws-p1, #ws2:checked ~ .ws-p2, #ws3:checked ~ .ws-p3 {
  display: block; animation: voTabIn .32s cubic-bezier(.2, .7, .2, 1) both;
}
@keyframes voTabIn { from { opacity: 0; transform: translateY(6px) } to { opacity: 1; transform: none } }

@media (prefers-reduced-motion: reduce) {
  [style*="infinite"] { animation: none !important; }
  ::view-transition-group(root) { animation: none; }
}
