// APP ROOT — router interno + tweaks panel
const { useState, useEffect } = React;
const App = () => {
const [route, setRoute] = useState('home'); // 'home' | 'catalogo' | 'detalle'
const [vehicleId, setVehicleId] = useState(null);
const [searchPreset, setSearchPreset] = useState(null);
// Tweaks
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
"accent": "#ea5a0c",
"displayFont": "Cairo",
"density": 3,
"dark": true
}/*EDITMODE-END*/;
const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
// Apply tweaks → CSS vars
useEffect(() => {
document.documentElement.style.setProperty('--accent', t.accent);
// brighten
document.documentElement.style.setProperty('--accent-bright', shiftLight(t.accent, 0.08));
document.body.dataset.density = t.density;
document.documentElement.style.setProperty('--serif', `"${t.displayFont}", "Helvetica Neue", Helvetica, Arial, sans-serif`);
if (!t.dark) {
document.documentElement.style.setProperty('--bg', '#f6f2ea');
document.documentElement.style.setProperty('--bg-elev', '#efe9dd');
document.documentElement.style.setProperty('--bg-elev-2', '#e6decb');
document.documentElement.style.setProperty('--ink', '#15110a');
document.documentElement.style.setProperty('--ink-dim', '#5d564a');
document.documentElement.style.setProperty('--ink-mute', '#857b6a');
document.documentElement.style.setProperty('--line', '#d4ccba');
document.documentElement.style.setProperty('--line-soft', '#e2dac6');
} else {
document.documentElement.style.setProperty('--bg', '#0a0a0a');
document.documentElement.style.setProperty('--bg-elev', '#131311');
document.documentElement.style.setProperty('--bg-elev-2', '#1c1b18');
document.documentElement.style.setProperty('--ink', '#f3ede2');
document.documentElement.style.setProperty('--ink-dim', '#a8a094');
document.documentElement.style.setProperty('--ink-mute', '#6b6358');
document.documentElement.style.setProperty('--line', '#2a2823');
document.documentElement.style.setProperty('--line-soft', '#1f1d1a');
}
}, [t]);
const nav = (newRoute, anchor, preset) => {
setRoute(newRoute);
if (preset) setSearchPreset(preset);
try { window.history.pushState({ route:newRoute, anchor:anchor||null, preset:preset||null }, '', '#'+newRoute); } catch(e) {}
setTimeout(() => {
if (anchor) {
const el = document.getElementById(anchor);
if (el) {
const rect = el.getBoundingClientRect();
window.scrollTo({top: window.scrollY + rect.top - 80, behavior:'smooth'});
}
} else {
window.scrollTo({top:0, behavior:'instant'});
}
}, 50);
};
const selectVehicle = (id) => {
setVehicleId(id);
setRoute('detalle');
try { window.history.pushState({ route:'detalle', vehicleId:id }, '', '#detalle'); } catch(e) {}
setTimeout(() => window.scrollTo({top:0, behavior:'instant'}), 30);
};
// Botón ATRÁS/ADELANTE del navegador -> navegación interna (no sale del sitio)
useEffect(() => {
if (!window.history.state) {
try { window.history.replaceState({ route:'home' }, '', window.location.pathname); } catch(e) {}
}
const onPop = (e) => {
const st = e.state || { route:'home' };
setRoute(st.route || 'home');
setVehicleId(st.vehicleId || null);
if (st.preset) setSearchPreset(st.preset);
setTimeout(() => window.scrollTo({ top:0, behavior:'instant' }), 20);
};
window.addEventListener('popstate', onPop);
return () => window.removeEventListener('popstate', onPop);
}, []);
return (
{route === 'home' && }
{route === 'catalogo' && }
{route === 'detalle' && nav('catalogo')} onNav={nav} onSelectVehicle={selectVehicle}/>}
setTweak('accent', v)}/>
setTweak('dark', v)}/>
setTweak('displayFont', v)}/>
setTweak('density', v)}/>
);
};
// Util: lighten a hex by amount (0..1)
function shiftLight(hex, amt) {
const m = hex.replace('#','').match(/.{2}/g);
if (!m) return hex;
const [r,g,b] = m.map(x => parseInt(x,16));
const nr = Math.min(255, Math.round(r + (255-r)*amt));
const ng = Math.min(255, Math.round(g + (255-g)*amt));
const nb = Math.min(255, Math.round(b + (255-b)*amt));
return '#' + [nr,ng,nb].map(x=>x.toString(16).padStart(2,'0')).join('');
}
const root = ReactDOM.createRoot(document.getElementById('root'));
// Esperar a que el storage layer hidrate los vehículos antes de montar la app
(window.__OMEGA_READY || Promise.resolve()).then(() => {
root.render();
});