<div class="hero-container" id="hero-container">
<div class="sidebar-text">
Music for the daydreamers, the storytellers, and the wanderers — a soundtrack for those who find beauty in every moment, and meaning in every silence.
</div>
<div class="bg-text-container">
<h1 class="bg-text font-display">
these are my stories
</h1>
</div>
<div class="center-profile" id="center-profile">
<div class="profile-avatar">
<img alt="Coveo Portrait" src="https://storage.maquinaespacial.com/media/5ODEGNTRDBVF/avatar.avif"/>
</div>
<h2 class="profile-title">
Coveo
</h2>
<p class="profile-subtitle">
An Audio/Visual Project
</p>
</div>
<div class="gallery-ring" id="gallery-ring">
<div class="gallery-items" id="gallery-items">
<!-- Items injected here by JS, keeping original for preview -->
<div class="gallery-item" data-color="#ff7b54" data-index="0" data-time="00:08 / 03:45" data-title="SUNSET DREAMS">
<img alt="Cover 1" src="https://storage.maquinaespacial.com/media/5ODEGNTRDBVF/13.avif"/>
</div>
<div class="gallery-item" data-color="#54a0ff" data-index="1" data-time="01:12 / 04:20" data-title="NIGHT CITY">
<img alt="Cover 2" src="https://storage.maquinaespacial.com/media/5ODEGNTRDBVF/12.avif"/>
</div>
<div class="gallery-item" data-color="#44bd32" data-index="2" data-time="00:45 / 02:30" data-title="FOREST WHISPERS">
<img alt="Cover 3" src="https://storage.maquinaespacial.com/media/5ODEGNTRDBVF/11.avif"/>
</div>
<div class="gallery-item" data-color="#e84118" data-index="3" data-time="02:15 / 05:00" data-title="RED ROSES">
<img alt="Cover 4" src="https://storage.maquinaespacial.com/media/5ODEGNTRDBVF/10.avif"/>
</div>
<div class="gallery-item" data-color="#d1ccc0" data-index="4" data-time="00:03 / 00:15" data-title="TOUCHING HANDS">
<img alt="Cover 5" src="https://storage.maquinaespacial.com/media/5ODEGNTRDBVF/9.avif"/>
</div>
<div class="gallery-item" data-color="#f5f6fa" data-index="5" data-time="01:50 / 03:10" data-title="WHITE CLOUDS">
<img alt="Cover 6" src="https://storage.maquinaespacial.com/media/5ODEGNTRDBVF/8.avif"/>
</div>
<div class="gallery-item" data-color="#2f3640" data-index="6" data-time="03:00 / 04:45" data-title="DARK NIGHT">
<img alt="Cover 7" src="https://storage.maquinaespacial.com/media/5ODEGNTRDBVF/7.avif"/>
</div>
<div class="gallery-item" data-color="#111111" data-index="7" data-time="00:30 / 03:00" data-title="MIDNIGHT RIDE">
<img alt="Cover 8" src="https://storage.maquinaespacial.com/media/5ODEGNTRDBVF/6.avif"/>
</div>
<div class="gallery-item" data-color="#2c3e50" data-index="8" data-time="01:20 / 04:00" data-title="OCEAN BREEZE">
<img alt="Cover 9" src="https://storage.maquinaespacial.com/media/5ODEGNTRDBVF/5.avif"/>
</div>
<div class="gallery-item" data-color="#c56cf0" data-index="9" data-time="02:10 / 03:40" data-title="NEON LIGHTS">
<img alt="Cover 10" src="https://storage.maquinaespacial.com/media/5ODEGNTRDBVF/4.avif"/>
</div>
<div class="gallery-item" data-color="#3ae374" data-index="10" data-time="01:15 / 04:15" data-title="URBAN JUNGLE">
<img alt="Cover 11" src="https://storage.maquinaespacial.com/media/5ODEGNTRDBVF/3.avif"/>
</div>
<div class="gallery-item" data-color="#ffb8b8" data-index="11" data-time="00:50 / 02:50" data-title="PINK SKY">
<img alt="Cover 12" src="https://storage.maquinaespacial.com/media/5ODEGNTRDBVF/1.avif"/>
</div>
</div>
</div>
<div class="fog-overlay">
</div>
<div class="bottom-instructions" id="bottom-instructions">
<p class="instructions-subtitle">
The art of sonic and visual
</p>
<h3 class="instructions-title font-display">
Storytelling
</h3>
<p class="instructions-hint">
Tap artwork to preview a song
</p>
</div>
<div class="audio-player" id="audio-player">
<div class="player-mobile-controls">
<button class="btn-icon btn-play">
<svg fill="currentColor" viewbox="0 0 24 24">
<path d="M6 4h4v16H6zm8 0h4v16h-4z">
</path>
</svg>
</button>
<button class="btn-icon btn-close" id="close-player">
<svg fill="none" stroke="currentColor" stroke-width="2" viewbox="0 0 24 24">
<path d="M6 18L18 6M6 6l12 12" stroke-linecap="round" stroke-linejoin="round">
</path>
</svg>
</button>
</div>
<div class="player-inner">
<div class="player-info">
<p class="info-label">
Previewing
</p>
<h4 class="info-title" id="player-title">
Still Dreaming
</h4>
</div>
<div class="vinyl-container" id="vinyl-container">
<svg class="vinyl-svg" id="vinyl-svg" viewbox="0 0 200 200">
<defs>
<clippath id="center-hole">
<circle cx="100" cy="100" r="40">
</circle>
</clippath>
</defs>
<circle cx="100" cy="100" fill="#d1ccc0" id="vinyl-bg" r="98">
</circle>
<circle cx="100" cy="100" fill="none" r="90" stroke="rgba(255,255,255,0.2)" stroke-width="1.2">
</circle>
<circle cx="100" cy="100" fill="none" r="85" stroke="rgba(255,255,255,0.2)" stroke-width="1.2">
</circle>
<circle cx="100" cy="100" fill="none" r="80" stroke="rgba(255,255,255,0.2)" stroke-width="1.2">
</circle>
<circle cx="100" cy="100" fill="none" r="75" stroke="rgba(255,255,255,0.2)" stroke-width="1.2">
</circle>
<circle cx="100" cy="100" fill="none" r="70" stroke="rgba(255,255,255,0.2)" stroke-width="1.2">
</circle>
<circle cx="100" cy="100" fill="none" r="65" stroke="rgba(255,255,255,0.2)" stroke-width="1.2">
</circle>
<circle cx="100" cy="100" fill="none" r="60" stroke="rgba(255,255,255,0.2)" stroke-width="1.2">
</circle>
<circle cx="100" cy="100" fill="none" r="55" stroke="rgba(255,255,255,0.2)" stroke-width="1.2">
</circle>
<circle cx="100" cy="100" fill="none" r="50" stroke="rgba(255,255,255,0.2)" stroke-width="1.2">
</circle>
<circle cx="100" cy="100" fill="#ffffff" r="42">
</circle>
<image clip-path="url(#center-hole)" height="100" href="https://images.unsplash.com/photo-1529333166437-7750a6dd5a70?ixlib=rb-1.2.1&auto=format&fit=crop&w=400&q=80" id="vinyl-image" preserveaspectratio="xMidYMid slice" width="100" x="50" y="50"/>
<circle cx="100" cy="100" fill="#111" r="5">
</circle>
</svg>
</div>
<div class="player-time" id="player-time">
00:03 / 00:15
</div>
<div class="desktop-controls">
<button class="btn-desktop-play">
<svg fill="currentColor" viewbox="0 0 24 24">
<path d="M6 4h4v16H6zm8 0h4v16h-4z">
</path>
</svg>
</button>
</div>
</div>
</div>
</div>
@import url('https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Inter:wght@400;500;700&display=swap');
:root {
--primary: #ff4f00;
--canvas: #f3f4f6;
--canvas-soft: #e5e7eb;
--ink: #111827;
--gray-400: #9ca3af;
--gray-500: #6b7280;
}
body {
font-family: 'Inter', sans-serif;
background-color: var(--canvas);
color: var(--gray-500);
margin: 0;
padding: 0;
-webkit-font-smoothing: antialiased;
}
.font-display {
font-family: 'Instrument Serif', serif;
}
/* Base Layout */
.hero-container {
position: relative;
height: 100vh;
width: 100%;
background-color: var(--canvas);
color: var(--ink);
overflow: hidden;
display: flex;
flex-direction: column;
user-select: none;
}
/* Sidebar Text */
.sidebar-text {
display: none;
}
@media (min-width: 1024px) {
.sidebar-text {
display: block;
position: absolute;
left: 2rem;
top: 50%;
transform: translateY(-50%) rotate(-90deg);
transform-origin: left;
z-index: 20;
font-size: 10px;
letter-spacing: 0.2em;
color: var(--gray-400);
text-transform: uppercase;
width: 400px;
}
}
/* Background Text */
.bg-text-container {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
pointer-events: none;
z-index: 0;
overflow: hidden;
}
.bg-text {
font-size: 18vw;
line-height: 1;
color: var(--canvas-soft);
white-space: nowrap;
transform: rotate(-12deg);
opacity: 0.6;
user-select: none;
}
/* Center Profile */
.center-profile {
position: absolute;
top: 45%;
left: 50%;
transform: translate(-50%, -50%);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 20;
}
.profile-avatar {
width: 7rem;
height: 7rem;
border-radius: 50%;
background-color: var(--primary);
position: relative;
overflow: hidden;
margin-bottom: 1rem;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
}
@media (min-width: 768px) {
.profile-avatar {
width: 9rem;
height: 9rem;
}
}
.profile-avatar img {
width: 100%;
height: 100%;
object-fit: cover;
mix-blend-mode: luminosity;
opacity: 0.8;
}
.profile-title {
font-size: 1.25rem;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--ink);
margin: 0;
}
@media (min-width: 768px) {
.profile-title {
font-size: 1.5rem;
}
}
.profile-subtitle {
font-size: 10px;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--gray-500);
margin: 0.25rem 0 0 0;
}
@media (min-width: 768px) {
.profile-subtitle {
font-size: 0.75rem;
}
}
/* Circular Gallery */
.gallery-ring {
position: absolute;
top: 45%;
left: 50%;
transform: translate(-50%, -50%);
width: 100vw;
height: 100vw;
max-width: 1200px;
max-height: 1200px;
border-radius: 50%;
z-index: 10;
}
@media (min-width: 768px) {
.gallery-ring {
top: 60%;
}
}
.gallery-items {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
}
.gallery-item {
position: absolute;
top: 50%;
left: 50%;
width: 5rem;
height: 5rem;
margin-left: -2.5rem;
margin-top: -2.5rem;
border-radius: 1.5rem;
overflow: hidden;
cursor: pointer;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
transition: filter 0.8s ease-in-out, box-shadow 0.5s ease-in-out, transform 0.3s ease;
will-change: transform, filter;
}
@media (min-width: 768px) {
.gallery-item {
width: 7rem;
height: 7rem;
margin-left: -3.5rem;
margin-top: -3.5rem;
}
}
.gallery-item img {
width: 100%;
height: 100%;
object-fit: cover;
pointer-events: none;
}
/* Base Blur state for siblings */
.gallery-ring.is-hovering .gallery-item:not(.hovered) {
filter: blur(8px) opacity(0.6) grayscale(50%);
}
.gallery-item.hovered {
z-index: 30;
box-shadow: 0 20px 40px -5px rgba(0, 0, 0, 0.2);
}
/* Fog Overlay */
.fog-overlay {
display: none;
}
@media (min-width: 768px) {
.fog-overlay {
display: block;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 18rem;
background: linear-gradient(to top, #f3f4f6, rgba(243, 244, 246, 0.8), transparent);
z-index: 15;
pointer-events: none;
}
}
/* Bottom Instructions */
.bottom-instructions {
position: absolute;
bottom: 3rem;
left: 0;
width: 100%;
text-align: center;
z-index: 20;
pointer-events: none;
transition: opacity 0.3s ease;
}
.instructions-subtitle {
font-size: 10px;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--gray-500);
margin: 0 0 0.5rem 0;
}
@media (min-width: 768px) {
.instructions-subtitle {
font-size: 0.75rem;
}
}
.instructions-title {
font-size: 2.25rem;
line-height: 2.5rem;
font-style: italic;
color: var(--ink);
margin: 0;
}
@media (min-width: 768px) {
.instructions-title {
font-size: 3.75rem;
line-height: 1;
}
}
.instructions-hint {
font-size: 0.875rem;
font-weight: 500;
color: var(--gray-500);
margin: 1.5rem 0 0 0;
}
@media (min-width: 768px) {
.instructions-hint {
display: none;
}
}
/* Audio Player */
.audio-player {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 85vh;
background-color: rgba(0, 0, 0, 0.4);
backdrop-filter: blur(40px);
-webkit-backdrop-filter: blur(40px);
color: #ffffff;
z-index: 50;
transform: translateY(120%);
opacity: 0;
transition: all 0.7s cubic-bezier(0.76, 0, 0.24, 1);
border-top-left-radius: 2.5rem;
border-top-right-radius: 2.5rem;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 2rem;
box-sizing: border-box;
will-change: transform;
}
.audio-player.active {
transform: translateY(0) !important;
opacity: 1 !important;
}
@media (min-width: 768px) {
.audio-player {
height: 8rem;
background-color: transparent;
backdrop-filter: none;
-webkit-backdrop-filter: none;
border-radius: 0;
flex-direction: row;
padding: 0;
}
}
.player-mobile-controls {
position: absolute;
bottom: 2.5rem;
left: 50%;
transform: translateX(-50%);
display: flex;
align-items: center;
gap: 1.5rem;
}
@media (min-width: 768px) {
.player-mobile-controls {
display: none;
}
}
.btn-icon {
width: 3.5rem;
height: 3.5rem;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: #ffffff;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
transition: background-color 0.2s;
border: none;
cursor: pointer;
}
.btn-icon svg {
width: 1.25rem;
height: 1.25rem;
}
.btn-play {
background-color: rgba(255, 255, 255, 0.2);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.3);
}
.btn-play:hover {
background-color: rgba(255, 255, 255, 0.3);
}
.btn-close {
background-color: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.2);
}
.btn-close:hover {
background-color: rgba(255, 255, 255, 0.2);
}
.player-inner {
width: 100%;
max-width: 48rem;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
}
@media (min-width: 768px) {
.player-inner {
flex-direction: row;
background-color: rgba(0, 0, 0, 0.3);
backdrop-filter: blur(24px);
-webkit-backdrop-filter: blur(24px);
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: 0 -10px 40px -15px rgba(0, 0, 0, 0.2);
border-radius: 2rem;
padding: 1.25rem 2.5rem;
margin-bottom: 1.5rem;
box-sizing: border-box;
}
}
.player-info {
text-align: center;
margin-bottom: 3rem;
}
@media (min-width: 768px) {
.player-info {
text-align: left;
margin-bottom: 0;
flex: 1;
}
}
.info-label {
font-size: 10px;
font-weight: 700;
letter-spacing: 0.2em;
color: rgba(255, 255, 255, 0.6);
text-transform: uppercase;
margin: 0 0 0.5rem 0;
}
@media (min-width: 768px) {
.info-label {
margin: 0 0 0.25rem 0;
}
}
.info-title {
font-size: 1.5rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
color: #ffffff;
margin: 0;
}
@media (min-width: 768px) {
.info-title {
font-size: 1.125rem;
}
}
.vinyl-container {
position: relative;
width: 16rem;
height: 16rem;
margin-bottom: 3rem;
flex-shrink: 0;
}
@media (min-width: 768px) {
.vinyl-container {
width: 8rem;
height: 8rem;
margin-bottom: 0;
margin-top: -4rem;
}
}
.vinyl-svg {
width: 100%;
height: 100%;
filter: drop-shadow(0 25px 25px rgba(0, 0, 0, 0.25));
}
@keyframes spin-vinyl {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.vinyl-spinning {
animation: spin-vinyl 4s linear infinite;
transform-origin: center center;
}
.player-time {
text-align: center;
font-size: 11px;
font-family: monospace;
letter-spacing: 0.2em;
color: rgba(255, 255, 255, 0.6);
}
@media (min-width: 768px) {
.player-time {
text-align: right;
font-size: 10px;
flex: 1;
}
}
.desktop-controls {
display: none;
}
@media (min-width: 768px) {
.desktop-controls {
display: flex;
margin-left: 1.5rem;
padding-left: 1.5rem;
border-left: 1px solid rgba(255, 255, 255, 0.2);
height: 2.5rem;
align-items: center;
}
}
.btn-desktop-play {
width: 2rem;
height: 2rem;
border-radius: 50%;
background: transparent;
border: none;
display: flex;
align-items: center;
justify-content: center;
color: #ffffff;
cursor: pointer;
transition: background-color 0.2s;
}
.btn-desktop-play:hover {
background-color: rgba(255, 255, 255, 0.1);
}
.btn-desktop-play svg {
width: 1rem;
height: 1rem;
}
document.addEventListener('DOMContentLoaded', () => {
const ring = document.getElementById('gallery-ring');
const items = document.querySelectorAll('.gallery-item');
const player = document.getElementById('audio-player');
const closePlayerBtn = document.getElementById('close-player');
const vinylSvg = document.getElementById('vinyl-svg');
const vinylBg = document.getElementById('vinyl-bg');
const vinylImage = document.getElementById('vinyl-image');
const playerTitle = document.getElementById('player-title');
const playerTime = document.getElementById('player-time');
const instructions = document.getElementById('bottom-instructions');
let mainTimeline;
let itemsTimeline;
// 1. Position items in a circle
function positionItems() {
const totalItems = items.length;
const isMobile = window.innerWidth < 768;
// On mobile, use a much larger radius so left/right items bleed off-screen
const radius = isMobile ? window.innerWidth * 0.65 : Math.min(window.innerWidth * 0.28, 450);
// Position each item relative to center
items.forEach((item, i) => {
// Offset angle so item 0 is at the top
const angle = (i / totalItems) * Math.PI * 2 - (Math.PI / 2);
const x = Math.cos(angle) * radius;
const y = Math.sin(angle) * radius;
gsap.set(item, {
x: x,
y: y,
rotation: 0
});
});
}
function initGSAP() {
if (mainTimeline) mainTimeline.kill();
if (itemsTimeline) itemsTimeline.kill();
// Rotate the ring continuously
mainTimeline = gsap.to(ring, {
rotation: 360,
duration: 60,
repeat: -1,
ease: "none"
});
// Counter-rotate the items so they stay upright
itemsTimeline = gsap.to(items, {
rotation: -360,
duration: 60,
repeat: -1,
ease: "none"
});
}
// Initialize layout and animation
positionItems();
initGSAP();
// Re-calculate on resize
window.addEventListener('resize', () => {
positionItems();
// restart animation to avoid rotation jumps
initGSAP();
});
// 2. Hover Interactions (Blur siblings)
items.forEach(item => {
item.addEventListener('mouseenter', () => {
ring.classList.add('is-hovering');
item.classList.add('hovered');
// Slight scale up with GSAP
gsap.to(item, {
scale: 1.2,
duration: 0.3,
ease: "back.out(1.7)"
});
});
item.addEventListener('mouseleave', () => {
ring.classList.remove('is-hovering');
item.classList.remove('hovered');
gsap.to(item, {
scale: 1,
duration: 0.3,
ease: "power2.out"
});
});
});
// 3. Click Interactions (Player)
items.forEach(item => {
item.addEventListener('click', () => {
// Get data
const color = item.getAttribute('data-color');
const title = item.getAttribute('data-title');
const time = item.getAttribute('data-time');
const imgSrc = item.querySelector('img').src;
// Update Player UI
vinylBg.setAttribute('fill', color);
vinylImage.setAttribute('href', imgSrc);
playerTitle.textContent = title;
playerTime.textContent = time;
// Hide instructions, Show player
instructions.style.opacity = '0';
player.classList.add('active');
// Spin Vinyl
vinylSvg.classList.add('vinyl-spinning');
});
});
// Close Player
closePlayerBtn.addEventListener('click', () => {
player.classList.remove('active');
instructions.style.opacity = '1';
vinylSvg.classList.remove('vinyl-spinning');
});
// Optional: click outside gallery to close player on desktop
document.addEventListener('click', (e) => {
if (window.innerWidth >= 768 && player.classList.contains('active')) {
// if click is outside player and not on a gallery item
if (!player.contains(e.target) && !e.target.closest('.gallery-item')) {
player.classList.remove('active');
instructions.style.opacity = '1';
vinylSvg.classList.remove('vinyl-spinning');
}
}
});
});
Diseño Visual y UI (Audiovisual Hero)
Paleta de Colores y Texturas
- Background: Gris clarísimo y etéreo (
#f3f4f6), complementado con una Niebla Inferior (gradiente hacia transparente) que oculta el final de la órbita de manera elegante.
- Centro (Acento): Naranja brillante (
#ff4f00) para el halo que recubre el perfil central.
- Reproductor Glassmorphism: Un diseño inmersivo hecho de cristal oscuro (
bg-black/40 o bg-black/30) con un potente backdrop-blur. Los textos y botones son blancos semitransparentes para integrarse al cristal, logrando un contraste premium contra el fondo.
Tipografía
- Titulares Gigantes: Uso de fuente Serifa cursiva tipo Display (
Instrument Serif) para el titular "Storytelling", aportando una estética editorial romántica.
- Micro-Copy: Tipografía sans-serif geométrica (
Inter) en mayúsculas sostenidas, tamaño extra pequeño (text-[10px]) y con un tracking extremadamente amplio.
Layout y Composición
- Mecánica Orbital Excéntrica (Desktop): El anillo orbital está desfasado hacia abajo (
top-[60%]) con respecto al perfil central (top-[45%]). Esto provoca que la órbita sea asimétrica, rozando el centro arriba y hundiéndose en la niebla abajo.
- Disco de Vinilo Analógico: SVG puro con anillos concéntricos blancos translúcidos (
rgba(255,255,255,0.2)) creando los surcos de un LP físico, aportando textura y realismo.
Audiovisual Storytelling Hero (5ODEGNTRDBVF)
Este "Bit" es un Hero interactivo y cinematográfico diseñado para proyectos musicales, portafolios audiovisuales o cualquier plataforma de storytelling.
A través de un arreglo matemático de elementos, muestra una órbita infinita de imágenes (portadas de canciones o capítulos) rotando alrededor de un perfil central. La órbita es excéntrica en desktop, logrando que las portadas rocen el centro en la parte superior y se sumerjan en una capa de niebla en la parte inferior.
Al interactuar con ellas, el reproductor de audio emerge con un exquisito diseño glassmorphism (cristal translúcido), que incluye un disco de vinilo dinámico cuyas ranuras son blancas translúcidas y hereda dinámicamente la portada seleccionada.
Web Skills & Técnicas
Técnicas Modernas Aplicadas
- GSAP Infinite & Counter Rotation: Para lograr una órbita 2D fotorrealista donde los objetos conservan su orientación ("gravedad"), rotamos un padre gigante en 360 grados (
rotation: 360), al mismo tiempo que rotamos a todos los hijos en -360 grados exactos (rotation: -360). Esto hace que las imágenes siempre se mantengan perfectamente verticales (sin ponerse de cabeza) al dar la vuelta.
- GSAP Soft Hover Triggers: Cuando el mouse cruza una imagen, inyectamos clases para aplicar el filtro CSS
blur suavizado (0.8s ease-in-out) a todos los siblings, combinándolo con una ampliación elástica para esa imagen específica.
- Desfase Orbital CSS: Aprovechamos el sistema de posicionamiento absoluto para lograr una órbita "excéntrica" sin código matemático complejo: el contenedor de las órbitas se baja intencionalmente (
md:top-[60%]) con respecto al perfil central, logrando que los elementos pasen muy pegados arriba y muy separados abajo.
- Data Binding Manual: Para evitar frameworks densos, inyectamos atributos nativos como
data-color y data-title para re-colorear SVGs y textos del reproductor en el momento exacto del clic.
- Glassmorphism Profundo: El reproductor usa fondos semi-translúcidos (
bg-black/30) con fuertes desenfoques de fondo (backdrop-blur-xl), integrándose sin costuras a cualquier contenido que se deslice por detrás.