# Landing motion 3D

## Objective
Replace the four static illustrations of the main landing (`hero-hernan`, `scroll-2`, `scroll-3`, `scroll-4`) with live 3D scenes that have professional motion.

## Problem and why
The illustrations are flat SVG files. `scroll-3.svg` weighs 5.6 MB and `scroll-4.svg` 3.6 MB because they embed photos, and every word inside them is a vector path, so search engines and screen readers cannot read it.

## Concept
"Encendé tu negocio": each scene starts off and flat. The Taxes power mark turns it on, the pieces rise to their 3D layers, a pulse travels along the dashed connectors, and the data starts working.

## Decisions
- CSS 3D with real DOM panels, no Three.js: no new dependency, crisp and indexable text, works with Vue 2.7 and Laravel Mix.
- CSS lives in `public/landingempresas/css/landing-scenes.css`, because the landing does not load `new_css_2025.css`.
- Delivery strategy `exception-ok`: no branch and no commits, by the user's standing instruction for this repository. Changes stay uncommitted on `master`.
- The project bundle is not compiled, by project rule. Verification uses a throwaway build that writes only to the session scratchpad.
- The logo exists only as a raster, so its vector geometry was measured from `scroll-4.svg` and checked with a difference overlay against the raster.
- The map is the original vector art (119 paths, same territory, including the islands). Only its land fill changes, from white to `#f3f6ff`, so it reads on the white page.
- `scene-section` was added to two `<section>` tags in `Index.vue`, beyond the `<img>` swap: the rows relied on the intrinsic width of the SVG files and would otherwise collapse.
- A narrow scene (under 560 px) uses `.is-compact` based on the width of the scene, not the viewport, because the hero and billing columns are half width at 768 px.
- The two smallest island silhouettes were removed from `mapa-argentina-base.svg`, which only supplies thickness. The top map keeps them.
- User request during the work: the six section eyebrows (number and label) and the hero badge dot are removed from the main landing. `section-eyebrow` stays in `index.css` because `Partners.vue` and the course pages still use it; the dot CSS is removed because nothing else uses it.

## Scope
- In: `Index.vue` of the main landing, new scene components, new CSS, optimized photos, one conditional preload in `head.blade.php`.
- Out: proveedores landing, solution and price pages, the original SVG files (kept on disk, solution pages still use some of them), business logic, `taxes-register`.

## Tasks
Route for all tasks: delegated direct, one writer. Trigger: 2+ non-trivial files.

- [x] T1 Extract the assets from the SVG files and export optimized WebP photos.
- [x] T2 Shared motion mixin and 3D power mark.
- [x] T3 Hero scene.
- [x] T4 Pillars scene (replaces `scroll-2`).
- [x] T5 "Local y en el Mundo" scene (replaces `scroll-3`).
- [x] T6 Facturacion and Mercado Libre scene (replaces `scroll-4`).
- [x] T7 Wire the scenes into `Index.vue` and link the CSS.
- [x] T8 Visual verification on a scratchpad preview.
- [x] T9 Remove the section eyebrows and the hero badge dot. Route: direct inline, mechanical edit. Observed at 1440 and 390 px: 0 eyebrows, 0 dots, badge text intact, no overflow, no console errors.

## Acceptance criteria
- All copy from the original art is present as real text, including "Local y en el Mundo".
- The map keeps the same territory as the original art, including the islands.
- Animation uses only `transform` and `opacity`, and pauses while a scene is off screen. Exception: `stroke-dashoffset` for the one-shot draw of the ring and the connectors.
- `prefers-reduced-motion` shows the final "on" state with no loops and no tilt.
- A scene ends "on" even if IntersectionObserver never fires.
- No horizontal overflow at 1440, 1024, 768 and 390 px wide.
- No console errors.

## Checks
No runnable deterministic test applies to this visual work, so there is no RED step. Checks are browser checks on the preview build (Chromium through Playwright).

## Verification evidence
- Frames: 1440, 1024, 768, 390 px, each scene off, mid turn-on, settled. Contact sheets `.playwright-mcp/sheet-*.png`.
- Motion: rig and orbit `matrix3d` differ between two samples 1.5 s apart.
- Billing loop: order appears at 3061 ms, flies at 3721 ms, becomes invoice at 5881 ms, bar and total update at 7743 ms, next order at 9721 ms. Two full cycles observed; April total went 0 -> 77,625 -> 177,525.
- Off screen: 0 rAF calls in 3 s, no running animations in any scene (12 paused, 4 finished), no tickers, state unchanged, loop resumes on return.
- Overflow: `scrollWidth` equals `clientWidth` at all four widths (1430, 1014, 758, 380).
- Reduced motion: 0 rAF calls, 0 animations, no timers, all marks lit, all panels on, final data shown.
- Failsafe: with a stubbed IntersectionObserver, all four scenes are on after 3 s.
- Console: no errors, warnings, Vue warnings or failed requests at any width.
- Weight of the four graphics: 10,157,264 bytes before; 315,405 bytes of new images plus 39,274 bytes of CSS after.
- Logo fidelity: difference overlay against the raster is black except for hairline edges.

## Not checked
- The compiled project bundle: it was not compiled. The real page was checked in Chromium through local Laravel and a scratch proxy that serves a throwaway development build of `app_landing_empresas.js`: 4 scenes on, real form, no console errors, no failed requests, no broken images, no overflow at 1440 px.
- Safari and Firefox: only Chromium was exercised.
- Frame rate on low-end devices.

## Progress
All tasks implemented and verified on the preview. Nothing committed. Native review: offered at medium risk and declined by the user for this candidate, so no independent review ran. Assessed tier with the untracked files declared: medium; writer self-verification plus a parent spot check applies. WebKit was attempted but the installed build matches no local Playwright library, and no browser was downloaded, so Safari stays unchecked.

## Next step
The user compiles the bundle when they decide to (`public/js/app_landing_empresas.js` must be rebuilt for the scenes to appear) and checks the real page.
