Files
brahman/crates/apps/gioser-web/index.html
T
sergio 5e0fcae4b4 feat(gioser): shake on click, mouseleave rebound, element particles, taskbar
Renderer (gioser-canvas-web):
- Spring shake (SpringDamper1, 7.5 Hz / ζ=0.13) aplicado como rotación Z
  en el MVP. impulse_click() inyecta velocidad alternada → vibración fuerte
  con ~5 ciclos decayendo en ~0.8s.
- release_tilt() pone target del tilt en (0,0) → la chacana cae al frente
  con el rebote natural del spring sub-crítico.
- world_scale_for_aspect(): en portrait (aspect<1) escala baja proporcional
  para que el aro exterior no se corte por los lados. Base 1.05, piso 0.45.
- click_radius_css_px() expone radio del aro en CSS-pixels desde el centro
  del canvas; la app lo usa para hit-test del impulso.
- set_client_size() separa CSS-pixels de device-pixels (DPR).
- tilt_degrees() ahora retorna (pitch, yaw, roll) — el brand replica los 3.
- 4 nuevos uniforms u_aire/fuego/tierra/agua_color para el shader de
  partículas.

Shader (gioser-shaders/FS_CHACANA):
- Función element_particles(tip, outward, color, kind) → 4 partículas por
  cardinal con personalidad: AIRE drift+sway, FUEGO rise+flicker (siempre
  hacia +Y), TIERRA cae, AGUA ondula descendiendo. Gauss + envelope
  sinusoidal en la vida. ~16 partículas total, costo modesto.

App (gioser-web):
- pointerdown en canvas → si distancia al centro < click_radius_css_px →
  impulse_click(). Touch y mouse vienen unificados por PointerEvent.
- mouseleave en canvas → release_tilt(). Sin set_target, el spring se
  quedaría en la última posición — ahora vuelve al frente con rebote.
- position_tips ahora clampea raw_x/raw_y a [margin, viewport - taskbar -
  margin] en CSS pixels. Los botones NUNCA salen del canvas ni cubren la
  taskbar incluso en aspect extremos o tilt máximo.
- AppState + TaskbarState (RefCell): trackea drawers abiertos + activo.
  open_tab/switch_tab/close_tab/home aplican mutación + sync().
- sync() rebuild de taskbar-list innerHTML por cada cambio de estado,
  más swap de body classes + drawer .open classes.
- Click delegation en taskbar-list — un listener para todas las cajitas.
- Botón home con data-home en la barra (svg de casa) cierra todo y
  limpia el taskbar.
- Escape también cierra el drawer activo.
- update_tilt_css ahora setea --tilt-z también — brand title roll
  visible en el shake.

CSS:
- .drawer bottom: 52px (reserva taskbar).
- .taskbar full ancho fixed bottom, glass + gold border, scrollable horiz
  para muchas cajitas.
- .taskbar-item con --task-color por elemento (aire/fuego/tierra/agua),
  .active glow del color + inset border bottom.
- .taskbar-home con svg de casa dorado, hover glow.
- Responsive: taskbar 46px en mobile + ajustes.
- .brand transform agrega rotateZ(--tilt-z) para que el título vibre con
  la chacana en click impulses.

Workspace verde + 18 tests.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 01:46:05 +00:00

133 lines
6.7 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="es">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>GioSer · En el centro, el ser</title>
<link rel="stylesheet" href="./styles.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Cinzel:wght@500;700&family=Inter:wght@300;500;600&family=JetBrains+Mono:wght@400;600&display=swap">
</head>
<body>
<canvas id="gioser-canvas" aria-hidden="true"></canvas>
<header id="brand" class="brand">
<h1 class="brand-title">Gio<span class="brand-dot">·</span>Ser</h1>
</header>
<main id="tips" aria-label="Cuatro elementos">
<a id="tip-aire" class="tip tip-aire" href="#aire" data-md="./md/aire.md" aria-label="Aire — Software e IA">
<svg viewBox="0 0 48 48" class="tip-glyph" aria-hidden="true">
<path d="M6 18 q 9 -12 18 0 t 18 0" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
<path d="M6 28 q 9 -12 18 0 t 18 0" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" opacity="0.75"/>
<path d="M6 38 q 9 -12 18 0 t 18 0" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" opacity="0.45"/>
</svg>
<span class="tip-label">AIRE</span>
<span class="tip-sub">Software · IA</span>
</a>
<a id="tip-fuego" class="tip tip-fuego" href="#fuego" data-md="./md/fuego.md" aria-label="Fuego — Inspiración">
<svg viewBox="0 0 48 48" class="tip-glyph" aria-hidden="true">
<path d="M24 4 q -12 12 -6 24 q 3 -6 6 -6 q 1 10 6 12 q 10 -10 0 -22 q -4 6 -6 -8 z"
fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/>
<circle cx="24" cy="28" r="3" fill="currentColor" opacity="0.5"/>
</svg>
<span class="tip-label">FUEGO</span>
<span class="tip-sub">Inspiración</span>
</a>
<a id="tip-tierra" class="tip tip-tierra" href="#tierra" data-md="./md/tierra.md" aria-label="Tierra — Cuerpo">
<svg viewBox="0 0 48 48" class="tip-glyph" aria-hidden="true">
<path d="M4 36 l 12 -16 l 8 9 l 6 -12 l 14 19 z"
fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/>
<path d="M24 36 v 8 M19 38 l -4 5 M29 38 l 4 5 M24 44 v 2"
fill="none" stroke="currentColor" stroke-width="1.3" opacity="0.7"/>
</svg>
<span class="tip-label">TIERRA</span>
<span class="tip-sub">Cuerpo</span>
</a>
<a id="tip-agua" class="tip tip-agua" href="#agua" data-md="./md/agua.md" aria-label="Agua — Espiritualidad aplicada">
<svg viewBox="0 0 48 48" class="tip-glyph" aria-hidden="true">
<path d="M6 22 q 6 -10 12 0 t 12 0 t 12 0" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
<path d="M6 30 q 6 -10 12 0 t 12 0 t 12 0" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" opacity="0.75"/>
<path d="M6 38 q 6 -10 12 0 t 12 0 t 12 0" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" opacity="0.5"/>
</svg>
<span class="tip-label">AGUA</span>
<span class="tip-sub">Espiritualidad</span>
</a>
</main>
<!-- DRAWERS: uno por elemento. Cada uno crece desde la posición del tip
clickeado (origin set via CSS vars desde WASM) hasta fullscreen. -->
<aside id="drawer-aire" class="drawer drawer-aire" data-element="aire" aria-hidden="true">
<button class="drawer-close" data-close-drawer aria-label="Cerrar Aire">×</button>
<div class="drawer-ambience" aria-hidden="true"></div>
<header class="drawer-head">
<span class="drawer-mark">aire</span>
<h2 class="drawer-title">Aire</h2>
<span class="drawer-tag">Software · IA · Aspiración</span>
</header>
<section class="drawer-content" id="drawer-aire-content"></section>
</aside>
<aside id="drawer-fuego" class="drawer drawer-fuego" data-element="fuego" aria-hidden="true">
<button class="drawer-close" data-close-drawer aria-label="Cerrar Fuego">×</button>
<div class="drawer-ambience" aria-hidden="true"></div>
<header class="drawer-head">
<span class="drawer-mark">fuego</span>
<h2 class="drawer-title">Fuego</h2>
<span class="drawer-tag">Inspiración</span>
</header>
<section class="drawer-content" id="drawer-fuego-content"></section>
</aside>
<aside id="drawer-tierra" class="drawer drawer-tierra" data-element="tierra" aria-hidden="true">
<button class="drawer-close" data-close-drawer aria-label="Cerrar Tierra">×</button>
<div class="drawer-ambience" aria-hidden="true"></div>
<header class="drawer-head">
<span class="drawer-mark">tierra</span>
<h2 class="drawer-title">Tierra</h2>
<span class="drawer-tag">Cuerpo</span>
</header>
<section class="drawer-content" id="drawer-tierra-content"></section>
</aside>
<aside id="drawer-agua" class="drawer drawer-agua" data-element="agua" aria-hidden="true">
<button class="drawer-close" data-close-drawer aria-label="Cerrar Agua">×</button>
<div class="drawer-ambience" aria-hidden="true"></div>
<header class="drawer-head">
<span class="drawer-mark">agua</span>
<h2 class="drawer-title">Agua</h2>
<span class="drawer-tag">Espiritualidad aplicada</span>
</header>
<section class="drawer-content" id="drawer-agua-content"></section>
</aside>
<!-- TASKBAR estilo Windows: home a la izquierda + cajitas dinámicas
de las vistas MD abiertas. Sincronizada por WASM. -->
<nav class="taskbar" aria-label="Vistas abiertas">
<button class="taskbar-home" data-home aria-label="Volver al home" type="button">
<svg viewBox="0 0 24 24" class="taskbar-home-glyph" aria-hidden="true">
<path d="M3 12 L12 3 L21 12" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M5 11 V20 H10 V14 H14 V20 H19 V11" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linejoin="round"/>
<circle cx="12" cy="17" r="0.8" fill="currentColor"/>
</svg>
</button>
<span class="taskbar-divider" aria-hidden="true"></span>
<ul class="taskbar-list" id="taskbar-list" role="presentation"></ul>
</nav>
<script type="module">
import init from "./pkg/gioser_web.js";
init().catch(err => {
console.error(err);
document.body.insertAdjacentHTML("beforeend",
'<pre style="color:#f59056;position:fixed;left:1rem;bottom:1rem;max-width:90vw;white-space:pre-wrap;font-family:monospace;z-index:9999">' +
String(err) + '</pre>');
});
</script>
</body>
</html>