feat: calendario gancio-calendar + horarios semanales + mejoras CSS

- Integra gancio-calendar desde mad.convoca.la (place ID 42, CSO La Enredadera)
- Añade calendario semanal de colectivos debajo del gancio con pills de colores
- Corrige ID del lugar: 42 (no 286) confirmado via API
- Tema light + custom properties --calendar-* para colores blanco/negro/rosa
- Sidebar más compacto en móvil (65vw/220px), nav con fuente Impact uppercase
- Leyenda más grande y legible (0.75rem, puntos 16px)
- Márgenes 25px izquierda / 10px derecha en calendario semanal
- Añade context.txt con guía completa de despliegue y referencias técnicas
- Elimina botón "Calendario" redundante y espacio entre nav y calendario

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
SITO 2026-04-09 00:09:34 +02:00
parent 976e45f156
commit f3823c4c53
3 changed files with 265 additions and 68 deletions

132
context.txt Normal file
View file

@ -0,0 +1,132 @@
================================================================================
CSO LA ENREDADERA DE TETUÁN — CONTEXTO Y DESPLIEGUE
laenre.net
================================================================================
REPOSITORIO
-----------
Git: https://gitea.laenre.net/hacklab/ENRE_WEB.git
Usuario: hacklab
Rama principal: main
ESTRUCTURA DE ARCHIVOS
----------------------
index.html → Página principal (calendario + secciones de colectivos)
index.css → Estilos globales
convocala.html → Página de eventos embebida con gancio-calendar
calendario.html → Calendario semanal manual (referencia, no enlazado desde nav)
Code462WPink-Regular.ttf → Fuente personalizada del título
INFO/ → Imágenes de colectivos (logos, fotos)
subdir/ → Páginas secundarias (sobre_nosotrxs.html, campa.html...)
DEPENDENCIAS EXTERNAS (CDN, sin instalar nada)
----------------------------------------------
- Google Fonts: Rock Salt, Anton
https://fonts.googleapis.com/css2?family=Rock+Salt&display=swap
https://fonts.googleapis.com/css2?family=Anton&display=swap
- Gancio Calendar web component (desarrollado por CSO La Rosa):
https://rosa.frama.io/gancio-calendar/gancio-calendar.js
Repo: https://framagit.org/rosa/gancio-calendar
Playground: https://rosa.frama.io/gancio-calendar/
- Fuente de datos de eventos: mad.convoca.la (instancia Gancio Madrid)
Lugar: CSOA La Enredadera de Tetuán
ID en mad.convoca.la: 42
URL pública: https://mad.convoca.la/place/CSO%20La%20Enredadera
API que usa el widget: https://mad.convoca.la/api/events?places=42
CÓMO FUNCIONA EL CALENDARIO
----------------------------
El calendario de index.html usa el web component <gancio-calendar>:
<script type="module"
src="https://rosa.frama.io/gancio-calendar/gancio-calendar.js"></script>
<gancio-calendar
baseurl="https://mad.convoca.la"
places="42"
accent_color="#ff00aa"
locale="es-ES"
theme="default">
</gancio-calendar>
- places="42" → filtra eventos del CSOA La Enredadera
- accent_color="#ff00aa" → rosa fucsia corporativo
- Los eventos se publican en mad.convoca.la y aparecen aquí automáticamente
- Guía para publicar eventos: https://convoca.la/mad/guias/publicar_evento
convocala.html es una página dedicada con el mismo widget + botones de acción
y enlace a la guía de publicación.
PALETA DE COLORES
-----------------
Rosa fucsia: #ff00aa (color principal, botones, bordes)
Negro: #000000 (sidebar, fondos de títulos)
Blanco: #ffffff (fondo secciones)
Fuente: Impact / Anton (nav, calendario)
Rock Salt (cuerpo general)
Code462WPink (título h1)
DESPLIEGUE EN EL SERVIDOR
--------------------------
La web es HTML/CSS estático, no necesita backend ni build.
1. Clonar el repo en el servidor:
git clone https://hacklab@gitea.laenre.net/hacklab/ENRE_WEB.git
2. Servir el directorio raíz con cualquier servidor web estático:
- Nginx: apuntar document_root al directorio clonado
- Apache: igual
- Caddy: igual
- Para pruebas locales: python3 -m http.server 8080
3. Actualizar desde el repo (sin reiniciar nada):
git pull
IMPORTANTE: La web necesita servirse desde un servidor HTTP real
(no abrir index.html directamente como archivo) porque:
- Las fuentes locales usan rutas absolutas (/Code462WPink-Regular.ttf)
- El web component gancio-calendar necesita hacer fetch a mad.convoca.la
(requiere contexto HTTP para CORS)
SERVIDOR LOCAL PARA PRUEBAS
----------------------------
cd /home/sito/COFRE/NETACTIVIST/ENRE_WEB
python3 -m http.server 8080
→ Abrir http://localhost:8080
NGINX (ejemplo mínimo)
----------------------
server {
listen 80;
server_name laenre.net www.laenre.net;
root /var/www/ENRE_WEB;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
REDES SOCIALES Y CONTACTO
--------------------------
Email: enredadera@riseup.net
Mastodon: https://masto.es/@csolaenre
Instagram: https://www.instagram.com/la_enredadera_de_tetuan/
Hacklab: https://hacklab.laenre.net
Okupanel: https://okupanel.laenre.net
NOTAS TÉCNICAS
--------------
- El ID del lugar en mad.convoca.la es 42 (no confundir con 286 que
corresponde a otro lugar. Se confirmó via API: /api/events?places=42
devuelve los eventos correctos de La Enredadera)
- La rama "pruebas-calendario" en el repo local contiene una versión
anterior con el calendario semanal manual (JS puro, sin gancio).
Se puede recuperar si se quiere volver a ese enfoque.
- El bot de reenvío a Mastodon/Bluesky está pendiente de configurar.
Cuando esté disponible, añadirlo a la sección de difusión en convocala.html
================================================================================

120
index.css
View file

@ -147,7 +147,7 @@ main {
margin-left: var(--sidebar-w);
transition: margin-left .25s ease;
flex-grow: 1;
padding: 0 16px 0 20px; /* 20px izquierda para separar del sidebar */
padding: 0;
text-align: center;
font-size: 0.9em;
}
@ -155,7 +155,7 @@ main {
header {
background: #ff00aa;
color: white;
padding: 1px;
padding: 6px 16px 4px 20px;
font-size: 2em;
}
@ -243,6 +243,21 @@ section{
line-height: 1.6;
}
/* El calendario va pegado al header, sin margen ni padding extra */
section#agenda {
margin: 0;
padding: 0 0 0 8px;
border: none;
border-radius: 0;
box-shadow: none;
background: transparent;
}
/* Calendario semanal: margen 25px izquierda, 10px derecha */
section#agenda-semanal {
margin: 10px 10px 10px 25px;
}
section#feminismos{
padding-left: 16px;
padding-right: 16px;
@ -530,86 +545,93 @@ button:hover {
.cal-legend {
display: flex;
flex-wrap: wrap;
gap: 5px 14px;
margin: 10px 0 2px;
gap: 8px 20px;
margin: 14px 0 6px;
justify-content: center;
}
.cal-legend-item {
display: flex;
align-items: center;
gap: 5px;
font-size: 0.55rem;
gap: 7px;
font-size: 0.75rem;
font-family: var(--impact);
letter-spacing: .5px;
}
.cal-legend-dot {
width: 11px;
height: 11px;
border-radius: 3px;
width: 16px;
height: 16px;
border-radius: 4px;
flex-shrink: 0;
border: 1px solid rgba(0,0,0,.12);
border: 1px solid rgba(0,0,0,.15);
}
/* ========== TELÉFONOS PEQUEÑOS (<= 480px) ========== */
@media (max-width: 480px){
html{ font-size: 9px; } /* baja toda la escala */
body{ overflow-x: hidden; }
body{ overflow-x: hidden; flex-direction: column; }
.vertical-marquee{ display:none !important; }
body{ flex-direction: column; overflow-x: hidden; }
.container{ width:100%; position: relative; }
main{ margin-left: 0 !important; font-size: 1rem; }
header{ padding: 16px 12px; padding-left:20px; font-size: 1.05em; }
main{ margin-left: 0 !important; font-size: 1rem; padding: 0; }
header{ padding: 10px 12px 6px; font-size: 1em; }
/* Hamburguesa + sidebar superpuesta */
header h1{ font-size: clamp(1rem, 6vw, 1.4rem); margin: 2px 0 4px; }
/* Hamburguesa */
.sb-toggle{ display:flex; }
/* Sidebar: ancho moderado, no ocupa toda la pantalla */
.sidebar{
position: fixed; left: 0; top: 0; bottom: 0;
width: min(82vw, 300px);
width: min(65vw, 220px);
transform: translateX(-100%);
z-index: 1000; overflow-y:auto; padding:20px;
z-index: 1000; overflow-y: auto; padding: 16px 14px;
}
.sidebar h2{ font-size: 1.3rem; margin-top: 6px; }
.sidebar p{ font-size: 0.75rem; }
.sidebar .sidebar-nav ul{ margin-top: 20px; gap: 7px; }
.sidebar .sidebar-nav a{ font-size: 0.95rem; padding: 9px 10px; }
#nav-toggle:checked ~ .container .sidebar{ transform: translateX(0); }
#nav-toggle:checked ~ .container::before{
content:""; position:fixed; inset:0; background:rgba(0,0,0,.45); z-index:999;
}
/* Nav superior: 2 filas, botones más compactos */
.top-nav ul, .top-nav.second ul{
/* Nav superior: chips compactos en 2-3 filas */
.top-nav ul{
display: flex;
flex-wrap: wrap;
justify-content: center;
gap:6px;
padding:0 6px;
margin:10px 0 0;
}
.top-nav li, .top-nav.second li{
list-style:none;
gap: 5px 6px;
padding: 6px 8px 8px;
margin: 0;
width:auto;
flex:0 0 auto;
}
.top-nav li{ list-style: none; }
.top-nav a, .top-nav.second a, .top-nav2 a{
display: inline-block;
padding:5px 10px;
font-size:.8rem;
padding: 4px 10px;
font-size: .72rem;
font-family: Impact, 'Anton', sans-serif;
letter-spacing: 1px;
letter-spacing: .8px;
text-transform: uppercase;
line-height:1.1;
line-height: 1.2;
border: 2px solid transparent;
border-radius:16px;
border-radius: 14px;
background: #fff;
color: #000;
text-decoration: none;
white-space: nowrap;
}
.top-nav a:active{ border-color: #ff00aa; color: #ff00aa; }
/* Gancio en móvil: ancho completo */
gancio-calendar{ width: 100%; margin-left: 0; }
/* Secciones y contenido */
section{ margin:12px 0; padding:12px; border-radius:10px; }
section h2{ font-size:2rem; }
section{ margin: 10px 8px; padding: 12px; border-radius: 10px; }
section h2{ font-size: 1.1rem; }
.content-page.readable{ max-width:100%; margin:16px auto 36px; padding:14px; font-size:1rem; line-height:1.7; }
button{ font-size:.9em; padding:8px 12px; }
footer{ font-size:.85em; padding:14px 0; }
footer{ font-size:.85em; padding:14px 8px; }
/* ====== CALENDARIO móvil ====== */
.cal{ border-radius:8px; }
@ -648,11 +670,13 @@ button:hover {
.sb-toggle{ display:flex; }
.sidebar{
position: fixed; left:0; top:0; bottom:0;
width: min(78vw, 320px);
width: min(55vw, 240px);
background:#000; color:#fff;
transform: translateX(-100%);
z-index:1000; overflow-y:auto; padding:20px;
z-index:1000; overflow-y:auto; padding:18px 14px;
}
.sidebar h2{ font-size: 1.4rem; }
.sidebar .sidebar-nav a{ font-size: 1rem; padding: 10px 10px; }
#nav-toggle:checked ~ .container .sidebar{ transform: translateX(0); }
#nav-toggle:checked ~ .container::before{
content:""; position:fixed; inset:0; background:rgba(0,0,0,.45); z-index:999;
@ -689,6 +713,26 @@ button:hover {
.cal-head-cell{ padding:7px 1px; font-size:.75rem; }
}
/* ====== GANCIO-CALENDAR: colores de la Enredadera ====== */
gancio-calendar {
display: block;
width: calc(100% - 70px);
margin-left: 35px;
/* Fondo blanco, texto negro, líneas y acentos rosa fucsia */
--calendar-surface: #ffffff; /* fondo principal */
--calendar-surface-alt: #fff6fc; /* fondo alternativo (días fuera de mes, etc.) */
--calendar-text: #111111; /* texto principal */
--calendar-muted: #555555; /* texto secundario/hora */
--calendar-accent: #ff00aa; /* color de acento (hoy, selección) */
--calendar-border: #ff00aa; /* líneas del grid */
--calendar-event-divider: #ffaadd; /* separador entre eventos */
--calendar-chip-bg: #ff00aa; /* fondo de chips/tags */
--calendar-chip-text: #000000; /* texto de chips/tags */
--calendar-chip-border: #cc0088; /* borde de chips */
--calendar-shadow: rgba(255,0,170,.12); /* sombra */
}
/* ========== TABLETS HORIZONTALES / PORTÁTILES PEQUEÑOS (769px1024px) ========== */
@media (min-width: 769px) and (max-width: 1024px){

View file

@ -6,6 +6,8 @@
<title>La Enredadera de Tetuán</title>
<link rel="preload" href="/Code462WPink-Regular.ttf" as="font" type="font/ttf">
<link rel="stylesheet" href="/index.css">
<!-- Web component gancio-calendar (CSO La Rosa) https://framagit.org/rosa/gancio-calendar -->
<script type="module" src="https://rosa.frama.io/gancio-calendar/gancio-calendar.js"></script>
</head>
<body>
<input type="checkbox" id="nav-toggle" class="sr-only">
@ -63,25 +65,46 @@
</header>
<!-- CALENDARIO MENSUAL -->
<section id="agenda" class="panel" aria-label="Calendario mensual">
<h2>Calendario</h2>
<!-- CALENDARIO: gancio-calendar embebido desde mad.convoca.la -->
<section id="agenda" class="panel" aria-label="Calendario de eventos">
<div class="cal-controls" role="group" aria-label="Navegación de mes">
<button class="button cal-prev" type="button" aria-label="Mes anterior">&larr;</button>
<div class="cal-title" aria-live="polite"></div>
<button class="button cal-next" type="button" aria-label="Mes siguiente">&rarr;</button>
<!--
places="286" = ID de CSO La Enredadera en mad.convoca.la
https://mad.convoca.la/place/CSO%20La%20Enredadera
-->
<gancio-calendar
baseurl="https://mad.convoca.la"
title="Agenda de La Enredadera de Tetuán"
instance_name="mad.convoca.la"
instance_description="Agenda activista y cultural de Tetuán"
locale="es-ES"
places="42"
accent_color="#ff00aa"
theme="light">
</gancio-calendar>
</section>
<!-- CALENDARIO SEMANAL DE COLECTIVOS -->
<section id="agenda-semanal" aria-label="Horarios semanales de colectivos">
<h2>Horarios Semanales</h2>
<div class="cal-controls" id="semanal-controls" role="group" aria-label="Navegación de mes">
<button class="button semanal-prev" type="button" aria-label="Mes anterior">&larr;</button>
<div class="cal-title semanal-title" aria-live="polite"></div>
<button class="button semanal-next" type="button" aria-label="Mes siguiente">&rarr;</button>
</div>
<div class="cal" id="cal-root"></div>
<div class="cal-legend" id="cal-legend-root"></div>
<div class="cal" id="semanal-root"></div>
<div class="cal-legend" id="semanal-legend-root"></div>
<script>
(function () {
const monthNames = ['Enero','Febrero','Marzo','Abril','Mayo','Junio','Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'];
const weekdayNames = ['L','M','X','J','V','S','D'];
const ENRE_EVENTS_URL = 'https://mad.convoca.la/place/286/CSO%20La%20Enredadera';
const ENRE_EVENTS_URL = 'https://mad.convoca.la/place/42/CSO%20La%20Enredadera';
const COLORS = {
hacklab: { bg:'#39FF14', fg:'#000', label:'Hacklab' },
@ -138,11 +161,11 @@
cell.appendChild(wrap);
}
const root = document.getElementById('cal-root');
const legend = document.getElementById('cal-legend-root');
const title = document.querySelector('.cal-title');
const btnPrev = document.querySelector('.cal-prev');
const btnNext = document.querySelector('.cal-next');
const root = document.getElementById('semanal-root');
const legend = document.getElementById('semanal-legend-root');
const title = document.querySelector('.semanal-title');
const btnPrev = document.querySelector('.semanal-prev');
const btnNext = document.querySelector('.semanal-next');
const today = new Date();
let view = new Date();
@ -164,7 +187,6 @@
const secondFri = fridays[1];
const lastFri = fridays[fridays.length - 1];
// Cabecera
const head = document.createElement('div');
head.className = 'cal-row cal-head';
weekdayNames.forEach(w => {
@ -175,7 +197,6 @@
});
root.appendChild(head);
// Grid 6×7
let day = 1 - startIndex;
for (let r = 0; r < 6; r++) {
const row = document.createElement('div');