diff --git a/README.md b/README.md
index 13dfd3c..583478b 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
Notas personales que viven en tu navegador y se sincronizan entre tus propios dispositivos.
- Sin cuentas, sin backend que centralice el contenido y con cifrado de extremo a extremo.
+ Sin cuentas, sin un almacén central de contenido y con cifrado de extremo a extremo.
@@ -18,23 +18,132 @@
----
+## Qué es Selnote
-## Qué hace
+Selnote es una aplicación web estática para crear notas y conservar archivos cifrados en el navegador. Replica los cambios entre dispositivos autorizados mediante conexiones directas WebRTC y representa las notas como neuronas alrededor de un cerebro 3D.
-Selnote está pensado para conservar notas y archivos bajo tu control: cifra los datos en el dispositivo, guarda una copia local y replica los cambios directamente entre dispositivos emparejados. La interfaz convierte el conjunto de notas en un mapa visual para navegar el contenido y entender qué dispositivos forman parte del cerebro.
+No requiere una cuenta ni usa un backend como almacén de notas. La infraestructura de red ayuda a encontrar dispositivos y, cuando la conexión directa falla, puede transportar bytes ya cifrados.
-El cambio de nombre a Selnote conserva la base de datos local y el espacio de descubrimiento usados por versiones anteriores. Actualizar la aplicación no migra ni borra las notas existentes, y los dispositivos ya emparejados continúan compartiendo el mismo protocolo.
+> [!IMPORTANT]
+> El enlace secreto contiene la llave que permite encontrar y descifrar el cerebro. No lo publiques ni lo compartas con personas que no deban leer su contenido.
-## Funcionalidades principales
+## Probar ahora
-- **Notas locales cifradas** con AES-GCM y almacenamiento en IndexedDB.
-- **Historial verificable de cambios**, firmado con claves Ed25519.
-- **Sincronización P2P** entre dispositivos mediante WebRTC; el contenido viaja cifrado.
-- **Emparejamiento por código o QR** para autorizar nuevos dispositivos.
-- **Modo de transferencia por luz**: enviá notas pequeñas de pantalla a cámara sin Wi-Fi, datos ni Bluetooth.
-- **Adjuntos e imágenes** cifrados, fragmentados y verificados por hash antes de usarse.
-- **Edición, búsqueda, eliminación y revocación** desde una única interfaz web.
+Abrí **[Selnote en GitHub Pages](https://anthoniriv.github.io/selnote-web/)** en un navegador moderno.
+
+1. Seleccioná **Crear cerebro**.
+2. Creá una nota con el botón **+** o pegá texto, imágenes o archivos.
+3. Desde **enlace secreto**, elegí **mi dispositivo** para conectar otro equipo propio o **invitado** para una sesión de lectura temporal.
+4. Abrí el enlace en el segundo dispositivo y mantené ambos conectados hasta que aparezca la sinapsis.
+5. Editá una nota y comprobá que el cambio llegue al otro dispositivo.
+
+## Inicio rápido
+
+### Crear notas
+
+- **+** abre el editor para crear una nota.
+- **⧉** crea una nota desde el portapapeles; en escritorio también podés usar `Ctrl+V` o `⌘V` fuera del editor.
+- **⌕** busca por título o contenido. También funcionan `Ctrl/⌘+F`, `Ctrl/⌘+K` y, si el sistema no lo reserva, `Ctrl/⌘+Espacio`.
+- Arrastrar archivos sobre la aplicación abre una nota nueva con esos adjuntos.
+
+### Conectar dispositivos
+
+El enlace secreto da acceso al cerebro; el emparejamiento establece una conexión entre dos navegadores. Son pasos distintos:
+
+1. El owner comparte un enlace de **mi dispositivo**.
+2. El nuevo dispositivo demuestra criptográficamente que posee la llave del cerebro.
+3. El owner registra su permiso de escritura en la cadena firmada.
+
+Para equipos que ya tienen acceso al mismo cerebro, **sin internet** permite intercambiar una oferta y una respuesta WebRTC por texto o QR dentro de la misma red local. Ese código conecta los pares, pero no reemplaza el enlace secreto ni concede permisos por sí solo.
+
+## Mapa de funcionalidades
+
+### Notas e interfaz
+
+- Creación, lectura, edición y eliminación de notas según el permiso del dispositivo.
+- Pegado directo de texto, imágenes y archivos; selector múltiple, selector móvil de fotos y vídeos, y arrastrar y soltar.
+- Búsqueda por título y contenido con navegación por teclado y enfoque de la neurona encontrada.
+- Detección de enlaces `http` y `https` dentro del texto, abiertos en una pestaña aislada.
+- Bloques de código con sintaxis de triple acento grave, etiqueta de lenguaje y botón para copiar.
+- Fecha local de la última modificación y resúmenes de contenido en las tarjetas.
+- Cerebro 3D interactivo: rotación con puntero, zoom con rueda o gesto de pellizco, pulsos al recibir cambios y una rama por nota.
+- Vista plana de respaldo si WebGL o la biblioteca 3D local no pueden cargarse.
+
+### Archivos y contenido multimedia
+
+- Adjuntos cifrados de hasta **2 GB por archivo**. El límite efectivo también depende de la cuota y el espacio disponible en el navegador.
+- Cifrado y almacenamiento por fragmentos de 256 KB para evitar cargar el archivo completo en memoria durante la ingesta.
+- Vista previa de imágenes, reproducción de audio y vídeo, y descarga de cualquier adjunto disponible.
+- Verificación SHA-256 del contenido recibido antes de aceptarlo.
+- Transferencias reanudables por fragmento, con deduplicación de fragmentos idénticos y reintentos cuando un emisor desaparece.
+- Descarga paralela desde varios dispositivos, repartida según la velocidad observada de cada conexión.
+- Barra de progreso con porcentaje, velocidad y ruta utilizada: directa, por relevo o mixta.
+- Wake Lock cuando el navegador lo permite, para reducir interrupciones mientras hay una transferencia activa.
+
+### Sincronización y red
+
+- Replicación P2P por canales WebRTC; el tracker coordina la señalización, no almacena notas.
+- Descubrimiento mediante un tópico derivado de la llave: sin el secreto no se conoce el canal del cerebro.
+- Fallback por WebSocket cuando los pares no consiguen una ruta WebRTC directa. El relevo transporta el contenido cifrado por la aplicación.
+- Sincronización de la cadena completa al detectar huecos y difusión inmediata de bloques nuevos.
+- Convergencia determinista ante ramas simultáneas y reaplicación de cambios propios que hayan quedado fuera de la rama adoptada.
+- Reanudación al volver desde segundo plano, limpieza de conexiones obsoletas y reintento de archivos pendientes.
+- Control **desconectar/conectar** para aislar el dispositivo de la red sin dejar de usar su copia local.
+- Estado visible de red, número de pares y diagnóstico básico cuando no existe una ruta entre dispositivos.
+- Emparejamiento local sin salida a Internet mediante oferta/respuesta copiada, compartida o escaneada como QR.
+
+### Transferencia por luz
+
+- Envío de una nota y sus adjuntos directamente de una pantalla a una cámara, sin Wi-Fi, datos móviles ni Bluetooth.
+- Secuencia de QR animados con códigos fountain: el receptor puede reconstruir la carga aunque pierda algunos cuadros.
+- Límite exacto de **2 MB por envío**, incluyendo texto, metadatos y adjuntos.
+- Progreso de emisión y recepción, selección automática de cámara trasera cuando está disponible y reconstrucción local como una nota nueva.
+
+La transferencia por luz no sincroniza dos cerebros ni concede acceso: importa una copia puntual de la nota en el cerebro receptor.
+
+### Dispositivos y permisos
+
+- Dos clases de enlace secreto:
+ - **Mi dispositivo:** conserva la identidad y la réplica local; solicita permiso para escribir.
+ - **Invitado:** funciona en memoria, es de solo lectura y olvida llaves, bloques y archivos al cerrar la pestaña.
+- Identidad Ed25519 propia por dispositivo persistente; la clave privada no sale del navegador.
+- Prueba cifrada de posesión de la llave antes de que el owner autorice un dispositivo nuevo.
+- Panel con dispositivos autorizados, estado en línea, custodio actual y orden de sucesión.
+- Revocación de escritura. El dispositivo revocado conserva lo ya sincronizado y necesita una reautorización explícita para escribir otra vez.
+- Lectura, búsqueda y descarga disponibles para invitados y dispositivos sin permiso de escritura.
+
+### Custodia y resiliencia
+
+- Un único dispositivo mantiene la custodia vigente y firma las operaciones administrativas.
+- Orden de sucesión firmado y editable por el custodio.
+- Traspaso de custodia al primer sucesor conectado cuando el owner cierra la página. Una recarga se distingue de un cierre para no borrar la copia accidentalmente.
+- Reclamación de custodia por el primer sucesor disponible después de **60 segundos** sin ver al custodio anterior.
+- Purga de una réplica persistente que permanece **5 minutos** sin ninguna sinapsis; la aplicación avisa un minuto antes.
+- Recuperación de una réplica local cuya cadena no pasa la verificación: se descarta la cadena corrupta y se intenta resincronizar desde otros dispositivos.
+- Eliminación global iniciada por el custodio mediante una sentencia firmada. El modo lápida continúa notificando a dispositivos que estaban apagados cuando vuelven a conectarse.
+
+> [!WARNING]
+> El modelo de custodia prioriza que la memoria viva mientras haya dispositivos conectados. Al cerrar como custodio, la copia local puede borrarse y la custodia pasar a un sucesor. Leé el diálogo de confirmación antes de cerrar o eliminar el cerebro.
+
+### Privacidad e integridad
+
+- Notas cifradas con AES-256-GCM antes de persistirse o transferirse.
+- Adjuntos cifrados por fragmento y almacenados fuera de la cadena; la cadena conserva descriptores cifrados.
+- Historial enlazado por hash y operaciones firmadas con Ed25519.
+- Validación del génesis, continuidad de índices y hashes, firmas, autoridad vigente y permisos de escritura antes de aceptar una cadena.
+- Llave de cifrado dentro del fragmento `#` del enlace: el navegador no la envía como parte de la solicitud HTTP normal.
+- Política CSP restrictiva y bibliotecas JavaScript servidas desde `vendor/`, sin fallback ejecutable a CDN.
+
+El cifrado protege el contenido, no todo el contexto de conexión. Tracker, STUN y TURN o relevo pueden observar metadatos necesarios para establecer la comunicación, como direcciones IP, puertos, horarios, pares participantes y volumen aproximado de tráfico. Consultá [Red y despliegue](docs/networking.md) y el [modelo de amenazas](docs/threat-model.md).
+
+### PWA y operación
+
+- Manifest para instalar Selnote como aplicación independiente cuando el navegador lo permite.
+- Service worker con estrategia network-first y respaldo offline para el shell: HTML, manifest, icono y bibliotecas locales.
+- Apertura y uso de la réplica local sin Internet después de que el shell haya quedado en caché.
+- Precarga de las bibliotecas QR necesarias para el emparejamiento local y la transferencia por luz.
+- Comprobación periódica de versión en despliegues que expongan `/version`; la recarga se aplaza mientras el usuario edita o confirma una acción.
+- Aplicación estática sin proceso de compilación ni dependencias npm de ejecución.
## Cómo funciona
@@ -46,34 +155,39 @@ El cambio de nombre a Selnote conserva la base de datos local y el espacio de de
│
├── se guarda localmente en IndexedDB
│
- └── se replica a dispositivos autorizados por WebRTC
+ └── se replica a dispositivos autorizados
+ │
+ ├── WebRTC directo
+ └── relevo cifrado si no hay ruta directa
```
-El contenido no se sube a un servicio central. Un tracker liviano puede ayudar a encontrar pares y negociar la conexión, pero las notas y los adjuntos se envían cifrados entre dispositivos. Para un intercambio puntual, el código QR permite iniciar la transferencia usando únicamente la pantalla y la cámara.
+La cadena registra la secuencia verificable de operaciones. Los binarios se guardan aparte, cifrados y direccionados por hash, para que la sincronización inicial siga siendo ligera y las transferencias puedan reanudarse por fragmentos.
-## Flujo de uso
-
-1. Abrí la aplicación en un navegador compatible y creá un espacio de notas.
-2. Guardá notas o adjuntá archivos: permanecen cifrados en el almacenamiento del navegador.
-3. Emparejá otro dispositivo con el código o QR para replicar el contenido entre ambos.
+El cambio de nombre a Selnote conserva el nombre heredado de la base IndexedDB y el espacio de descubrimiento del protocolo. Actualizar la aplicación no migra ni borra por sí mismo las notas existentes, y los dispositivos compatibles continúan compartiendo la misma red.
## Arquitectura
El proyecto es una aplicación web estática y autocontenida:
```text
-index.html interfaz, lógica de aplicación y estilos
-assets/ recursos visuales de la documentación
+index.html interfaz, estilos y lógica principal
+manifest.webmanifest metadatos de instalación
+sw.js caché del shell offline
+vendor/ Three.js y bibliotecas QR locales
+scripts/ validaciones usadas por la aplicación y la CI
+tests/ pruebas de integridad del repositorio
+docs/ red, despliegue y modelo de amenazas
+assets/ recursos visuales de la documentación
```
-El archivo de entrada implementa la interfaz, IndexedDB, Web Crypto, WebRTC y la visualización 3D. El repositorio incluye un `package.json` sin dependencias de ejecución para las verificaciones locales y de CI; no requiere proceso de compilación ni backend de almacenamiento.
-
| Capa | Tecnología |
|------|------------|
| Interfaz | HTML, CSS y JavaScript vanilla |
| Almacenamiento | IndexedDB del navegador |
-| Cifrado e identidad | Web Crypto, AES-GCM y Ed25519 |
-| Sincronización | WebRTC P2P + señalización liviana |
+| Cifrado e identidad | Web Crypto, AES-GCM, SHA-256 y Ed25519 |
+| Sincronización | WebRTC P2P + señalización y relevo WebSocket |
+| Experiencia offline | Web App Manifest + Service Worker |
+| Visualización | Three.js local con fallback plano |
## Ejecución local
@@ -85,13 +199,21 @@ python3 -m http.server 8080
Abrí [http://localhost:8080](http://localhost:8080). Usar un servidor local, en vez de abrir el archivo directamente, permite que el navegador aplique correctamente las APIs web que utiliza la aplicación.
-## Consideraciones
+Para ejecutar las mismas verificaciones que la CI:
+
+```bash
+npm run check
+npm test
+```
+
+## Límites y recuperación
-- El contenido se almacena localmente en cada navegador; borrar los datos del sitio elimina esa copia.
-- La sincronización depende de que los dispositivos puedan conectarse como pares.
-- El tracker solo facilita el encuentro y la negociación; no es el almacén de notas. Los servicios de tracker, STUN y TURN pueden observar metadatos de red necesarios para establecer la conexión —por ejemplo, direcciones IP, puertos, momento y volumen aproximado del tráfico—, aunque no el contenido cifrado de las notas ni de los adjuntos.
-- Los adjuntos se cifran antes de persistirse y se verifican al recibirse.
-- La transferencia por QR está pensada para notas y cargas pequeñas: el límite práctico depende de la cámara y la velocidad de lectura.
+- Selnote no sustituye una estrategia de respaldo. Si se borran todas las copias del navegador o se pierde el enlace secreto, no existe un servidor central desde el que recuperar el contenido.
+- Borrar los datos del sitio elimina la réplica y las llaves guardadas en ese navegador.
+- La sincronización requiere que al menos dos dispositivos compatibles coincidan en línea y logren una ruta directa o por relevo.
+- Los archivos admiten hasta 2 GB, pero la cuota real depende del navegador y del dispositivo.
+- La transferencia por luz admite hasta 2 MB y su velocidad depende de las pantallas, las cámaras y la iluminación.
+- Algunas funciones requieren permisos o soporte del navegador: portapapeles, cámara, WebRTC, Web Crypto, IndexedDB, Service Worker y Wake Lock.
## Comunidad y calidad
@@ -102,10 +224,3 @@ Abrí [http://localhost:8080](http://localhost:8080). Usar un servidor local, en
- [Red y despliegue](docs/networking.md)
- [Modelo de amenazas](docs/threat-model.md)
- [Licencia MIT](LICENSE)
-
-Para ejecutar las mismas verificaciones que la CI:
-
-```bash
-npm run check
-npm test
-```
diff --git a/index.html b/index.html
index 133662f..d3688e2 100644
--- a/index.html
+++ b/index.html
@@ -64,9 +64,51 @@
/* ---- setup ---- */
#setup {
position: fixed; inset: 0; z-index: 100;
- display: flex; flex-direction: column; justify-content: center; align-items: center;
+ display: flex; flex-direction: column; justify-content: flex-start; align-items: center;
background: rgba(255,255,255,.82); backdrop-filter: blur(6px);
- padding: 1rem;
+ padding: clamp(1rem, 4vh, 2.5rem) 1rem;
+ overflow-y: auto;
+ }
+ #setup .setup-brand {
+ position: relative;
+ width: min(720px, 92vw);
+ margin-top: auto;
+ color: var(--ink);
+ font-size: clamp(2.35rem, 11vw, 4.75rem);
+ font-weight: 700;
+ line-height: .95;
+ letter-spacing: .16em;
+ text-align: center;
+ text-indent: .16em;
+ }
+ #setup .setup-brand span { position: relative; display: inline-block; }
+ #setup .setup-brand span::before,
+ #setup .setup-brand span::after {
+ content: attr(data-text);
+ position: absolute; inset: 0;
+ color: var(--ink);
+ pointer-events: none;
+ opacity: 0;
+ animation: setup-glitch-in 680ms cubic-bezier(.16,1,.3,1) 120ms both;
+ }
+ #setup .setup-brand span::before { --glitch-x: -.09em; --glitch-x-reverse: .09em; --glitch-x-small: -.035em; --glitch-y: -.035em; }
+ #setup .setup-brand span::after { --glitch-x: .09em; --glitch-x-reverse: -.09em; --glitch-x-small: .035em; --glitch-y: .035em; animation-delay: 170ms; }
+ @keyframes setup-glitch-in {
+ 0%, 100% { clip-path: inset(0 0 100% 0); transform: translate(0); opacity: 0; }
+ 12% { clip-path: inset(8% 0 66% 0); transform: translate(var(--glitch-x), var(--glitch-y)); opacity: .78; }
+ 28% { clip-path: inset(62% 0 12% 0); transform: translate(var(--glitch-x-reverse), 0); opacity: .5; }
+ 44% { clip-path: inset(31% 0 42% 0); transform: translate(var(--glitch-x), var(--glitch-y)); opacity: .72; }
+ 62% { clip-path: inset(74% 0 4% 0); transform: translate(var(--glitch-x-small), 0); opacity: .34; }
+ 78% { clip-path: inset(18% 0 70% 0); transform: translate(0); opacity: .18; }
+ }
+ #setup .setup-tagline {
+ width: min(460px, 92vw);
+ margin: .75rem 0 1.35rem;
+ color: var(--dim);
+ font-size: .68rem;
+ line-height: 1.6;
+ letter-spacing: .08em;
+ text-align: center;
}
#setup .card {
width: min(460px, 92vw);
@@ -76,6 +118,12 @@
#setup h2 { font-size: .78rem; letter-spacing: .18em; text-transform: uppercase; margin-bottom: .6rem; }
#setup p { font-size: .72rem; color: var(--dim); line-height: 1.6; margin-bottom: 1rem; }
#setup .hint { font-size: .62rem; margin-bottom: .8rem; }
+ #setup .card:last-child { margin-bottom: auto; }
+
+ @media (prefers-reduced-motion: reduce) {
+ #setup .setup-brand span::before,
+ #setup .setup-brand span::after { content: none; animation: none; }
+ }
/* aviso de cerebro muerto */
#dead {
@@ -407,6 +455,8 @@
+
SELNOTE
+
Notas cifradas. Sincronización directa entre tus dispositivos.
Crear cerebro
Genera el génesis, tu llave de firma (owner) y la llave de cifrado AES-256. Todo el contenido viaja y se guarda cifrado — sin el enlace secreto nadie puede leer ni encontrar tu red.
diff --git a/screenshot.png b/screenshot.png
index 6709a5f..e39008d 100644
Binary files a/screenshot.png and b/screenshot.png differ