Commit Graph

2401 Commits

Author SHA1 Message Date
Miguel Angel Simon Sierra ff99e673ca fix(core): skip implicit transform from-correction when an earlier explicit tween owns the property
The U-final CSS-cascade correction picked the earliest IMPLICIT tween per
(target, property), so an implicit fade tween stacked after an explicit
burst tween (e.g. apple-money-count's confetti: translateY [0, y] then an
implicit drift-and-fade) was rewritten to the page-load identity value,
discarding anime.js's correct chain from the burst's end value and
collapsing the burst mid-flight (22.0dB at t=4.42s vs the GSAP baseline).

Correct an implicit tween only when it is the first tween of ANY kind on
its (target, property) pair. Verified by full re-render: apple-money-count
t=4.42s recovers to 50.0dB and vfx-liquid-glass's t=0.2-0.6s low band
recovers to 45.1dB; the product-promo stacked-implicit case that motivated
the earliest-implicit narrowing keeps its behavior (unit-tested).
2026-07-11 03:43:38 -04:00
Miguel Angel Simon Sierra 981378684b test(producer): linux docker goldens for animejs determinism fixtures and refreshed adapter golden 2026-07-11 02:41:13 -04:00
Miguel Angel Simon Sierra 2f529315a8 feat(player): snappier controls reveal and immediate first probe tick 2026-07-10 20:08:55 -04:00
Miguel Angel Simon Sierra ed3e552db4 Merge branch 'fix-family-a' into worktree-feat-animejs-first-party 2026-07-10 14:20:23 -04:00
Miguel Angel Simon Sierra 8e5bd11aa4 fix(registry): match GSAP center-stagger slot semantics in us-map and spain-map
Same defect class as the earlier world-map and parallax fixes: GSAP's
stagger { each, from: "center" } assigns every element a UNIQUE slot,
ordered center-out (total span = each * (n-1)). anime.stagger(value,
{ from: "center" }) instead scales delay by distance from center, so
equidistant pairs share a slot and the reveal finishes in about half
the time.

us-map: live probe (GSAP fork-point timeline vs anime, same instants)
showed the old anime reveal at 6/46/50/50 states visible at
t=1.197/2.393/3.59/4.787s against GSAP's 4/24/44/50 -- the state map
was fully lit two seconds before the GSAP baseline. Precomputed rank
delays now match GSAP exactly at every probed instant (4/24/44/50).

spain-map: same fix for the region reveal and region-label stagger.
Old anime reveal was fully lit (19/19 regions) by t=2.393s vs GSAP's
17/19; fixed version now shows 18/19 at that instant (within the
one-element tolerance already established by the world-map fix).
2026-07-10 14:18:12 -04:00
Miguel Angel Simon Sierra 3a0049a1cd fix(core): mute priming-seek callbacks in anime.js adapter
primeAnimeInstance() seeks every registered timeline to its full
duration and back to 0 at registration time, purely to force
lazily-rendered CSS onto elements before the composition's first real
seek. anime.js fires tl.call()/onComplete callbacks as a side effect
of any seek that crosses their position, including this internal
priming seek -- so a composition using tl.call() (or a raw onComplete
tween) renders as if it had already reached that callback's end state
from frame 0 onward, regardless of the time actually requested later.

anime.js's own Timer.prototype.seek(time, muteCallbacks) already
suppresses onBegin/onComplete/onUpdate/onLoop/onRender for a given
seek; pass true on both priming seeks instead of reimplementing that
suppression. Widened RuntimeAnimeInstance.seek to accept the optional
second argument.

Confirmed against liquid-glass-widgets (a tl.call() status-text swap
scheduled at t=5.2s was rendering already-fired at t=1.434s) and
flowchart/flowchart-vertical (their addTimelineCall()/onComplete
helper had the whole diagram, cursor, and text-correction sequence
visible from frame 0). Added a regression test exercising the same
tl.call()-during-priming scenario directly against the adapter.
2026-07-10 14:17:53 -04:00
Miguel Angel Simon Sierra ec83da1479 Merge branch 'fix-open-items-b' into worktree-feat-animejs-first-party 2026-07-10 13:37:02 -04:00
Miguel Angel Simon Sierra 4ccc55c5fa fix(registry): drop engine-name mention from airbnb-deck comment tripping validate
The validate static guard greps compositions for GSAP usage; the explanatory
comment added with the deterministic-entrances fix mentioned the original
API by name and produced a false 'uses GSAP but no GSAP script is loaded'
error. Reword the comment.
2026-07-10 13:33:57 -04:00
Miguel Angel Simon Sierra 4561205d11 fix(registry): reveal play-mode HYPERFRAMES title stuck at individual CSS scale 0
The intro title was hidden with the individual CSS 'scale: 0' property.
anime.js animates scale through its own inline transform and never clears
the individual property, so the two multiplied and the headline stayed at
scale 0 for the whole clip (the cleanest Family B evidence on record: the
sibling pink pill rendered while the headline was missing at t=0.9). GSAP
folds individual transform properties into its transform management, which
is why the identical authoring worked in the baseline.

Drop the CSS 'scale: 0' (opacity 0 already hides the title) and drive scale
explicitly from the timeline (scale: [0, 1.1]). Also pin the ambient wobble
to rotate: ['0deg', '-3deg']: the pinned baseline renders the entrance
untilted because GSAP dropped the stylesheet rotate(-5deg) when taking over
the transform (its known axis-loss behavior, reproduced for parity, per the
x-post precedent).

Verified by snapshot at t=0.9/1.3/2.49 vs the pinned baseline: headline now
present and matching; note the baseline clip is 10s while the composition
is 15.6s (end card beyond baseline coverage).
2026-07-10 13:33:56 -04:00
Miguel Angel Simon Sierra 6bf2010889 fix(registry): derive airbnb-deck slide entrances from composition time
Scene entrances and problem fragments fired wall-clock anime.animate() calls
from the visibility controller (mirroring the GSAP original's gsap.from()).
Autoplaying animations run on anime's own rAF engine, which does not advance
under the seek-driven render pipeline, so slide content rendered stuck at
opacity 0 or mid-fade for the entire scene: the ADOPTION STRATEGY slide was
completely empty at t=63.7s and the MARKET SIZE footnote missing at t=41s,
while the GSAP baseline only survived because GSAP's ticker happened to keep
ticking between captures.

Compute entrance and fragment progress as a pure function of composition
time inside updateVisibility (same authored motion: 400ms/70ms-stagger
outCubic entrances, 350ms fragment slides) -- deterministic under seeking in
both directions, and the interactive slideshow path behaves the same.

Verified by snapshot at t=9.72/41.03/63.7 vs the pinned baseline: all slides
now render their full content; the only residual difference is fragments
mid-authored-fade where the baseline shows them prematurely settled.
2026-07-10 13:24:06 -04:00
Miguel Angel Simon Sierra c67c7ba6ef fix(registry): match GSAP center-stagger slot semantics in parallax card fades
Same defect class as the world-map fix: GSAP's stagger { each, from:
'center' } assigns each card a unique slot in center-out order (span =
each * (n-1)), while anime.stagger(value, { from: 'center' }) scales delay
by distance from center so equidistant pairs share slots and the cascade
finishes in half the time.

parallax-zoom: all 15 cards were lit by t=0.36s vs the GSAP baseline's
~0.9s completion, matching the damaged t=0.12-0.6s opening window. Live
probe after the fix: 1/5/9/13/15 cards visible at t=0.12/0.24/0.36/0.48/0.6
-- on the GSAP schedule; snapshots at 0.36/0.42 match the baseline pattern.

parallax-unzoom: same stagger on the non-focus card fade-in at t=2.0s,
matching its damaged t=2.27-3.16s window; snapshots at 2.39/2.57/2.86 now
match the baseline cascade.

(The parallax-zoom snippet twin has no card stagger; demo-only.)
2026-07-10 13:19:38 -04:00
Miguel Angel Simon Sierra e6fde21048 fix(registry): reveal caption-clip-wipe group-final words lost to staggered exit add
The exit wipe used one multi-target add with delay: anime.stagger(40). For
any word whose reveal window overlaps the group exit window (the last words
of each caption group), anime bakes a duplicate exit tween node into the
word's reveal child with the implicit 'from' resolved to the PRE-REVEAL
hidden state (inset right 100%), and that node clobbers the reveal -- the
word never appears ('starts' stayed invisible through t=0.85-1.15s while the
GSAP baseline shows it wiping in; verified via anime internals dump:
duplicate clip-path node from [0,100,0,0] at st=120 inside the reveal child).

Replace the staggered add with a per-word loop at explicit positions
(g.end - 0.2 + i*40), which produces correctly chained tweens. Probed
computed clip-paths now match GSAP math exactly: w3 inset right 25.4% at
t=0.96 (was 100%), w23 exit left inset 17.56% = inCubic(0.56) at t=6.69,
w24 overlap blend matches GSAP replace values. Applied to both twins.

Residual damaged checkpoints at t=5.58/6.13-6.21 are sub-200ms group-exit
transients right before the group visibility cut, not missing content.
2026-07-10 13:08:19 -04:00
Miguel Angel Simon Sierra 1a9190db27 fix(registry): match GSAP center-stagger slot semantics in world-map reveal
GSAP's stagger { each: 0.02, from: 'center' } gives every element a UNIQUE
20ms slot in center-out order (total span = each * (n-1) = 3.52s for 177
countries; measured live: 21/57/93/121/155 countries visible at
t=1.5/2.23/2.93/3.5/4.19s, complete at 4.7s). anime.stagger(20,
{ from: 'center' }) scales delay by DISTANCE from center instead, so
equidistant pairs share a slot and the reveal finished at t=2.93s -- the
whole map filled roughly twice too early, matching the damaged t=1.68-4.61s
band against the baseline.

Precompute the GSAP rank order (sort by |i - center|, ties lower-index
first) and pass explicit per-element delays. Live probe after the fix:
21/58/93/121/156/177 -- within one country of GSAP at every checkpoint.
Snapshot frames at t=2.23/2.93/4.19 now match the pinned baseline.
2026-07-10 12:57:40 -04:00
Miguel Angel Simon Sierra 5bcdb37e99 fix(registry): register vfx-iphone-device timeline after GLTF models load
The GSAP original assigned window.__timelines['devices-canvas'] inside
onReady() -- only after both DRACO/GLTF device models finished loading and the
screens were captured -- so the render pipeline's readiness poll waited for
the models before capturing frame 0. The anime.js port moved registration to
script-parse time, letting the pipeline start capturing while the models were
still loading: frame 0 rendered an empty pedestal, and early-window frames
drifted against the baseline.

Move hyperframesAnime.register() into onReady() (after captureScreens), which
also makes the registration-time priming pass paint from a fully-loaded scene,
and drop the duplicate parse-time registration.

Verified by snapshot at t=0/9.13/11.08 vs the pinned GSAP baseline: 9.13 and
11.08 now match exactly (device positions and captured screen content); t=0
shows the authored hero state while the baseline's own opening 0.6s is black
(GSAP-side model-load race at the pinned fork).
2026-07-10 12:45:52 -04:00
Miguel Angel Simon Sierra d87d722df0 fix(registry): paint vfx-portal frame 0 directly after deferred panel capture
Same class as the vfx-shatter fix: hyperframesAnime.register() primes the
timeline (seek to end, back to 0), so the deferred init's tl.seek(0) is a
no-op that never fires onUpdate, and the WebGL canvas stays black for the
first captured frame (t=0 hard-fail at 3.3dB, baseline shows the light
landing page). Call renderPortal(0) directly.

Verified by snapshot at t=0/3.3/3.9 vs the pinned GSAP baseline: t=0 now
shows the landing page. The remaining PSNR gap on this item is baseline-side:
the pinned GSAP baseline's drawElementImage capture is missing ALL text
(logo, nav, hero headline, card copy) for the entire clip, while the anime.js
candidate captures it correctly.
2026-07-10 12:40:38 -04:00
Miguel Angel Simon Sierra be14c9e653 fix(registry): paint vfx-shatter frame 0 directly after deferred panel capture
hyperframesAnime.register() primes the timeline (seek to end, then back to 0),
so by the time the deferred init has captured the HTML panels into WebGL
textures, tl.currentTime is already 0 and its tl.seek(0) is a no-op that never
fires onUpdate. Nothing repaints the canvas until the first nonzero seek,
leaving the very first rendered frame solid black (single damaged checkpoint
at t=0, 19.5dB, baseline shows the full hero). Call renderFrame(0) directly
instead of seeking.

Verified via snapshot at t=0/0.5/2.0 against the pinned GSAP baseline: frame 0
now shows the hero and matches.
2026-07-10 11:02:53 -04:00
Miguel Angel Simon Sierra 0684ff71f1 fix(cli): enable CanvasDrawElement in snapshot Chrome to match render pipeline
The engine's browserManager launches render Chrome with
--enable-features=CanvasDrawElement globally, but the snapshot command's own
puppeteer launch omitted it, so any composition using ctx.drawElementImage()
(vfx-shatter, vfx-portal, ios26-liquid-glass, ...) showed its 'API required'
placeholder in snapshots while rendering fine in the real pipeline.
2026-07-10 11:02:46 -04:00
Miguel Angel Simon Sierra c7e6e5820e fix(registry): re-assert morph-text t=0 word state after anime.js priming
hyperframesAnime.register() primes each timeline by seeking to its end and
back to 0. morph-text drives its word swap from an onUpdate proxy tween with
manual DOM writes, so the mid-word text painted by the priming seek has
nothing for anime.js to restore on the return seek and the wrong headline
stuck at t=0 (baseline shows 'Do more with less.', port showed a later word).

Re-assert applyMorph(0) after registration, and normalize the modulo in
applyMorph so a float-rounding hair-below-zero T from the return seek cannot
floor to the last word. Applied to both demo.html and the distributable
morph-text.html (same pattern in both twins).

Verified by frame comparison against the pinned GSAP baseline at t=0, 10.03,
10.5 and 12.0: t=0 now matches; the t=10-14.9s soft cluster is blur-morph
antialiasing jitter with identical content.
2026-07-10 08:06:43 -04:00
Miguel Angel Simon Sierra 4a3c01471e feat(registry): renderable demo for caption-blend-difference 2026-07-10 07:43:06 -04:00
Miguel Angel Simon Sierra 4fe33306dd fix(registry): locate repo blocks dir by marker in vscode theme generator 2026-07-10 07:43:05 -04:00
Miguel Angel Simon Sierra 014c435285 Merge branch 'fix-open-items-a' into worktree-feat-animejs-first-party 2026-07-10 02:49:54 -04:00
Miguel Angel Simon Sierra 0f75d83846 fix(registry): drop non-authored grid option from grid-pixelate-wipe stagger
The GSAP source used a plain 1D stagger (stagger: { amount, from }, no grid),
which on a row-major 16x9 element list produces a horizontal-band reveal
(middle rows first). The anime.js port added an explicit grid: [16, 9] option
that wasn't in the original, switching anime.js to true 2D geometric
distance and producing a radial/circular reveal instead, a visibly different
wipe shape confirmed against the pinned baseline at t=2.7s.

Removing the grid option restores the original array-index-distance stagger
and matches the baseline's band-shaped reveal.
2026-07-10 02:49:13 -04:00
Miguel Angel Simon Sierra ec275f2f1e fix(registry): stop liquid-glass-media-controls text from sticking at final value
onUpdate on a plain JS-object tween target only re-fires while the seek
position is inside that specific tween's own active window, unlike
tracked inline-style properties which the core adapter's priming/
restore logic re-derives for any seek. Without an explicit hold at
t=0, primeAnimeInstance's seek(duration) pass ran every tween once
(setting the search label to its final text and the slider to 82%),
and seek(0) never re-invoked those onUpdate callbacks since 0 sits
outside their windows, so both stayed stranded at the final value
across the whole opening portion of the clip.

Seed both the slider value and a new searchPhase value with a
duration:0 identity tween at t=0 (same onUpdate) so seeking back to
the opening frames re-fires the callback and reads back "Search"/34%.
Also converts the two tl.call() text swaps to explicit-from/to phase
tweens, since call() side effects don't participate in the seek
lifecycle at all.
2026-07-10 02:48:03 -04:00
Miguel Angel Simon Sierra 1b33ef289d fix(registry): restore missing initial hidden state on lt-soft-pill text
The GSAP source seeded #lt-name/#lt-role with an explicit initial set
(opacity 0, x -10) before building the timeline. The anime.js port
dropped that seed and used implicit-from {opacity: 1, translateX: 0}
tweens instead, which have no CSS rule or earlier keyframe to read a
hidden state from, so the tween was a no-op and both text lines were
visible from frame 0 instead of animating in at t=420/500ms.

Give the reveal tweens explicit from/to arrays so the pre-reveal state
is correctly established.
2026-07-10 02:47:50 -04:00
Miguel Angel Simon Sierra f91a095177 Merge branch 'feat-anime-transitions' into worktree-feat-animejs-first-party 2026-07-10 02:37:28 -04:00
Miguel Angel Simon Sierra c21c348c8e Merge branch 'fix-player-standalone' into worktree-feat-animejs-first-party 2026-07-10 02:36:55 -04:00
Miguel Angel Simon Sierra d325bac29e feat(registry): anime_template for all transitions + runtime-aware injector
Add an anime.js v4 anime_template (and anime_template_horizontal/vertical for
push-slide) alongside each gsap_template in the transition registry, vendored
identically into product-launch-video, pr-to-video, and faceless-explainer.
transitions.mjs now detects the target composition's runtime and stamps GSAP
onto window.__timelines["main"] or anime onto
hyperframesAnime.get("main").instance accordingly, defaulting to anime per the
anime-first contract. Anime templates use explicit [from, to] arrays,
decomposed transform keys, ms-based tokens, and percentage transformOrigin
pairs (a real Chrome anime.js 4.5.0 bug: keyword syntax silently resolves both
endpoints to (0,0)).
2026-07-10 02:36:11 -04:00
Miguel Angel Simon Sierra 404c4f66f4 fix(player): pre-parse runtime injection for standalone anime compositions
<hyperframes-player> couldn't play a raw anime.js composition from src: the
inline hyperframesAnime.register() call throws before the runtime exists,
and the existing late-injection fallback only fires for GSAP's __timelines
and appends the runtime after parse, which is too late for a call that
already ran.

Add a runtime-src attribute to override the runtime URL, and a pre-parse
path in the probe: once it observes a same-origin composition that
references hyperframesAnime but never got a runtime/timeline/registry,
fetch the original src, inject the runtime script + a <base> tag ahead of
the composition's own scripts, and reload via srcdoc (once per src).
shouldInjectRuntime now also refuses to late-inject once an anime registry
is present, since that path can never help these compositions.
2026-07-10 02:35:43 -04:00
Miguel Angel Simon Sierra 2dbfe71d5f Merge branch 'feat-remotion-goldens' into worktree-feat-animejs-first-party 2026-07-10 02:31:00 -04:00
Miguel Angel Simon Sierra 3f8fe4e26c fix(skills): port remotion-to-hyperframes test corpus goldens to anime.js
The T1-T3 hf-src goldens and sequencing.md still authored GSAP timelines
while the skill's api-map/timing/transitions docs and the porter itself
already default to anime.js. Convert each golden's paused GSAP timeline to
anime.createTimeline({ autoplay: false }) + hyperframesAnime.register,
translating positions/durations to milliseconds and easing names via the
documented GSAP->anime.js table, while preserving the original tween
structure (implicit vs explicit from-values) exactly. Re-measured SSIM
against the Remotion baselines and refreshed expected.json's calibration
numbers to match.
2026-07-10 02:29:42 -04:00
Miguel Angel Simon Sierra ad2a632e7f fix(registry): drive per-word glow/glitch text-shadow via numeric custom properties
anime.js v4.5.0 cannot interpolate a text-shadow tween whose from/to values
have a mismatched layer shape (a 1-layer base shadow vs. a 3-layer glitch
shadow in caption-glitch-rgb, or "none" vs. a 3-layer glow in
caption-neon-glow): it silently freezes at the last-applied value (and can
scramble color channels) instead of animating, so glitch-rgb's per-word RGB
split never resets and neon-glow's glow never appears at all.

Confirmed live via getComputedStyle probes seeking the registered timeline at
10ms increments, and by frame comparison against the pinned GSAP baseline.

Fix both by tweening only plain numbers (--glitch-off/--glitch-alpha,
--glow-r/-g/-b/-alpha) and letting CSS reconstruct the shadow, sidestepping
anime's compound-value interpolation entirely.
2026-07-10 02:29:38 -04:00
Miguel Angel Simon Sierra 268a530443 fix(core): only correct the earliest implicit transform tween per target/property (U-final)
The prior implicit-transform-from fix corrected EVERY implicit-from tween
matching a decomposed transform property, not just the first one on a given
target. Confirmed via a real render + PSNR A/B test against the commit
before that fix: registry/examples/product-promo's nested
scene1-logo-intro.html animates each Figma logo piece with two tweens on
the same target+property (an instant duration:0 jump off-screen, then an
implicit-from "converge to center" tween) -- the second tween correctly
inherits its "from" from the first tween's just-set value inside anime.js,
but the prior fix overwrote it with the element's true CSS/page-load
identity value instead, making the piece appear already-assembled at the
center from frame 0. This regressed product-promo's PSNR from ~50.5dB to
~47.0dB.

Only apply the CSS-cascade correction to the tween with the smallest
`_absoluteStartTime` for each distinct (target, property) pair; every later
implicit-from tween on that same pair is left untouched, since anime.js
already chains it correctly from the preceding tween. Verified: the
product-promo regression is resolved (51.2dB, back above baseline) while
flowchart/kinetic-type retain their original fix's improvement.
2026-07-09 20:59:16 -04:00
Miguel Angel Simon Sierra 7818e6a9c0 fix(core): rewrite anime.js clip-path "none" resets after a circle() shape (U-final)
anime.js v4.5.0 cannot correctly resolve a literal "none" clip-path target
when an earlier tween on the same element used a structured circle()
shape. Confirmed via internal tween inspection: it silently re-templates
"none" as a zeroed copy of the preceding circle()'s numeric parameters
(`_toNumbers` become `[0, 0, 0]`, reusing the prior string template),
rendering as `circle(0% at 0% 0%)` -- a near-fully-clipped, effectively
black/empty box -- instead of the intended fully-revealed state. This is
baked in at `.add()`-call time, before any seek ever runs, so it cannot be
fixed by mutating tween fields afterward.

Patch every timeline's `.add()` to rewrite a literal `clipPath: "none"`
into an equivalent fully-open `circle(150% at X% Y%)` (same shape function
anime already interpolates correctly, radius large enough to cover any
aspect ratio) whenever a tracked preceding value for that element was a
circle() shape. Leaves "none" untouched when there is no preceding
structured shape to conflict with (anime resolves that case correctly on
its own), and leaves every other property/shape untouched.

Verified against registry/blocks/transitions-light and
registry/blocks/transitions-radial (the confirmed "Family B" black/hidden
content defect from the U-final adjudication) with real render+compare-item
PSNR improvement; no regression on the other Family B members
(vfx-portal/vfx-shatter/play-mode), which do not use this clip-path pattern
and remain open with a different, not-yet-identified root cause.
2026-07-09 20:35:37 -04:00
Miguel Angel Simon Sierra 20e25341e9 fix(core): correct anime.js implicit transform from-values against CSS cascade (U-final)
anime.js v4.5.0 does not read an element's CSS-cascaded `transform` value
when resolving an implicit "from" for decomposed transform sub-properties
(translateX/Y, scale, scaleX/Y, rotate) authored without an explicit
`[from, to]` array. It silently defaults to identity instead, so any
element relying on a stylesheet rule like
`.node { transform: translate(-50%, -50%) scale(0); }` to start hidden
renders at (or near) its final position/scale from the very first frame.
Confirmed via isolated puppeteer reproduction: this is baked into anime's
internal tween node (`_fromNumber`) at `.add()` time, independent of seek
order or priming.

Correct each affected tween's `_fromNumber`/`_number` with the true
CSS-cascaded value (decomposed via DOMMatrixReadOnly) before the instance's
first-ever seek, in the existing per-instance priming pass. Verified
against registry/blocks/flowchart and registry/examples/kinetic-type
(same "content resolves ahead of schedule" defect family from the U-final
adjudication) with real render+compare-item PSNR improvement.
2026-07-09 20:27:14 -04:00
Miguel Angel Simon Sierra 3d87d63bc2 fix(core): recognize scoped hyperframesAnime self-registrations in sub-composition readiness poll 2026-07-09 18:11:12 -04:00
Miguel Angel Simon Sierra 66b4e0cc9b fix(core): recognize hyperframesAnime registrations in sub-composition readiness poll 2026-07-09 17:25:27 -04:00
Miguel Angel Simon Sierra ff57ded8ac fix(eval): recognize hyperframesAnime.register as a standalone-composition signal (U10z) 2026-07-09 17:13:29 -04:00
Miguel Angel Simon Sierra 792bcff2a8 fix(core): restore priming-stranded style properties by keyframe timing not a fixed allowlist (U10z) 2026-07-09 16:33:49 -04:00
Miguel Angel Simon Sierra 09b0849c95 fix(registry): partially fix north-korea-locked-down label centering (U10z) 2026-07-09 15:49:07 -04:00
Miguel Angel Simon Sierra 3434cc80cc fix(registry): confirm yt-lower-third centering wrapper fix (U10z) 2026-07-09 15:48:30 -04:00
Miguel Angel Simon Sierra cdfab41128 fix(registry): fix transitions-mechanical outro fade timing (U10z) 2026-07-09 15:47:53 -04:00
Miguel Angel Simon Sierra 522009180e fix(registry): apply GSAP immediateRender semantics to vpn-youtube-spot addFrom (U10z) 2026-07-09 15:47:11 -04:00
Miguel Angel Simon Sierra 8c9e17ec52 fix(core): seek nested anime.js compositions with local, offset time (U10z)
The anime.js adapter registers every composition and sub-composition as a
flat entry in window.__hfAnime and seeked ALL of them with the same raw
global time. Unlike GSAP (where sub-composition timelines are nested inside
a parent timeline and inherit correct local time from that nesting), each
anime.js registration needs its own composition's cumulative start time
subtracted before seeking, or a sub-composition mounted at a nonzero
data-start renders far ahead of where it should be (confirmed: at global
t=1.6s with data-start=1.5s, the child received seek(1600ms) instead of the
correct seek(100ms)).

Resolve each registration's host via data-composition-id, subtract its
cumulative start (reusing the existing runtime start-time resolver), and
clamp to the authored/host duration before seeking.

Verified: registry/examples/product-promo average PSNR vs GSAP baseline
20.5dB -> wait, 33.3dB -> 50.5dB (damaged checkpoints 77 -> 32) with no
regressions in the other items spot-checked. Full regression suite passes
(82 files, 1168 tests) plus a new red/green test for the nested-seek case.
2026-07-09 14:39:46 -04:00
Miguel Angel Simon Sierra 2ce3d56fc4 fix(registry): reproduce GSAP transform-axis-loss centering bug in x-post (U10z)
x-post.x-card-frame statically centered both axes (translate(-50%,-50%)),
but the GSAP baseline's gsap.to(card,{y:0}) only preserves the axis it
never animates (x); the animated y axis loses the CSS percentage
centering entirely, pinning the card's top edge at raw top:50% instead
of true vertical center. Drop the Y half of the wrapper's static
transform (translateX(-50%) only) so the anime.js port lands at the
same asymmetric resting position as the pinned GSAP baseline.

Verified: avg PSNR vs baseline 20.5dB -> 53.2dB, hard-fail checkpoints
(<30dB) 87 -> 0; residual low-band checkpoints sit at ~44dB (just under
the 45dB soft threshold), consistent with font/antialiasing render
noise rather than a positional defect.
2026-07-09 13:44:04 -04:00
Miguel Angel Simon Sierra abd1b1edf4 revert(registry): remove ios26 seek reset (U10y)
This reverts commit b078f8c09.
2026-07-09 13:08:05 -04:00
Miguel Angel Simon Sierra edb6d85b4f revert(registry): remove x-post anchor nudge (U10y)
This reverts commit 3e31e84e8.
2026-07-09 13:07:16 -04:00
Miguel Angel Simon Sierra 1cd8e6fb8e fix(registry): reset ios26-liquid-glass opening frame (U10y) 2026-07-09 12:59:37 -04:00
Miguel Angel Simon Sierra c3b9561581 fix(registry): restore x-post centering (U10y) 2026-07-09 12:58:52 -04:00
Miguel Angel Simon Sierra c6ace46482 fix(registry): keep 3d transition scene visible under outro 2026-07-09 12:37:51 -04:00
Miguel Angel Simon Sierra b83d07ec38 fix(core): preserve primed anime numeric styles 2026-07-09 12:37:01 -04:00