/* ============ MEDIA LOADING SHIMMER — one shared tier (mediaload.css + mediaload.js) ============
   A calm cream-on-cream sweep on heavy-media boxes while their media loads — never a gray
   skeleton, never high contrast. Consumers opt in with data-mload on the media's positioned,
   radius-clipped container (today: Case study .vframe, Expertise .cover); NEVER on a WebGL/GL
   plane or a GL-composited surface. Look: a flat cream veil (rgba(246,240,231,.10)) plus one
   soft cream highlight (peak .30) sweeping left-to-right on a 1800ms loop with an off-screen
   pause between sweeps. mediaload.js arms .mlon only while the media is genuinely loading;
   the veil's opacity-in carries a 150ms delay so cached/instant loads never flash it, and it
   fades out in 150ms on the media's first frame. Pure overlay (::after, pointer-events:none,
   border-radius:inherit): the reserved boxes stay byte-identical, zero layout impact.
   Reduced motion: the static tint, no sweep. Linked from the consuming page's helmet. */
[data-mload]::after{content:"";position:absolute;inset:0;z-index:2;pointer-events:none;border-radius:inherit;opacity:0;background-color:rgba(246,240,231,.10);background-image:linear-gradient(105deg,rgba(246,240,231,0) 32%,rgba(246,240,231,.30) 50%,rgba(246,240,231,0) 68%);background-repeat:no-repeat;background-size:220% 100%;background-position:120% 0;transition:opacity .15s var(--ease,ease)}
[data-mload].mlon::after{opacity:1;transition:opacity .2s var(--ease,ease) .15s;animation:mlsweep 1800ms linear infinite}
@keyframes mlsweep{from{background-position:120% 0}to{background-position:-120% 0}}
/* Hard-cut clear for hidden-but-painting embedders (frozen timeline: the fade never plays). */
[data-mload].mlx::after{transition:none!important;animation:none!important;opacity:0!important}
@media (prefers-reduced-motion:reduce){[data-mload].mlon::after{animation:none}}
