gioser

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

TOML 1373Shell 116Rust 74Markdown 641915 Definitions

sitio: pestañas sin artículos, la ficha del sistema con la observación debajo, y deslizar entre pestañas

Las pestañas entraban justas al pegarse arriba: pasan a «Descargar ·
Decisiones · Componentes · Código». Y se vuelven a medir cuando la página
termina de cargar (imagen y fuentes), porque la primera vez trastabillaban.

La primera tabla de «Qué lleva dentro» tenía la tercera columna con el
encabezado vacío y se leía como si faltara: ahora es una ficha, pieza y
versión en una línea y la observación debajo de las dos. Las versiones largas
se parten antes que estirar la página en el teléfono.

Y en el teléfono se pasa de una pestaña a otra deslizando, como un PageView:
el panel sigue al dedo y entra el vecino desde ese lado. Lo que se desplaza de
costado (el diagrama, una tabla ancha) manda hasta llegar a su borde, y el
gesto horizontal se reclama para la página: sin eso Chrome lo tomaba como
«volver atrás» y el visitante se iba del sitio (medido: quedaba en about:blank).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

cbf144a410d1a9f61a856cb0a5c3c216fadfe57b · by sergio · (8 d ago) · parent b35d25b51 · browse the tree at this commit

Semantic delta

No definition changed: this change is text, documentation or data.

1 files · +60 −2

diff --git a/web/takana-os.net/index.html b/web/takana-os.net/index.html
index 5c1e6f71..00993d31 100644
--- a/web/takana-os.net/index.html
+++ b/web/takana-os.net/index.html
@@ -327,6 +327,30 @@ html.js .t-tarjeta .titular .simbolo{visibility:hidden}
 html.js .t-panel:not(.activo){display:none}
 html.js .t-panel.activo{animation:t-entra .4s ease both}
 @keyframes t-entra{from{opacity:0;transform:translateY(10px)}}
+/* La ficha del sistema (03): pieza y versión en una línea, y la observación DEBAJO de las dos —
+   una tercera columna con el encabezado vacío se leía como si faltara. Poco convencional para
+   una tabla, a propósito. */
+table.ficha{display:block;overflow:visible;border-top:1px solid var(--linea)}
+table.ficha thead tr,table.ficha tbody tr{display:grid;grid-template-columns:minmax(0,.8fr) minmax(0,1.7fr);
+ column-gap:1rem;border-bottom:1px solid var(--linea)}
+table.ficha th,table.ficha td{border:0;padding:.55rem .2rem}
+table.ficha th{background:none;font:500 .66rem/1.2 var(--mono);letter-spacing:.14em;text-transform:uppercase;color:var(--debil)}
+table.ficha th:nth-child(3){display:none}
+table.ficha td:first-child{color:var(--texto);font-weight:600}
+/* las versiones largas («PipeWire 1.2.7 · WirePlumber 0.5.15») se parten antes que estirar la página */
+table.ficha td.n{white-space:normal;overflow-wrap:anywhere}
+table.ficha td:nth-child(3){grid-column:1/-1;padding-top:0;font-size:.86rem;color:var(--debil)}
+
+/* Deslizar entre pestañas con el dedo, como un PageView: el panel sigue al dedo y, al soltar
+   pasado el umbral, entra el vecino desde ese lado. */
+/* El deslizamiento horizontal es de la página: sin esto Chrome lo toma como «volver atrás» y el
+   visitante se va del sitio queriendo ir a la pestaña anterior (medido: quedaba en about:blank). */
+html,body{overscroll-behavior-x:none}
+@keyframes t-desde-der{from{opacity:0;transform:translateX(48px)}}
+@keyframes t-desde-izq{from{opacity:0;transform:translateX(-48px)}}
+html.js .t-panel.activo.desde-der{animation:t-desde-der .32s cubic-bezier(.2,.8,.2,1) both}
+html.js .t-panel.activo.desde-izq{animation:t-desde-izq .32s cubic-bezier(.2,.8,.2,1) both}
+
 .t-panel.franja{border-top:0;padding-top:1.4rem}
 @media(max-width:720px){
  .t-tabs{justify-content:flex-start;overflow-x:auto;scrollbar-width:none;gap:.3rem}
@@ -390,7 +414,7 @@ html.js .t-panel.activo{animation:t-entra .4s ease both}
 <div class="t-cuerpo">
 <!-- El fondo vivo. `aria-hidden` porque no dice nada: es color. -->
 <div class="aurora" aria-hidden="true"><i></i><i></i><i></i></div>
-<div class="t-tabs" id="t-tabs" role="tablist" aria-label="secciones / sections"><button class="t-tab" role="tab" type="button" id="tab-descargar" data-tab="descargar" aria-controls="descargar" aria-selected="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 4v11M7 11l5 5 5-5M5 20h14"/></svg><span class="rot"><span data-l="es">Descargar</span><span data-l="en">Download</span></span></button><button class="t-tab" role="tab" type="button" id="tab-decisiones" data-tab="decisiones" aria-controls="decisiones" aria-selected="false"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3v18M5 7h14"/><path d="M8 7 5 13h6zM16 7l-3 6h6z"/></svg><span class="rot"><span data-l="es">Las decisiones</span><span data-l="en">The decisions</span></span></button><button class="t-tab" role="tab" type="button" id="tab-componentes" data-tab="componentes" aria-controls="componentes" aria-selected="false"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m12 3 8 4.5v9L12 21l-8-4.5v-9z"/><path d="m4 7.5 8 4.5 8-4.5M12 12v9"/></svg><span class="rot"><span data-l="es">Los componentes</span><span data-l="en">Components</span></span></button><button class="t-tab" role="tab" type="button" id="tab-codigo" data-tab="codigo" aria-controls="codigo" aria-selected="false"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 18 3 12l6-6M15 6l6 6-6 6"/></svg><span class="rot"><span data-l="es">El código</span><span data-l="en">The code</span></span></button></div>
+<div class="t-tabs" id="t-tabs" role="tablist" aria-label="secciones / sections"><button class="t-tab" role="tab" type="button" id="tab-descargar" data-tab="descargar" aria-controls="descargar" aria-selected="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 4v11M7 11l5 5 5-5M5 20h14"/></svg><span class="rot"><span data-l="es">Descargar</span><span data-l="en">Download</span></span></button><button class="t-tab" role="tab" type="button" id="tab-decisiones" data-tab="decisiones" aria-controls="decisiones" aria-selected="false"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3v18M5 7h14"/><path d="M8 7 5 13h6zM16 7l-3 6h6z"/></svg><span class="rot"><span data-l="es">Decisiones</span><span data-l="en">Decisions</span></span></button><button class="t-tab" role="tab" type="button" id="tab-componentes" data-tab="componentes" aria-controls="componentes" aria-selected="false"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m12 3 8 4.5v9L12 21l-8-4.5v-9z"/><path d="m4 7.5 8 4.5 8-4.5M12 12v9"/></svg><span class="rot"><span data-l="es">Componentes</span><span data-l="en">Components</span></span></button><button class="t-tab" role="tab" type="button" id="tab-codigo" data-tab="codigo" aria-controls="codigo" aria-selected="false"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 18 3 12l6-6M15 6l6 6-6 6"/></svg><span class="rot"><span data-l="es">Código</span><span data-l="en">Code</span></span></button></div>
 
 <section class="franja t-panel activo" id="descargar" role="tabpanel" aria-labelledby="tab-descargar"><div class="envoltura">
  <p class="sello"><svg class="simbolo" viewBox="0 0 748 748"><use href="#tocapu"/></svg><span data-l="es">01 · descargar</span><span data-l="en">01 · download</span></p>
@@ -668,7 +692,7 @@ html.js .t-panel.activo{animation:t-entra .4s ease both}
  <p class="sello"><svg class="simbolo" viewBox="0 0 748 748"><use href="#tocapu"/></svg><span data-l="es">03 · los componentes</span><span data-l="en">03 · the components</span></p>
  <h2><span data-l="es">Qué lleva dentro</span><span data-l="en">What is inside</span></h2>
 
- <table>
+ <table class="ficha">
   <thead><tr>
    <th><span data-l="es">pieza</span><span data-l="en">piece</span></th>
    <th><span data-l="es">versión</span><span data-l="en">version</span></th>
@@ -980,6 +1004,8 @@ html.js .t-panel.activo{animation:t-entra .4s ease both}
  addEventListener('resize',function(){medir();pintar()},{passive:true});
  medir(); pintar();
  if(document.fonts&&document.fonts.ready) document.fonts.ready.then(function(){medir();pintar()});
+ // y otra vez al terminar de cargar todo: la primera vez trastabillaba porque se medía antes
+ addEventListener('load',function(){medir();pintar()});
  document.getElementById('t-marca').addEventListener('click',function(e){ e.preventDefault(); scrollTo({top:0,behavior:quieto?'auto':'smooth'}); });
 
  function elegir(id, foco){
@@ -1001,6 +1027,38 @@ html.js .t-panel.activo{animation:t-entra .4s ease both}
    j=e.key==='ArrowRight'?(i+1)%n:e.key==='ArrowLeft'?(i-1+n)%n:e.key==='Home'?0:e.key==='End'?n-1:-1;
    if(j>=0){ e.preventDefault(); elegir(tabs[j].dataset.tab,true); } });
  });
+
+ // ── deslizar entre pestañas (como un PageView de Flutter) ──
+ function vecino(dir){ var i=tabs.findIndex(function(t){return t.getAttribute('aria-selected')==='true'}), j=i+dir;
+  return (j>=0&&j<tabs.length) ? tabs[j].dataset.tab : null; }
+ var x0=null, y0=0, dx=0, eje=null, panel=null, rueda=null;
+ // lo que bajo el dedo se desplaza de costado (un diagrama, una tabla ancha, un bloque de código)
+ function corre(el){ for(;el&&el!==cuerpo;el=el.parentElement){ var o=getComputedStyle(el).overflowX;
+  if((o==='auto'||o==='scroll')&&el.scrollWidth>el.clientWidth+2) return el; } return null; }
+ cuerpo.addEventListener('touchstart',function(e){ if(e.touches.length!==1){x0=null;return;}
+  rueda=corre(e.target);
+  x0=e.touches[0].clientX; y0=e.touches[0].clientY; dx=0; eje=null; panel=document.querySelector('.t-panel.activo'); },{passive:true});
+ cuerpo.addEventListener('touchmove',function(e){ if(x0===null||!panel) return;
+  var mx=e.touches[0].clientX-x0, my=e.touches[0].clientY-y0;
+  if(!eje){ if(Math.abs(mx)<10&&Math.abs(my)<10) return; eje=Math.abs(mx)>Math.abs(my)*1.3?'x':'y';
+   // como un PageView anidado: el que se desplaza de costado manda, salvo que ya esté en su borde
+   if(eje==='x'&&rueda){ var finD=rueda.scrollLeft+rueda.clientWidth>=rueda.scrollWidth-2, finI=rueda.scrollLeft<=2;
+    if(!(mx<0?finD:finI)) eje='rueda'; } }
+  if(eje!=='x') return;
+  if(e.cancelable) e.preventDefault();          // el gesto horizontal es de la página, no «volver atrás»
+  dx = vecino(mx<0?1:-1) ? mx : mx*.25;          // en el borde resiste, como el rebote
+  panel.style.transition='none'; panel.style.transform='translateX('+(dx*.6).toFixed(1)+'px)';
+  panel.style.opacity=(1-Math.min(.45,Math.abs(dx)/innerWidth)).toFixed(3); },{passive:false});
+ cuerpo.addEventListener('touchend',function(){ if(x0===null||!panel) return; x0=null;
+  var p0=panel, d=dx, dir=d<0?1:-1, id=vecino(dir);
+  p0.style.transition='transform .2s ease,opacity .2s ease'; p0.style.transform=''; p0.style.opacity='';
+  setTimeout(function(){p0.style.transition=''},220);
+  if(eje!=='x'||!id||Math.abs(d)<Math.min(90,innerWidth*.22)) return;
+  elegir(id);
+  var nuevo=document.getElementById(id); nuevo.classList.remove('desde-der','desde-izq'); void nuevo.offsetWidth;
+  nuevo.classList.add(dir>0?'desde-der':'desde-izq');
+  nuevo.addEventListener('animationend',function(){nuevo.classList.remove('desde-der','desde-izq')},{once:true});
+  if(p>.5&&menu) scrollTo({top:Math.round(menu.pegado),behavior:quieto?'auto':'smooth'}); });
  // un enlace con ancla a una sección (#codigo, #descargar…) abre esa pestaña
  var pedido=decodeURIComponent((location.hash||'').slice(1));
  if(elegir(pedido)&&menu) scrollTo({top:Math.round(menu.pegado)});