-
-
+
+
@@ -484,11 +496,12 @@ const heroLayout = [
import '../scripts/galaxia-scroll.js';
-
+
diff --git a/src/scripts/proyectos-burbujas.js b/src/scripts/proyectos-burbujas.js
new file mode 100644
index 0000000..64b4b70
--- /dev/null
+++ b/src/scripts/proyectos-burbujas.js
@@ -0,0 +1,458 @@
+import { forceSimulation, forceCollide, forceManyBody, forceX, forceY } from 'd3-force';
+import { select } from 'd3-selection';
+import { scaleSqrt } from 'd3-scale';
+import { drag } from 'd3-drag';
+import 'd3-transition';
+import gsap from 'gsap';
+
+// ── Mapa de proyectos: burbujas-squircle con simulación de física ─────────────
+// Cada proyecto es un "squircle" (forma de icono de iOS) cuyo tamaño viene de
+// la propiedad `peso` del JSON. Las burbujas se agrupan por categoría en zonas
+// y se pueden filtrar desde las pills o desde la órbita de categorías.
+
+function initBurbujas() {
+ const dataEl = document.getElementById('burbujas-data');
+ const wrap = document.getElementById('mapaWrap');
+ const tip = document.getElementById('mapaTip');
+ const pillsEl = document.getElementById('mapaPills');
+ if (!dataEl || !wrap || !tip || !pillsEl) return;
+
+ const { cats, projects } = JSON.parse(dataEl.textContent);
+ const catById = Object.fromEntries(cats.map((c) => [c.id, c]));
+ const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
+
+ const svg = select('#mapaChart');
+ if (svg.empty()) return;
+
+ let curCat = 'all';
+ let entered = false; // ya se reprodujo la animación de entrada
+ let narrow = isNarrow();
+ let sim = null;
+ let nodes = [];
+ let bubs = null;
+ let W = 0;
+ let H = 0;
+ let zones = {};
+
+ function isNarrow() {
+ return (wrap.clientWidth || window.innerWidth) < 620;
+ }
+
+ // Superellipse |x/r|^n + |y/r|^n = 1 → la forma "casi cuadrada" de los
+ // iconos de iOS. n controla cuánto se acerca al cuadrado.
+ function squircle(r, n = 4.5) {
+ const STEPS = 64;
+ let d = '';
+ for (let i = 0; i < STEPS; i++) {
+ const t = (i / STEPS) * Math.PI * 2;
+ const c = Math.cos(t);
+ const s = Math.sin(t);
+ const x = r * Math.sign(c) * Math.abs(c) ** (2 / n);
+ const y = r * Math.sign(s) * Math.abs(s) ** (2 / n);
+ d += (i === 0 ? 'M' : 'L') + x.toFixed(2) + ',' + y.toFixed(2);
+ }
+ return d + 'Z';
+ }
+
+ // La esquina del squircle sobresale del círculo inscrito (~4%)
+ const EXTENT = Math.SQRT2 * 0.5 ** (2 / 4.5);
+
+ function wrapTitle(t, maxChars) {
+ const words = t.trim().split(/\s+/);
+ const lines = [];
+ let cur = '';
+ for (const w of words) {
+ if (!cur) cur = w;
+ else if ((cur + ' ' + w).length <= maxChars) cur += ' ' + w;
+ else { lines.push(cur); cur = w; }
+ }
+ if (cur) lines.push(cur);
+ if (lines.length > 2) {
+ lines.length = 2;
+ lines[1] = lines[1].slice(0, Math.max(1, maxChars - 1)) + '…';
+ }
+ return lines;
+ }
+
+ function target(d) {
+ return curCat === 'all' ? zones[d.cat] : [W / 2, H / 2];
+ }
+
+ function clampX(d) { return Math.max(d.r * EXTENT + 2, Math.min(W - d.r * EXTENT - 2, d.x)); }
+ function clampY(d) { return Math.max(d.r * EXTENT + 2, Math.min(H - d.r * EXTENT - 2, d.y)); }
+
+ function redraw() {
+ if (!bubs) return;
+ bubs.attr('transform', (d) => {
+ d.x = clampX(d);
+ d.y = clampY(d);
+ return `translate(${d.x},${d.y}) scale(${d.k * d.h})`;
+ });
+ }
+
+ function build() {
+ narrow = isNarrow();
+ const cols = narrow ? 2 : 3;
+ const rows = Math.ceil(cats.length / cols);
+ W = narrow ? 640 : 1000;
+ H = narrow ? 980 : 640;
+ const cellW = W / cols;
+ const cellH = H / rows;
+
+ zones = {};
+ cats.forEach((c, i) => {
+ const col = i % cols;
+ const row = Math.floor(i / cols);
+ // Desplazado hacia abajo para dejar aire a la etiqueta de zona
+ zones[c.id] = [(col + 0.5) * cellW, (row + 0.5) * cellH + 18];
+ });
+
+ const rScale = scaleSqrt().domain([0, 100]).range([0, narrow ? 62 : 86]);
+ const keepK = entered || reduced ? 1 : 0;
+ nodes = projects.map((p, i) => {
+ const [zx, zy] = zones[p.cat] || [W / 2, H / 2];
+ return {
+ ...p,
+ r: Math.max(narrow ? 26 : 32, rScale(p.peso ?? 50)),
+ x: zx + Math.cos(i * 2.4) * 30,
+ y: zy + Math.sin(i * 2.4) * 30,
+ k: keepK, // escala de entrada
+ h: 1, // escala de hover
+ };
+ });
+
+ if (sim) sim.stop();
+ svg.selectAll('*').remove();
+ svg.attr('viewBox', `0 0 ${W} ${H}`);
+
+ // ── Defs: degradado de legibilidad + clip squircle por burbuja ──
+ const defs = svg.append('defs');
+ const grad = defs.append('linearGradient')
+ .attr('id', 'bub-fade').attr('x1', 0).attr('y1', 0).attr('x2', 0).attr('y2', 1);
+ grad.append('stop').attr('offset', '0.3').attr('stop-color', 'rgba(2,8,23,0)');
+ grad.append('stop').attr('offset', '1').attr('stop-color', 'rgba(2,8,23,0.86)');
+
+ nodes.forEach((d) => {
+ defs.append('clipPath').attr('id', `bclip-${d.id}`)
+ .append('path').attr('d', squircle(d.r));
+ });
+
+ // ── Divisores y etiquetas de zona ──
+ const divG = svg.append('g').attr('class', 'mapa-divs');
+ for (let c = 1; c < cols; c++) {
+ divG.append('line')
+ .attr('x1', c * cellW).attr('y1', 16).attr('x2', c * cellW).attr('y2', H - 16)
+ .attr('stroke', 'rgba(255,255,255,0.13)').attr('stroke-width', 1).attr('stroke-dasharray', '3,7');
+ }
+ for (let r = 1; r < rows; r++) {
+ divG.append('line')
+ .attr('x1', 16).attr('y1', r * cellH).attr('x2', W - 16).attr('y2', r * cellH)
+ .attr('stroke', 'rgba(255,255,255,0.13)').attr('stroke-width', 1).attr('stroke-dasharray', '3,7');
+ }
+
+ const zlG = svg.append('g').attr('class', 'mapa-zlabels');
+ cats.forEach((c, i) => {
+ const col = i % cols;
+ const row = Math.floor(i / cols);
+ zlG.append('text')
+ .attr('x', (col + 0.5) * cellW)
+ .attr('y', row * cellH + 22)
+ .attr('text-anchor', 'middle')
+ .attr('font-family', "'Chakra Petch', sans-serif")
+ .attr('font-size', narrow ? 12 : 13)
+ .attr('font-weight', 600)
+ .attr('letter-spacing', '0.12em')
+ .attr('fill', c.color)
+ .attr('opacity', 0.85)
+ .text(c.titulo.toUpperCase());
+ });
+
+ // ── Burbujas ──
+ bubs = svg.append('g').attr('class', 'mapa-bubs')
+ .selectAll('g')
+ .data(nodes)
+ .enter()
+ .append('g')
+ .attr('class', 'bub')
+ .attr('tabindex', 0)
+ .attr('role', 'link')
+ .attr('aria-label', (d) => `${d.titulo} — ${catById[d.cat]?.titulo ?? ''}`);
+
+ // Fondo (por si la imagen tarda) + imagen recortada al squircle
+ bubs.append('path')
+ .attr('d', (d) => squircle(d.r))
+ .attr('fill', 'rgba(13,18,38,0.95)');
+
+ bubs.append('image')
+ .attr('href', (d) => d.imagen)
+ .attr('x', (d) => -d.r).attr('y', (d) => -d.r)
+ .attr('width', (d) => d.r * 2).attr('height', (d) => d.r * 2)
+ .attr('preserveAspectRatio', 'xMidYMid slice')
+ .attr('clip-path', (d) => `url(#bclip-${d.id})`)
+ .each(function (d) {
+ // Si la imagen no existe: fondo tintado del color de la categoría + su icono
+ this.addEventListener('error', () => {
+ const g = select(this.parentNode);
+ const color = catById[d.cat]?.color ?? '#9bb4d0';
+ this.remove();
+ g.insert('path', '.bub-ring')
+ .attr('d', squircle(d.r))
+ .attr('fill', color)
+ .attr('fill-opacity', 0.16);
+ const logo = catById[d.cat]?.logo;
+ if (logo) {
+ const s = d.r * 0.62;
+ g.insert('image', '.bub-ring')
+ .attr('href', logo)
+ .attr('x', -s / 2)
+ .attr('y', -s / 2 - d.r * 0.14)
+ .attr('width', s)
+ .attr('height', s)
+ .attr('opacity', 0.9)
+ .attr('pointer-events', 'none');
+ }
+ }, { once: true });
+ });
+
+ bubs.append('path')
+ .attr('d', (d) => squircle(d.r))
+ .attr('fill', 'url(#bub-fade)');
+
+ bubs.append('path')
+ .attr('class', 'bub-ring')
+ .attr('d', (d) => squircle(d.r))
+ .attr('fill', 'none')
+ .attr('stroke', (d) => catById[d.cat]?.color ?? '#9bb4d0')
+ .attr('stroke-width', 1.6)
+ .attr('opacity', 0.9);
+
+ // Título dentro de la burbuja (solo si cabe)
+ bubs.each(function (d) {
+ if (d.r < 40) return;
+ const g = select(this);
+ const fs = Math.max(11, Math.min(17, d.r * 0.24));
+ const maxChars = Math.max(7, Math.floor((d.r * 1.55) / (fs * 0.56)));
+ const lines = wrapTitle(d.titulo, maxChars);
+ const lh = fs + 2;
+ const baseY = d.r * 0.66;
+ lines.forEach((line, i) => {
+ g.append('text')
+ .attr('class', 'bub-titulo')
+ .attr('text-anchor', 'middle')
+ .attr('x', 0)
+ .attr('y', baseY - (lines.length - 1 - i) * lh)
+ .attr('font-family', "'Chakra Petch', sans-serif")
+ .attr('font-size', fs)
+ .attr('font-weight', 600)
+ .attr('fill', '#fff')
+ .attr('stroke', 'rgba(0,8,20,0.55)')
+ .attr('stroke-width', 2.5)
+ .attr('paint-order', 'stroke')
+ .attr('pointer-events', 'none')
+ .text(line);
+ });
+ if (d.premio) {
+ g.append('text')
+ .attr('text-anchor', 'middle')
+ .attr('x', 0)
+ .attr('y', -d.r * 0.58)
+ .attr('font-size', Math.max(13, d.r * 0.24))
+ .attr('pointer-events', 'none')
+ .text('🏆');
+ }
+ });
+
+ // ── Física ──
+ sim = forceSimulation(nodes)
+ .force('charge', forceManyBody().strength(-14))
+ .force('collide', forceCollide((d) => d.r * 1.05 + 4).strength(0.95))
+ .force('x', forceX((d) => target(d)[0]).strength(curCat === 'all' ? 0.07 : 0.12))
+ .force('y', forceY((d) => target(d)[1]).strength(curCat === 'all' ? 0.07 : 0.12))
+ .on('tick', redraw)
+ .stop();
+
+ // ── Arrastrar burbujas ──
+ bubs.call(
+ drag()
+ .clickDistance(6)
+ .on('start', (event, d) => {
+ if (!event.active) sim.alphaTarget(0.25).restart();
+ d.fx = d.x;
+ d.fy = d.y;
+ })
+ .on('drag', (event, d) => { d.fx = event.x; d.fy = event.y; })
+ .on('end', (event, d) => {
+ if (!event.active) sim.alphaTarget(0);
+ d.fx = null;
+ d.fy = null;
+ })
+ );
+
+ // ── Interacción: tooltip, click y teclado ──
+ bubs
+ .on('click', (event, d) => {
+ if (event.defaultPrevented) return; // venía de un drag
+ window.location.href = `/proyectos/${d.id}`;
+ })
+ .on('keydown', (event, d) => {
+ if (event.key === 'Enter' || event.key === ' ') {
+ event.preventDefault();
+ window.location.href = `/proyectos/${d.id}`;
+ }
+ })
+ .on('mouseenter', function (event, d) {
+ select(this).raise();
+ select(this).select('.bub-ring').attr('stroke-width', 3).attr('opacity', 1);
+ gsap.to(d, { h: 1.06, duration: 0.25, ease: 'power2.out', onUpdate: redraw });
+ showTip(d);
+ moveTip(event);
+ })
+ .on('mousemove', (event) => moveTip(event))
+ .on('mouseleave', function (event, d) {
+ select(this).select('.bub-ring').attr('stroke-width', 1.6).attr('opacity', 0.9);
+ gsap.to(d, { h: 1, duration: 0.25, ease: 'power2.out', onUpdate: redraw });
+ tip.style.display = 'none';
+ });
+
+ applyFilterStyles(0);
+ redraw();
+
+ if (entered || reduced) {
+ sim.alpha(0.9).restart();
+ }
+ }
+
+ // ── Tooltip ──
+ function showTip(d) {
+ const cat = catById[d.cat];
+ const techs = (d.tecnologias || [])
+ .map((t) => `
${t}`)
+ .join('');
+ tip.innerHTML = `
+
${d.titulo}
+
${cat?.titulo ?? ''}
+ ${d.premio ? `
🏆 ${d.premio}
` : ''}
+ ${d.descripcion ? `
${d.descripcion}
` : ''}
+
+ Envergadura
+
+
+ ${techs ? `
${techs}
` : ''}
+ `;
+ tip.style.display = 'block';
+ }
+
+ function moveTip(event) {
+ const r = wrap.getBoundingClientRect();
+ const x = event.clientX - r.left;
+ const y = event.clientY - r.top;
+ const tw = tip.offsetWidth || 220;
+ tip.style.left = (x + 16 + tw < r.width ? x + 16 : Math.max(0, x - tw - 16)) + 'px';
+ tip.style.top = Math.max(0, Math.min(y - 12, r.height - tip.offsetHeight - 8)) + 'px';
+ }
+
+ // ── Filtro por categoría ──
+ function applyFilterStyles(dur) {
+ if (!bubs) return;
+ const visible = (d) => curCat === 'all' || d.cat === curCat;
+ bubs
+ .style('pointer-events', (d) => (visible(d) ? 'auto' : 'none'))
+ .attr('tabindex', (d) => (visible(d) ? 0 : -1))
+ .transition().duration(dur)
+ .style('opacity', (d) => (visible(d) ? 1 : 0.07));
+ svg.select('.mapa-divs').transition().duration(dur).style('opacity', curCat === 'all' ? 1 : 0);
+ svg.select('.mapa-zlabels').transition().duration(dur).style('opacity', curCat === 'all' ? 1 : 0);
+ }
+
+ function setFilter(cat) {
+ curCat = cat;
+ const s = cat === 'all' ? 0.07 : 0.12;
+ sim.force('x', forceX((d) => target(d)[0]).strength(s));
+ sim.force('y', forceY((d) => target(d)[1]).strength(s));
+ sim.alpha(0.6).restart();
+ applyFilterStyles(350);
+ tip.style.display = 'none';
+
+ pillsEl.querySelectorAll('.mapa-pill').forEach((p) => {
+ p.classList.toggle('act', p.dataset.cat === cat);
+ p.setAttribute('aria-pressed', p.dataset.cat === cat ? 'true' : 'false');
+ });
+ document.querySelectorAll('.proyecto-card').forEach((card) => {
+ card.classList.toggle('is-active', card.dataset.aptitudId === cat);
+ });
+ }
+
+ // ── Pills de filtro ──
+ [{ id: 'all', titulo: 'Todos', color: null }, ...cats].forEach((c) => {
+ const el = document.createElement('button');
+ el.type = 'button';
+ el.className = 'mapa-pill' + (c.id === 'all' ? ' act' : '');
+ el.dataset.cat = c.id;
+ el.setAttribute('aria-pressed', c.id === 'all' ? 'true' : 'false');
+ if (c.color) {
+ const dot = document.createElement('span');
+ dot.className = 'mapa-pill-dot';
+ dot.style.background = c.color;
+ el.appendChild(dot);
+ }
+ el.appendChild(document.createTextNode(c.titulo));
+ el.addEventListener('click', () => setFilter(curCat === c.id && c.id !== 'all' ? 'all' : c.id));
+ pillsEl.appendChild(el);
+ });
+
+ // ── La órbita de categorías también filtra el mapa ──
+ document.querySelectorAll('.proyecto-card').forEach((card) => {
+ card.addEventListener('click', (e) => {
+ e.preventDefault();
+ const id = card.dataset.aptitudId;
+ if (!id) return;
+ setFilter(curCat === id ? 'all' : id);
+ document.getElementById('proyectos-mapa')?.scrollIntoView({
+ behavior: reduced ? 'auto' : 'smooth',
+ block: 'nearest',
+ });
+ });
+ });
+
+ build();
+
+ // ── Entrada: las burbujas brotan al entrar en viewport ──
+ const io = new IntersectionObserver(
+ (entries) => {
+ if (!entries.some((e) => e.isIntersecting) || entered) return;
+ entered = true;
+ io.disconnect();
+ sim.alpha(0.9).restart();
+ if (reduced) {
+ nodes.forEach((d) => (d.k = 1));
+ redraw();
+ } else {
+ gsap.to(nodes, {
+ k: 1,
+ duration: 0.8,
+ ease: 'back.out(1.7)',
+ stagger: 0.045,
+ onUpdate: redraw,
+ });
+ }
+ },
+ { threshold: 0.15 }
+ );
+ io.observe(wrap);
+
+ // ── Cambio de layout (3×2 ↔ 2×3) al redimensionar ──
+ let resizeRaf = 0;
+ window.addEventListener('resize', () => {
+ if (resizeRaf) return;
+ resizeRaf = requestAnimationFrame(() => {
+ resizeRaf = 0;
+ if (isNarrow() !== narrow) build();
+ });
+ });
+}
+
+if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', initBurbujas);
+} else {
+ initBurbujas();
+}
diff --git a/src/styles/proyectos.css b/src/styles/proyectos.css
index b28fb4c..85afb1e 100644
--- a/src/styles/proyectos.css
+++ b/src/styles/proyectos.css
@@ -1,4 +1,4 @@
-/* Estilos para la sección de proyectos - Layout legible y fluido */
+/* Estilos para la sección de proyectos - Órbita de categorías + mapa de burbujas */
/* ============================================
ANIMACIONES PERSONALIZADAS
@@ -56,7 +56,8 @@
}
/* ============================================
- HERO DECORATIVO - Órbita sin scroll-hijack
+ HERO DECORATIVO - Órbita de categorías
+ (las tarjetas en órbita filtran el mapa)
============================================ */
.proyectos-hero {
@@ -66,15 +67,14 @@
justify-content: center;
position: relative;
padding: 20px;
- margin-top: 5vh;
- margin-bottom: 10vh;
+ margin-top: 2vh;
+ margin-bottom: 4vh;
}
.proyectos-hero-inner {
position: relative;
width: 100%;
- /*max-width: 400px;*/
- height: 600px;
+ height: 520px;
display: flex;
align-items: center;
justify-content: center;
@@ -142,7 +142,7 @@
overflow: hidden;
transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
will-change: transform;
- box-shadow:
+ box-shadow:
0 8px 20px rgba(0, 0, 0, 0.2),
0 0 20px rgba(147, 197, 253, 0.1);
}
@@ -176,7 +176,7 @@
.proyecto-card:hover .proyecto-card-inner {
transform: translateY(-8px) scale(1.08);
- box-shadow:
+ box-shadow:
0 25px 50px rgba(0, 0, 0, 0.35),
0 0 40px rgba(147, 197, 253, 0.3),
0 0 60px rgba(147, 197, 253, 0.15);
@@ -187,6 +187,18 @@
rgba(255, 255, 255, 0.08));
}
+/* Categoría activa como filtro del mapa: aro en su color */
+.proyecto-card.is-active {
+ filter: brightness(1.15) saturate(1.2);
+}
+
+.proyecto-card.is-active .proyecto-card-inner {
+ border-color: var(--cat-color, rgba(147, 197, 253, 0.8));
+ box-shadow:
+ 0 8px 24px rgba(0, 0, 0, 0.35),
+ 0 0 26px color-mix(in srgb, var(--cat-color, #93c5fd) 55%, transparent);
+}
+
.proyecto-icon {
width: 100%;
height: auto;
@@ -235,698 +247,193 @@
}
/* ============================================
- CONTENIDO DE PROYECTOS - Layout por Aptitud
+ MAPA DE BURBUJAS - Proyectos con física
============================================ */
-.proyectos-content {
- max-width: 1200px;
+.proyectos-mapa {
+ max-width: 1160px;
margin: 0 auto;
padding: 0 24px 8vh;
- display: flex;
- flex-direction: column;
- gap: 10vh;
-}
-
-.aptitud-bloque {
- position: relative;
-}
-
-.aptitud-header {
- display: flex;
- align-items: center;
- gap: 20px;
- margin-bottom: 32px;
- padding: 24px;
- background: linear-gradient(135deg,
- rgba(255, 255, 255, 0.08),
- rgba(147, 197, 253, 0.05));
- backdrop-filter: blur(16px);
- -webkit-backdrop-filter: blur(16px);
- border-radius: 20px;
- border: 1px solid rgba(255, 255, 255, 0.12);
- box-shadow:
- 0 8px 32px rgba(0, 0, 0, 0.2),
- inset 0 1px 0 rgba(255, 255, 255, 0.1);
- transition: all 0.4s ease;
-}
-
-.aptitud-header:hover {
- border-color: rgba(147, 197, 253, 0.25);
- box-shadow:
- 0 12px 40px rgba(0, 0, 0, 0.3),
- 0 0 40px rgba(147, 197, 253, 0.1),
- inset 0 1px 0 rgba(255, 255, 255, 0.15);
}
-.aptitud-icono {
- width: 70px;
- height: 70px;
- border-radius: 50%;
- background: linear-gradient(145deg,
- rgba(255, 255, 255, 0.15),
- rgba(147, 197, 253, 0.1));
- border: 2px solid rgba(255, 255, 255, 0.2);
+/* Pills de filtro por categoría */
+.mapa-pills {
display: flex;
- align-items: center;
+ flex-wrap: wrap;
justify-content: center;
- flex-shrink: 0;
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
-}
-
-.aptitud-icono img {
- width: 36px;
- height: 36px;
- object-fit: contain;
- filter: drop-shadow(0 2px 8px rgba(0, 0, 0, 0.3));
-}
-
-.aptitud-info {
- flex: 1;
- min-width: 0;
-}
-
-.aptitud-titulo {
- font-family: 'Chakra Petch', sans-serif;
- font-size: 1.5rem;
- font-weight: 700;
- color: white;
- margin: 0 0 8px 0;
- text-shadow: 0 2px 8px rgba(0,0,0,0.4);
- line-height: 1.2;
-}
-
-.aptitud-descripcion {
- font-family: 'Chakra Petch', sans-serif;
- font-size: 0.95rem;
- color: rgba(255, 255, 255, 0.7);
- margin: 0;
- line-height: 1.5;
- max-width: 700px;
-}
-
-/* Grid de proyectos - Más espacio para tarjetas grandes */
-.proyectos-grid-list {
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
- gap: 32px;
-}
-
-/* Tarjeta de proyecto individual - Formato Vertical */
-.proyecto-detail-card {
- display: flex;
- flex-direction: column;
- text-decoration: none;
- color: inherit;
- background: linear-gradient(135deg,
- rgba(30, 35, 55, 0.7),
- rgba(15, 20, 35, 0.8));
- backdrop-filter: blur(20px);
- -webkit-backdrop-filter: blur(20px);
- border-radius: 20px;
- border: 1px solid rgba(255, 255, 255, 0.1);
- cursor: pointer;
- transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
- position: relative;
- overflow: hidden;
- height: 100%;
- will-change: transform;
-}
-
-.proyecto-detail-card:hover {
- transform: translateY(-8px);
- border-color: rgba(147, 197, 253, 0.5);
- box-shadow:
- 0 20px 40px rgba(0, 0, 0, 0.5),
- 0 0 30px rgba(147, 197, 253, 0.15);
-}
-
-/* Imagen del proyecto (Ahora ocupa el 50% superior) */
-.proyecto-image-container {
- width: 100%;
- height: 200px;
- overflow: hidden;
- position: relative;
- border-bottom: 1px solid rgba(255, 255, 255, 0.05);
-}
-
-.proyecto-image {
- width: 100%;
- height: 100%;
- object-fit: cover;
- transition: transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
- will-change: transform;
-}
-
-.proyecto-detail-card:hover .proyecto-image {
- transform: scale(1.08);
+ gap: 10px;
+ margin-bottom: 22px;
}
-/* Botón flotante para enlace externo */
-.card-btn-link-float {
- position: absolute;
- top: 16px;
- right: 16px;
- width: 40px;
- height: 40px;
- background: rgba(10, 10, 20, 0.7);
- backdrop-filter: blur(8px);
- border: 1px solid rgba(255, 255, 255, 0.2);
- border-radius: 50%;
- display: flex;
+.mapa-pill {
+ display: inline-flex;
align-items: center;
- justify-content: center;
- color: white;
- opacity: 0;
- transform: translateY(-10px);
- transition: all 0.3s ease;
- z-index: 2;
-}
-
-.proyecto-detail-card:hover .card-btn-link-float {
- opacity: 1;
- transform: translateY(0);
-}
-
-.card-btn-link-float:hover {
- background: rgba(34, 197, 94, 0.8);
- border-color: #22c55e;
- transform: scale(1.1) !important;
-}
-
-/* Contenedor de la info */
-.proyecto-info-wrapper {
- padding: 16px;
- position: static;
- transform: none;
-}
-
-.proyecto-info {
- margin-bottom: 0;
-}
-
-.proyecto-detail-titulo {
+ gap: 8px;
+ padding: 8px 18px;
+ border-radius: 999px;
font-family: 'Chakra Petch', sans-serif;
- font-size: 1.1rem;
- font-weight: 600;
- color: white;
- margin: 0 0 8px 0;
- line-height: 1.2;
- transition: color 0.3s ease;
-}
-
-.proyecto-detail-card:hover .proyecto-detail-titulo {
- color: #93c5fd;
-}
-
-.proyecto-detail-desc {
- font-family: 'Chakra Petch', sans-serif;
- font-size: 0.82rem;
- color: rgba(255, 255, 255, 0.75);
- margin: 0 0 10px 0;
- line-height: 1.45;
- display: -webkit-box;
- -webkit-line-clamp: 2;
- line-clamp: 2;
- -webkit-box-orient: vertical;
- overflow: hidden;
-}
-
-/* Tags de tecnologías */
-.proyecto-tecnologias {
- display: flex;
- flex-wrap: wrap;
- gap: 6px;
-}
-
-.tech-tag {
- font-family: 'Chakra Petch', sans-serif;
- font-size: 0.75rem;
- padding: 4px 12px;
- background: rgba(255,255,255,0.1);
- border: 1px solid rgba(147, 197, 253, 0.2);
- border-radius: 8px;
- color: #bfdbfe;
-}
-
-.tech-tag[data-tech="React"],
-.tech-tag[data-tech="Next.js"] { background: rgba(97,218,251,0.2); color: #61dafb; }
-.tech-tag[data-tech="Blender"] { background: rgba(234,106,32,0.2); color: #ea6a20; }
-.tech-tag[data-tech="Python"] { background: rgba(55,118,171,0.2); color: #3776ab; }
-.tech-tag[data-tech="TypeScript"] { background: rgba(49,120,198,0.2); color: #3178c6; }
-.tech-tag[data-tech="Astro"] { background: rgba(255,90,40,0.2); color: #ff5a28; }
-
-.tech-tag-more {
- background: transparent;
- border-color: rgba(255, 255, 255, 0.2);
- color: rgba(255, 255, 255, 0.6);
-}
-
-/* ============================================
- MODAL DE PROYECTO - Estilo Cinematográfico
- ============================================ */
-
-.proyecto-modal-overlay {
- position: fixed;
- inset: 0;
- backdrop-filter: blur(5px) saturate(120%);
- -webkit-backdrop-filter: blur(5px) saturate(120%);
- z-index: 10000;
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 24px;
- opacity: 0;
- visibility: hidden;
- transition: all 0.36s cubic-bezier(0.16, 1, 0.3, 1);
- overflow-y: auto;
-}
-
-.proyecto-modal-overlay.active {
- opacity: 1;
- visibility: visible;
-}
-
-.proyecto-modal {
- width: 100%;
- max-width: 1400px;
- max-height: 90vh;
- overflow: hidden;
- display: flex;
- flex-direction: column;
- position: relative;
- transform: scale(0.95) translateY(20px);
- transition: transform 0.44s cubic-bezier(0.16, 1, 0.3, 1);
- background: rgba(12, 14, 20, 0.48);
- backdrop-filter: blur(6px) saturate(120%);
- -webkit-backdrop-filter: blur(6px) saturate(120%);
- border-radius: 18px;
- border: 1px solid rgba(255, 255, 255, 0.06);
- box-shadow:
- 0 30px 90px rgba(0, 0, 0, 0.75),
- 0 0 0 1px rgba(255, 255, 255, 0.02);
-}
-
-.proyecto-modal-overlay.active .proyecto-modal {
- transform: scale(1) translateY(0);
-}
-
-/* Imagen de fondo hero */
-.modal-backdrop {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 70%;
- overflow: hidden;
- z-index: 0;
- border-radius: 20px 20px 0 0;
-}
-
-.modal-backdrop-img {
- width: 100%;
- height: 100%;
- object-fit: cover;
- object-position: center top;
- filter: brightness(0.6);
- transition: transform 0.6s ease;
-}
-
-.proyecto-modal:hover .modal-backdrop-img {
- transform: scale(1.02);
-}
-
-/* Gradiente sobre la imagen */
-.modal-backdrop::after {
- content: '';
- position: absolute;
- inset: 0;
- background: linear-gradient(180deg,
- transparent 0%,
- transparent 20%,
- rgba(10, 10, 20, 0.6) 50%,
- rgba(10, 10, 20, 0.95) 80%,
- rgba(10, 10, 20, 1) 100%);
- pointer-events: none;
-}
-
-/* Botón cerrar */
-.modal-close {
- position: absolute;
- top: 16px;
- right: 16px;
- width: 48px;
- height: 48px;
- border-radius: 50%;
- background: rgba(0, 0, 0, 0.7);
+ font-size: 0.85rem;
+ font-weight: 500;
+ color: rgba(255, 255, 255, 0.8);
+ background: rgba(30, 35, 55, 0.6);
+ border: 1px solid rgba(255, 255, 255, 0.15);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
- border: 2px solid rgba(255, 255, 255, 0.2);
- color: rgba(255, 255, 255, 0.9);
cursor: pointer;
- display: flex;
- align-items: center;
- justify-content: center;
transition: all 0.3s ease;
- z-index: 100;
}
-.modal-close:hover {
- background: rgba(255, 255, 255, 0.15);
- border-color: rgba(255, 255, 255, 0.3);
+.mapa-pill:hover {
+ border-color: rgba(147, 197, 253, 0.5);
color: white;
- transform: scale(1.1);
-}
-
-/* Contenido principal del modal */
-.modal-content-wrapper {
- position: relative;
- z-index: 10;
- display: flex;
- flex-direction: column;
- height: 100%;
- padding: 0;
- overflow-y: auto;
- scrollbar-width: thin;
- scrollbar-color: rgba(147, 197, 253, 0.3) transparent;
-}
-
-.modal-content-wrapper::-webkit-scrollbar {
- width: 6px;
+ transform: translateY(-2px);
}
-.modal-content-wrapper::-webkit-scrollbar-track {
- background: transparent;
+.mapa-pill.act {
+ background: white;
+ color: #0a0e1c;
+ border-color: white;
+ box-shadow: 0 4px 20px rgba(255, 255, 255, 0.2);
}
-.modal-content-wrapper::-webkit-scrollbar-thumb {
- background: rgba(147, 197, 253, 0.3);
- border-radius: 3px;
+.mapa-pill-dot {
+ width: 9px;
+ height: 9px;
+ border-radius: 50%;
+ flex-shrink: 0;
}
-/* Sección hero con poster y título */
-.modal-hero {
- display: flex;
- align-items: flex-end;
- gap: 30px;
- padding: 40vh 48px 28px 48px;
- min-height: 55vh;
+/* Panel de cristal que contiene el chart */
+.mapa-panel {
+ background: linear-gradient(135deg,
+ rgba(30, 35, 55, 0.55),
+ rgba(12, 16, 32, 0.7));
+ backdrop-filter: blur(16px);
+ -webkit-backdrop-filter: blur(16px);
+ border: 1px solid rgba(255, 255, 255, 0.12);
+ border-radius: 28px;
+ padding: 14px;
+ box-shadow:
+ 0 12px 48px rgba(0, 0, 0, 0.35),
+ inset 0 1px 0 rgba(255, 255, 255, 0.08);
}
-/* Poster del proyecto - Cuadrado */
-.modal-poster-container {
- flex-shrink: 0;
- width: 240px;
- height: 240px;
+.mapa-wrap {
position: relative;
}
-.modal-poster {
+#mapaChart {
width: 100%;
- height: 100%;
- border-radius: 12px;
- object-fit: cover;
- box-shadow:
- 0 20px 50px rgba(0, 0, 0, 0.6),
- 0 0 0 1px rgba(255, 255, 255, 0.1);
- transition: transform 0.4s ease, box-shadow 0.4s ease;
+ height: auto;
+ display: block;
}
-.modal-poster:hover {
- transform: scale(1.03);
- box-shadow:
- 0 25px 60px rgba(0, 0, 0, 0.7),
- 0 0 0 1px rgba(255, 255, 255, 0.2);
+/* Burbujas: squircles clicables */
+.bub {
+ cursor: pointer;
+ outline: none;
}
-/* Info del héroe */
-.modal-hero-info {
- flex: 1;
- min-width: 0;
- padding-bottom: 10px;
+.bub:focus-visible .bub-ring {
+ stroke-width: 4;
+ opacity: 1;
}
-/* Título grande estilo película */
-.modal-titulo {
+/* Tooltip */
+.mapa-tip {
+ position: absolute;
+ display: none;
+ pointer-events: none;
+ z-index: 20;
+ width: 236px;
+ padding: 14px 16px;
+ border-radius: 14px;
+ background: rgba(10, 14, 28, 0.92);
+ backdrop-filter: blur(12px);
+ -webkit-backdrop-filter: blur(12px);
+ border: 1px solid rgba(255, 255, 255, 0.15);
+ box-shadow: 0 14px 40px rgba(0, 0, 0, 0.55);
font-family: 'Chakra Petch', sans-serif;
- font-size: clamp(2rem, 5vw, 3.5rem);
+}
+
+.mapa-tip-titulo {
+ font-size: 0.95rem;
font-weight: 700;
color: white;
- margin: 0 0 16px 0;
- line-height: 1.1;
- text-shadow:
- 0 4px 20px rgba(0, 0, 0, 0.8),
- 0 2px 4px rgba(0, 0, 0, 0.5);
- letter-spacing: -0.02em;
+ margin-bottom: 2px;
+ line-height: 1.25;
}
-/* Metadatos estilo streaming */
-.modal-meta {
- display: flex;
- align-items: center;
- gap: 16px;
- margin-bottom: 20px;
- flex-wrap: wrap;
+.mapa-tip-cat {
+ font-size: 0.72rem;
+ font-weight: 600;
+ letter-spacing: 0.06em;
+ text-transform: uppercase;
+ margin-bottom: 8px;
}
-.modal-meta-item {
- font-family: 'Chakra Petch', sans-serif;
- font-size: 0.9rem;
- color: rgba(255, 255, 255, 0.7);
- display: flex;
- align-items: center;
- gap: 6px;
+.mapa-tip-premio {
+ font-size: 0.78rem;
+ color: #ffd97a;
+ margin-bottom: 6px;
}
-.modal-meta-badge {
- padding: 4px 10px;
- background: rgba(255, 255, 255, 0.15);
- border-radius: 4px;
+.mapa-tip-desc {
font-size: 0.8rem;
- font-weight: 600;
- color: white;
- border: 1px solid rgba(255, 255, 255, 0.2);
-}
-
-/* Descripción corta / tagline */
-.modal-tagline {
- font-family: 'Chakra Petch', sans-serif;
- font-size: 1.1rem;
- font-style: italic;
- color: rgba(255, 255, 255, 0.85);
- margin: 0 0 16px 0;
- line-height: 1.5;
+ color: rgba(255, 255, 255, 0.78);
+ line-height: 1.45;
+ margin-bottom: 10px;
}
-/* Acciones principales */
-.modal-actions {
+.mapa-tip-peso {
display: flex;
align-items: center;
- gap: 12px;
- margin-top: 24px;
- flex-wrap: wrap;
-}
-
-.modal-btn-primary {
- display: inline-flex;
- align-items: center;
- gap: 10px;
- padding: 14px 32px;
- background: white;
- border: none;
- border-radius: 8px;
- color: #0a0a14;
- font-family: 'Chakra Petch', sans-serif;
- font-weight: 700;
- font-size: 1rem;
- text-decoration: none;
- cursor: pointer;
- transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
-}
-
-.modal-btn-primary:hover {
- transform: scale(1.05);
- box-shadow: 0 8px 30px rgba(255, 255, 255, 0.3);
-}
-
-.modal-btn-primary svg {
- width: 20px;
- height: 20px;
-}
-
-.modal-btn-secondary {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- width: 48px;
- height: 48px;
- background: rgba(255, 255, 255, 0.1);
- backdrop-filter: blur(10px);
- -webkit-backdrop-filter: blur(10px);
- border: 1px solid rgba(255, 255, 255, 0.2);
- border-radius: 50%;
- color: white;
- cursor: pointer;
- transition: all 0.3s ease;
-}
-
-.modal-btn-secondary:hover {
- background: rgba(255, 255, 255, 0.2);
- border-color: rgba(255, 255, 255, 0.4);
- transform: scale(1.1);
-}
-
-.modal-btn-secondary svg {
- width: 22px;
- height: 22px;
+ gap: 8px;
+ font-size: 0.68rem;
+ color: rgba(255, 255, 255, 0.55);
+ text-transform: uppercase;
+ letter-spacing: 0.05em;
+ margin-bottom: 10px;
}
-/* Cuerpo del modal con detalles */
-.modal-body {
+.mapa-tip-barra {
flex: 1;
- padding: 0 48px 40px 48px;
- background: rgba(10, 10, 20, 1);
-}
-
-/* Descripción del proyecto */
-.modal-description {
- max-width: 800px;
- margin-bottom: 24px;
-}
-
-.modal-description:empty {
- display: none;
- margin-bottom: 0;
+ height: 4px;
+ border-radius: 2px;
+ background: rgba(255, 255, 255, 0.12);
+ overflow: hidden;
}
-.modal-description-text {
- font-family: 'Chakra Petch', sans-serif;
- font-size: 1rem;
- color: rgba(255, 255, 255, 0.85);
- line-height: 1.7;
- margin: 0;
+.mapa-tip-barra i {
+ display: block;
+ height: 100%;
+ border-radius: 2px;
}
-/* Tecnologías / Tags */
-.modal-tecnologias {
+.mapa-tip-techs {
display: flex;
flex-wrap: wrap;
- gap: 10px;
- margin-top: 20px;
-}
-
-.modal-tecnologias:empty {
- display: none;
- margin-top: 0;
-}
-
-.modal-tech-tag {
- font-family: 'Chakra Petch', sans-serif;
- font-size: 0.8rem;
- font-weight: 500;
- padding: 8px 16px;
- background: rgba(147, 197, 253, 0.15);
- border: 1px solid rgba(147, 197, 253, 0.3);
- border-radius: 20px;
- color: rgba(200, 220, 255, 0.95);
- letter-spacing: 0.02em;
- transition: all 0.3s ease;
-}
-
-.modal-tech-tag:hover {
- background: rgba(147, 197, 253, 0.25);
- border-color: rgba(147, 197, 253, 0.5);
- transform: translateY(-2px);
-}
-
-/* Contenido HTML del proyecto */
-.modal-contenido {
- font-family: 'Chakra Petch', sans-serif;
- color: rgba(255, 255, 255, 0.85);
- line-height: 1.7;
- margin-top: 28px;
- padding-top: 28px;
- border-top: 1px solid rgba(255, 255, 255, 0.1);
-}
-
-.modal-contenido:empty {
- display: none;
- margin-top: 0;
- padding-top: 0;
- border-top: none;
-}
-
-.modal-contenido h3 {
- font-size: 1.3rem;
- font-weight: 700;
- color: white;
- margin: 0 0 16px 0;
-}
-
-.modal-contenido h4 {
- font-size: 1.05rem;
- font-weight: 600;
- color: rgba(200, 220, 255, 1);
- margin: 24px 0 12px 0;
-}
-
-.modal-contenido p {
- margin: 0 0 16px 0;
- color: rgba(255, 255, 255, 0.8);
-}
-
-.modal-contenido ul, .modal-contenido ol {
- margin: 0 0 16px 0;
- padding-left: 24px;
-}
-
-.modal-contenido li {
- margin-bottom: 8px;
- color: rgba(255, 255, 255, 0.8);
-}
-
-.modal-contenido strong {
- color: rgba(147, 197, 253, 1);
- font-weight: 600;
+ gap: 4px;
}
-.modal-contenido code {
- font-family: 'JetBrains Mono', monospace;
- font-size: 0.85em;
- background: rgba(0, 0, 0, 0.4);
+.mapa-tip-tech {
+ font-size: 0.68rem;
padding: 2px 8px;
- border-radius: 4px;
- color: rgba(196, 181, 253, 1);
-}
-
-.modal-contenido pre {
- background: rgba(0, 0, 0, 0.5);
- border: 1px solid rgba(255, 255, 255, 0.1);
- border-radius: 12px;
- padding: 16px;
- overflow-x: auto;
- margin: 16px 0;
-}
-
-.modal-contenido pre code {
- background: none;
- padding: 0;
-}
-
-.modal-contenido blockquote {
- margin: 20px 0;
- padding: 16px 20px;
- background: linear-gradient(135deg, rgba(147, 197, 253, 0.1), rgba(196, 181, 253, 0.08));
- border-left: 4px solid rgba(147, 197, 253, 0.6);
- border-radius: 0 12px 12px 0;
- font-style: italic;
- color: rgba(255, 255, 255, 0.9);
+ border-radius: 6px;
+ border: 1px solid rgba(147, 197, 253, 0.25);
+ background: rgba(147, 197, 253, 0.08);
+ color: #bfdbfe;
}
-.modal-contenido img {
- max-width: 100%;
- border-radius: 12px;
- margin: 16px 0;
- box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
+/* Leyenda bajo el mapa */
+.mapa-leyenda {
+ font-family: 'Chakra Petch', sans-serif;
+ font-size: 0.75rem;
+ color: rgba(255, 255, 255, 0.45);
+ text-align: center;
+ margin: 14px auto 0;
+ max-width: 600px;
+ line-height: 1.5;
}
/* ============================================
@@ -962,10 +469,6 @@
.proyecto-titulo {
font-size: 0.65rem;
}
-
- .proyectos-grid-list {
- grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
- }
}
@media (max-width: 1024px) {
@@ -993,43 +496,6 @@
width: 38px;
height: 38px;
}
-
- .aptitud-header {
- padding: 20px;
- gap: 16px;
- }
-
- .aptitud-icono {
- width: 60px;
- height: 60px;
- }
-
- .aptitud-titulo {
- font-size: 1.3rem;
- }
-
- .aptitud-descripcion {
- font-size: 0.85rem;
- }
-
- .modal-backdrop {
- height: 58%;
- }
-
- .modal-hero {
- padding: 30vh 32px 24px 32px;
- gap: 24px;
- min-height: 50vh;
- }
-
- .modal-poster-container {
- width: 200px;
- height: 200px;
- }
-
- .modal-body {
- padding: 0 32px 32px 32px;
- }
}
@media (max-width: 768px) {
@@ -1072,165 +538,23 @@
max-width: 70px;
}
- .proyectos-content {
- padding: 0 16px 6vh;
- gap: 8vh;
- }
-
- .proyectos-grid-list {
- grid-template-columns: 1fr;
- gap: 16px;
- }
-
- .aptitud-header {
- flex-direction: column;
- text-align: center;
- padding: 20px;
- gap: 14px;
+ .proyectos-mapa {
+ padding: 0 14px 6vh;
}
- .aptitud-icono {
- width: 55px;
- height: 55px;
- }
-
- .aptitud-icono img {
- width: 28px;
- height: 28px;
- }
-
- .aptitud-titulo {
- font-size: 1.2rem;
- }
-
- .proyecto-detail-card {
- flex-direction: column;
- }
-
- .proyecto-image-container {
- height: 160px;
- }
-
- .proyecto-info-wrapper {
- padding: 16px;
- }
-
- .proyecto-detail-titulo {
- font-size: 1.1rem;
- }
-
- .proyecto-detail-desc {
- font-size: 0.85rem;
- }
-
- /* Modal responsive */
- .proyecto-modal-overlay {
- padding: 12px;
- align-items: flex-start;
- padding-top: 40px;
- }
-
- .proyecto-modal {
- max-height: 88vh;
- border-radius: 16px;
- }
-
- .modal-backdrop {
- border-radius: 16px 16px 0 0;
- height: 54%;
- }
-
- .modal-hero {
- flex-direction: column;
- align-items: center;
- text-align: center;
- padding: 8vh 20px 14px 20px;
- gap: 16px;
- min-height: auto;
- }
-
- .modal-poster-container {
- width: 160px;
- height: 160px;
- }
-
- .modal-hero-info {
- display: flex;
- flex-direction: column;
- align-items: center;
- }
-
- .modal-titulo {
- font-size: 1.6rem;
- text-align: center;
- line-height: 1.2;
- margin-bottom: 12px;
- }
-
- .modal-meta {
- justify-content: center;
- font-size: 0.85rem;
- gap: 12px;
- }
-
- .modal-meta-badge {
- font-size: 0.75rem;
- padding: 3px 8px;
- }
-
- .modal-tagline {
- text-align: center;
- font-size: 0.95rem;
- line-height: 1.4;
- }
-
- .modal-actions {
- justify-content: center;
- margin-top: 16px;
- }
-
- .modal-btn-primary {
- padding: 12px 24px;
- font-size: 0.9rem;
- }
-
- .modal-btn-secondary {
- width: 44px;
- height: 44px;
- }
-
- .modal-body {
- padding: 0 20px 24px 20px;
- }
-
- .modal-description {
- text-align: left;
- }
-
- .modal-description-text {
- font-size: 0.9rem;
- line-height: 1.6;
- }
-
- .modal-tecnologias {
- justify-content: center;
- gap: 8px;
- }
-
- .modal-tech-tag {
- font-size: 0.75rem;
- padding: 6px 12px;
+ .mapa-panel {
+ border-radius: 20px;
+ padding: 10px;
}
- .modal-contenido {
- font-size: 0.9rem;
+ .mapa-pill {
+ padding: 7px 14px;
+ font-size: 0.78rem;
}
- .modal-close {
- top: 10px;
- right: 10px;
- width: 40px;
- height: 40px;
+ .mapa-tip {
+ width: 200px;
+ padding: 12px 14px;
}
}
@@ -1272,140 +596,26 @@
display: none;
}
- .proyectos-content {
- padding: 0 12px 5vh;
- gap: 6vh;
- }
-
- .aptitud-icono {
- width: 48px;
- height: 48px;
- }
-
- .aptitud-icono img {
- width: 24px;
- height: 24px;
- }
-
- .aptitud-titulo {
- font-size: 1.05rem;
- }
-
- .aptitud-descripcion {
- font-size: 0.8rem;
- }
-
- .proyecto-detail-card {
- flex-direction: column;
- border-radius: 14px;
+ .proyectos-mapa {
+ padding: 0 10px 5vh;
}
- .proyecto-image-container {
- height: 140px;
+ .mapa-pills {
+ gap: 7px;
+ margin-bottom: 16px;
}
- .proyecto-info-wrapper {
- padding: 14px;
- }
-
- .proyecto-detail-titulo {
- font-size: 0.95rem;
- }
-
- .proyecto-detail-desc {
- font-size: 0.8rem;
+ .mapa-pill {
+ padding: 6px 12px;
+ font-size: 0.72rem;
}
- /* Modal extra small */
- .proyecto-modal-overlay {
+ .mapa-panel {
+ border-radius: 16px;
padding: 8px;
- padding-top: 30px;
- }
-
- .proyecto-modal {
- max-height: 90vh;
- border-radius: 12px;
- }
-
- .modal-backdrop {
- border-radius: 12px 12px 0 0;
- height: 40%;
- }
-
- .modal-hero {
- padding: 15vh 16px 16px 16px;
- gap: 12px;
- }
-
- .modal-poster-container {
- width: 140px;
- height: 140px;
- }
-
- .modal-titulo {
- font-size: 1.35rem;
- margin-bottom: 8px;
- }
-
- .modal-meta {
- font-size: 0.8rem;
- gap: 10px;
- }
-
- .modal-meta-badge {
- font-size: 0.7rem;
- padding: 2px 6px;
- }
-
- .modal-tagline {
- font-size: 0.85rem;
- line-height: 1.4;
- }
-
- .modal-actions {
- margin-top: 12px;
- gap: 10px;
- }
-
- .modal-btn-primary {
- padding: 10px 20px;
- font-size: 0.85rem;
- }
-
- .modal-btn-secondary {
- width: 40px;
- height: 40px;
- }
-
- .modal-body {
- padding: 0 16px 20px 16px;
- }
-
- .modal-description-text {
- font-size: 0.85rem;
- }
-
- .modal-tech-tag {
- font-size: 0.7rem;
- padding: 5px 10px;
- }
-
- .modal-contenido {
- font-size: 0.85rem;
- }
-
- .modal-contenido h3 {
- font-size: 1.1rem;
- }
-
- .modal-contenido h4 {
- font-size: 0.95rem;
}
- .modal-close {
- width: 36px;
- height: 36px;
- top: 8px;
- right: 8px;
+ .mapa-leyenda {
+ font-size: 0.68rem;
}
}
From be479338238a7fbdf2c4f66c29aa668dc93199fe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Garc=C3=ADa=20Santamar=C3=ADa?=
<69808296+PGSCOM@users.noreply.github.com>
Date: Thu, 11 Jun 2026 12:21:52 +0200
Subject: [PATCH 33/49] =?UTF-8?q?Cambio=20en=20la=20secci=C3=B3n=20de=20pr?=
=?UTF-8?q?oyectos?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
package-lock.json | 177 ------------
package.json | 4 -
src/pages/index.astro | 14 +-
src/pages/proyectos/[id].astro | 6 +-
src/scripts/hero.js | 4 +-
src/scripts/preloader.js | 2 +-
src/scripts/proyectos-burbujas.js | 458 ------------------------------
src/scripts/proyectos-panal.js | 446 +++++++++++++++++++++++++++++
src/styles/proyectos.css | 12 +-
9 files changed, 467 insertions(+), 656 deletions(-)
delete mode 100644 src/scripts/proyectos-burbujas.js
create mode 100644 src/scripts/proyectos-panal.js
diff --git a/package-lock.json b/package-lock.json
index a8e1cf2..b409b69 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,11 +12,7 @@
"@types/react": "^19.1.16",
"@types/react-dom": "^19.1.9",
"astro": "^5.15.1",
- "d3-drag": "^3.0.0",
- "d3-force": "^3.0.0",
- "d3-scale": "^4.0.2",
"d3-selection": "^3.0.0",
- "d3-transition": "^3.0.1",
"gsap": "^3.15.0",
"liquid-glass-react": "^1.1.1",
"react": "^19.1.1",
@@ -2453,118 +2449,6 @@
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"license": "MIT"
},
- "node_modules/d3-array": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
- "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
- "license": "ISC",
- "dependencies": {
- "internmap": "1 - 2"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-color": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
- "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-dispatch": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
- "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-drag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz",
- "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==",
- "license": "ISC",
- "dependencies": {
- "d3-dispatch": "1 - 3",
- "d3-selection": "3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-ease": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
- "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-force": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz",
- "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==",
- "license": "ISC",
- "dependencies": {
- "d3-dispatch": "1 - 3",
- "d3-quadtree": "1 - 3",
- "d3-timer": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-format": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz",
- "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-interpolate": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
- "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
- "license": "ISC",
- "dependencies": {
- "d3-color": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-quadtree": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz",
- "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-scale": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
- "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
- "license": "ISC",
- "dependencies": {
- "d3-array": "2.10.0 - 3",
- "d3-format": "1 - 3",
- "d3-interpolate": "1.2.0 - 3",
- "d3-time": "2.1.1 - 3",
- "d3-time-format": "2 - 4"
- },
- "engines": {
- "node": ">=12"
- }
- },
"node_modules/d3-selection": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
@@ -2574,58 +2458,6 @@
"node": ">=12"
}
},
- "node_modules/d3-time": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
- "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
- "license": "ISC",
- "dependencies": {
- "d3-array": "2 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-time-format": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
- "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
- "license": "ISC",
- "dependencies": {
- "d3-time": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-timer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
- "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-transition": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz",
- "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==",
- "license": "ISC",
- "dependencies": {
- "d3-color": "1 - 3",
- "d3-dispatch": "1 - 3",
- "d3-ease": "1 - 3",
- "d3-interpolate": "1 - 3",
- "d3-timer": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- },
- "peerDependencies": {
- "d3-selection": "2 - 3"
- }
- },
"node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
@@ -3242,15 +3074,6 @@
"url": "https://github.com/sponsors/wooorm"
}
},
- "node_modules/internmap": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
- "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
"node_modules/iron-webcrypto": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz",
diff --git a/package.json b/package.json
index 40f2b98..f23e3dd 100644
--- a/package.json
+++ b/package.json
@@ -13,11 +13,7 @@
"@types/react": "^19.1.16",
"@types/react-dom": "^19.1.9",
"astro": "^5.15.1",
- "d3-drag": "^3.0.0",
- "d3-force": "^3.0.0",
- "d3-scale": "^4.0.2",
"d3-selection": "^3.0.0",
- "d3-transition": "^3.0.1",
"gsap": "^3.15.0",
"liquid-glass-react": "^1.1.1",
"react": "^19.1.1",
diff --git a/src/pages/index.astro b/src/pages/index.astro
index 64f042a..0e417e1 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -142,7 +142,7 @@ const burbujasData = {
Portfolio de Pablo García Santamaría — proyectos de código, cine y diseño.