Ahora escribo el reporte final completo usando todo el historial de investigación disponible.

---

# 🚀 Guía Técnica Integral: Limitaciones del Ecosistema Amazon Kindle para Desarrolladores Web/Móvil

## Versión del documento: 1.0 — Estado: COMPLETO

> **Propósito:** Esta guía documenta de forma exhaustiva las capacidades, limitaciones y estrategias de desarrollo para crear experiencias de lectura multiplataforma (Kindle físico E-Ink, Kindle Cloud Reader y App Kindle Móvil) utilizando **Angular + Ionic**, cubriendo HTML, CSS, JavaScript, UI/UX para lectura, audio e integración multiplataforma.

---

## 📑 Tabla de Contenidos

1. [Introducción al Ecosistema Kindle](#1-introducción-al-ecosistema-kindle)
2. [Las Tres Plataformas Objetivo](#2-las-tres-plataformas-objetivo)
3. [Navegador Experimental Browser (La Gran Limitación)](#3-navegador-experimental-browser)
   - 3.1. Historial de WebKit
   - 3.2. User-Agent
   - 3.3. Soporte de JavaScript
   - 3.4. Soporte de CSS
   - 3.5. Soporte de HTML
   - 3.6. Políticas de Seguridad CORS y CSP
4. [Kindle Cloud Reader (La Alternativa Web Moderna)](#4-kindle-cloud-reader)
5. [App Kindle Móvil (iOS/Android)](#5-app-kindle-móvil-iosandroid)
6. [Audio en el Ecosistema Kindle](#6-audio-en-el-ecosistema-kindle)
7. [UI/UX para Lectura Multiplataforma](#7-uiux-para-lectura-multiplataforma)
8. [Estrategia Angular + Ionic — Arquitectura de Implementación](#8-estrategia-angular--ionic)
9. [Diagramas de Arquitectura y Flujo](#9-diagramas)
10. [Solución de Problemas Comunes](#10-solución-de-problemas-comunes)
11. [Checklist de QA por Plataforma](#11-checklist-de-qa)
12. [Preguntas Frecuentes](#12-preguntas-frecuentes)
13. [Referencias y Recursos](#13-referencias)

---

## 1. Introducción al Ecosistema Kindle

El ecosistema Kindle de Amazon abarca **tres entornos de visualización fundamentalmente distintos** para contenido web. Un desarrollador que desee crear una experiencia de lectura utilizando Angular e Ionic debe entender que **no existe una solución única**: cada plataforma impone restricciones drásticamente diferentes.

### Las tres caras del Kindle

| Plataforma | Tipo de Pantalla | Motor de Renderizado | Restricciones |
|---|---|---|---|
| **Kindle Físico (E-Ink)** | E-Ink Carta/300 ppi (16 grises o color) | WebKit antiguo (~2013-2018) | Extremas |
| **Kindle Cloud Reader** | Cualquier pantalla LCD/OLED | Navegador moderno del usuario | Mínimas |
| **App Kindle (iOS/Android)** | LCD/OLED del dispositivo | WebView del sistema (WkWebView, Android WebView) | Mínimas |

> ⚠️ **Advertencia:** No confundir **Kindle Fire** (tablet Android con navegador Silk completo) con los **Kindles E-Ink** (Paperwhite, Oasis, Scribe). Esta guía se centra en los segundos. Kindle Fire queda fuera del alcance.

---

## 2. Las Tres Plataformas Objetivo

### 2.1. Kindle Físico E-Ink (Modelos Actuales)

| Modelo | Generación | Año | Pantalla | PPI | Color |
|---|---|---|---|---|---|
| Kindle Basic | 11.ª | 2022 | 6" E-Ink Carta | 300 | No |
| Kindle Paperwhite | 11.ª | 2021 | 6.8" E-Ink Carta | 300 | No |
| Kindle Paperwhite | 12.ª | 2024 | 7" E-Ink Carta 1300 | 300 | No |
| Kindle Oasis | 10.ª | 2019 | 7" E-Ink Carta | 300 | No |
| Kindle Scribe | 1.ª | 2022 | 10.2" E-Ink Carta 1200 | 300 | No |
| Kindle Colorsoft | 1.ª | 2024 | 7" E-Ink Kaleido | 300 | **Sí** |

**Navegador:** Experimental Browser (WebKit antiguo)
**Firmware más reciente:** 5.17.1 (2024-2025)

> 💡 **Tip:** El Kindle Scribe y Paperwhite 12.ª generación tienen el hardware más moderno, pero su navegador sigue siendo WebKit antiguo. **No hay correlación entre la generación del hardware y la versión del navegador.**

### 2.2. Kindle Cloud Reader

Accesible en: [read.amazon.com](https://read.amazon.com)

- **Stack:** PWA basada en React
- **Service Workers:** ✅ Para funcionalidad offline
- **Navegador:** El del usuario (Chrome, Firefox, Safari, Edge)
- **Sin restricciones E-Ink:** Audio, video, JS moderno, fuentes externas
- **Detección:** Se puede detectar por `window.matchMedia('(display-mode: standalone)')`

### 2.3. App Kindle Móvil (iOS/Android)

- **iOS:** WkWebView (Safari 17+ moderno)
- **Android:** Android System WebView (Chrome-based moderno)
- **Ionic + Capacitor:** Compatibilidad total
- **Sin restricciones significativas** para contenido web

> ⚠️ **Nota:** La App Kindle nativa **no permite** WebViews personalizados embebidos de terceros. Sin embargo, el contenido al que se accede desde el navegador interno de la app funciona con WebView del sistema. Para una app independiente, se usa **Ionic + Capacitor** como wrapper que lanza su propio WebView.

---

## 3. Navegador Experimental Browser (La Gran Limitación)

### 3.1. Historial de WebKit en Kindle

| Período | Versión WebKit | Capacidades JS |
|---|---|---|
| 2010-2013 | WebKit ~Safari 3/4 | JS básico, sin ES5 completo |
| 2014-2019 | WebKit ~Safari 6 (iOS 6) | ES5, sin Promises, sin fetch, sin let/const |
| 2020-2023 | WebKit ~Safari 9 (iOS 9) | ES6 parcial: let/const, arrow functions, clases |
| **2024-2025** | **WebKit ~Safari 9/10** | **ES6 parcial: NO Promises, NO async/await, NO fetch** |

> ⚠️ **Limitación conocida:** Aunque Amazon ha actualizado el firmware a 5.17.1, el WebKit subyacente **no se ha actualizado significativamente** desde la versión ~Safari 9-10. Esto ha sido confirmado por la comunidad de Mobileread mediante pruebas exhaustivas.

### 3.2. User-Agent del Navegador Kindle

**Kindle E-Ink (Paperwhite, Oasis, Scribe):**

```
Mozilla/5.0 (X11; U; Linux armv7l like Android; en_us) AppleWebKit/537.36 (KHTML, like Gecko) Kindle/5.17.1 Safari/537.36
```

**Kindle Fire (NO E-Ink, NO cubierto):**

```
Mozilla/5.0 (Linux; U; en-US) AppleWebKit/537.36 (KHTML, like Gecko) Silk/44.3.3 Safari/537.36
```

> 💡 **Tip:** La presencia de `Kindle/` sin `Silk/` identifica un dispositivo E-Ink. La presencia de `Silk/` identifica un Kindle Fire (tablet Android).

```typescript
// Detecta si el dispositivo es un Kindle E-Ink
function isKindleEInk(): boolean {
  const ua = navigator.userAgent;
  return /Kindle\//.test(ua) && !/Silk\//.test(ua) && /Linux/.test(ua);
}
```

### 3.3. Soporte de JavaScript

#### ✅ Soportado

| Característica | Versión desde | Notas |
|---|---|---|
| `var`, `function`, objetos, arrays | Siempre | Básico |
| `let`, `const` | WebKit 9+ | ✅ Funciona en firmware 5.17+ |
| Arrow functions `() => {}` | WebKit 9+ | ✅ Pero sin `this` contextual confiable |
| Clases ES6 | WebKit 9+ | ✅ `class Foo { ... }` |
| Template literales | WebKit 9+ | ⚠️ Parcial: `` `hola ${var}` `` |
| `Array.isArray()`, `Array.prototype.forEach()` | WebKit 6+ | ✅ |
| `String.prototype.includes()` | WebKit 9+ | ✅ |
| `Number.isNaN()`, `Number.isInteger()` | WebKit 9+ | ✅ |
| `Object.keys()`, `Object.values()` | ⚠️ Solo `keys()` | `values()` no disponible |
| `JSON.parse()` / `JSON.stringify()` | WebKit 6+ | ✅ |
| `setTimeout()` / `setInterval()` | Siempre | ✅ |
| `XMLHttpRequest` | Siempre | ✅ (alternativa a `fetch`) |
| `localStorage` / `sessionStorage` | Sí | ~5MB límite |
| `document.getElementById()`, `querySelector()` | ✅ | `querySelectorAll()` limitado |
| `addEventListener()` | ✅ | Parcial (no todos los eventos) |
| `Math.*` | ✅ | Completo |
| `Date` | ✅ | Parseo limitado |
| `RegExp` | ✅ | Sin Unicode flags modernos |
| `Element.classList` | ⚠️ | `add/remove/toggle` sí, pero `contains()` puede fallar |
| `window.navigator` | ✅ | Limitado a propiedades básicas |

#### ❌ NO Soportado

| Característica | Impacto | Alternativa |
|---|---|---|
| `Promise` | **CRÍTICO** | Usar callbacks o librería `promise-polyfill` (ver notas) |
| `async/await` | **CRÍTICO** | Requiere Promises → no disponible |
| `fetch()` | **CRÍTICO** | Usar `XMLHttpRequest` |
| `Map`, `Set`, `WeakMap`, `WeakSet` | Alto | Usar objetos planos `{}` |
| `Symbol` | Alto | Evitar su uso |
| `Array.from()` | Medio | Usar `Array.prototype.slice.call()` |
| `Array.prototype.find(), findIndex()` | Medio | Polyfill manual |
| `Array.prototype.includes()` | Medio | Polyfill manual |
| `Object.assign()` | Medio | Polyfill manual o `extend()` propio |
| `Object.entries(), Object.fromEntries()` | Alto | Evitar |
| `String.prototype.startsWith(), endsWith()` | Bajo | Usar `indexOf() === 0` |
| `String.prototype.padStart(), padEnd()` | Bajo | Polyfill manual |
| `IntersectionObserver` | Medio | No disponible |
| `ResizeObserver` | Medio | No disponible |
| `MutationObserver` | ⚠️ | **NO CONFIRMADO** — posiblemente no disponible |
| `Service Workers` | Medio | No disponible |
| `Web Workers` | Medio | No disponible |
| `Web Audio API` | Alto | No disponible |
| `Canvas 2D/WebGL` | Medio | No disponible |
| `SVG.js` | Medio | No disponible |
| `WebSocket` | ⚠️ | **NO CONFIRMADO** — probablemente no disponible |
| `IndexedDB` | ⚠️ | **NO CONFIRMADO** — probablemente no disponible |
| `Custom Elements (Web Components)` | Medio | No disponible |
| `Shadow DOM` | Medio | No disponible |
| `Proxy`, `Reflect` | Alto | No disponible |
| `TypedArray (Int32Array, etc)` | Medio | No disponible |
| `requestAnimationFrame` | Medio | No disponible (pantalla E-Ink es estática) |

```javascript
// Polyfill funcional para Promise usando callbacks
// ⚠️ No es un Promise real, pero permite encadenamiento básico
function createTask(executor) {
  var callbacks = [];
  var resolved = false;
  var value;

  function resolve(val) {
    if (resolved) return;
    resolved = true;
    value = val;
    for (var i = 0; i < callbacks.length; i++) {
      callbacks[i](val);
    }
  }

  return {
    then: function(cb) {
      if (resolved) {
        cb(value);
      } else {
        callbacks.push(cb);
      }
      return this;
    },
    resolve: resolve
  };
}

// Uso
var task = createTask(function(resolve) {
  // Simular async
  setTimeout(function() {
    resolve('datos cargados');
  }, 100);
});
```

### 3.4. Soporte de CSS

#### ✅ Soportado (parcial o totalmente)

| Propiedad | Soporte | Notas |
|---|---|---|
| `display: block`, `inline`, `inline-block` | ✅ Completo | |
| `display: none` | ✅ | |
| `display: table`, `table-row`, `table-cell` | ✅ | Tablas simples |
| `color`, `background-color` | ✅ | 16 niveles de gris en E-Ink; color en Colorsoft |
| `font-size`, `font-weight`, `font-style` | ✅ | Solo fuentes del sistema |
| `text-align`, `text-indent` | ✅ | |
| `margin`, `padding` | ✅ | |
| `border`, `border-radius` | ✅ | |
| `width`, `height`, `min/max` | ✅ | |
| `overflow: hidden`, `auto`, `scroll` | ⚠️ | Scroll nativo del navegador Kindle es pobre |
| `position: relative`, `absolute`, `fixed` | ⚠️ | `fixed` funciona pero el comportamiento es impredecible |
| `float: left`, `right` | ✅ | |
| `z-index` | ⚠️ | Funciona básicamente |
| `@media (max-width: ...)` | ✅ | Básico |
| `cursor: pointer` | ✅ | |
| `white-space`, `word-wrap` | ✅ | `word-break` no soportado |
| `line-height` | ✅ | |
| `list-style` | ✅ | |
| `opacity` | ⚠️ | Puede no renderizarse en E-Ink |
| `visibility: hidden` | ✅ | |
| `@import` | ⚠️ | Puede fallar; preferir inline |

#### ❌ NO Soportado (o extremadamente limitado)

| Propiedad | Impacto | Alternativa |
|---|---|---|
| `display: flex` | **CRÍTICO** | Usar `display: table` o `float` |
| `display: grid` | **CRÍTICO** | Usar tablas o floats |
| `flexbox` completo | Alto | `-webkit-box` puede funcionar parcialmente |
| `@font-face` | **CRÍTICO** | Solo fuentes del sistema |
| `@keyframes` / `animation` | Medio | No relevante en E-Ink (sin animación) |
| `transition`, `transform` | Medio | No relevante en E-Ink |
| `filter`, `backdrop-filter` | Bajo | Evitar |
| `box-shadow`, `text-shadow` | ⚠️ | Puede ignorarse o verse mal |
| `linear-gradient`, `radial-gradient` | Medio | Usar imágenes PNG |
| `position: sticky` | Medio | Usar `fixed` con limitaciones |
| `column-count`, `column-width` | Bajo | No intentar paginación CSS |
| `@media (prefers-color-scheme)` | Bajo | No soportado; usar clases manuales |
| `@media (prefers-reduced-motion)` | Bajo | No soportado |
| `@supports` | Bajo | No soportado |
| `SVG` en CSS (background) | Medio | No soportado |
| `clip-path` | Bajo | No soportado |
| `object-fit` | Medio | No soportado |
| `calc()` | ⚠️ | Parcial; no confiable |
| `var()` (CSS custom properties) | ❌ | No soportado |
| `currentColor` | ❌ | No soportado |
| `initial`, `inherit`, `unset` | ⚠️ | `inherit` funciona básicamente |
| `:before`, `:after` pseudo-elementos | ⚠️ | Pueden fallar; no confiable |
| `:nth-child()`, `:first-of-type` | ⚠️ | Parcial; probar antes de usar |
| `input[type=...]` selectores | ❌ | No soportado |

```css
/* ✅ Buenas prácticas para Kindle E-Ink */

/* Contenedor de página principal */
.reader-content {
  display: table;           /* Fallback: flex no funciona */
  width: 100%;
  max-width: 800px;
  margin: 0 auto;
  padding: 1.5rem;
  font-family: serif;       /* Solo fuentes del sistema */
  font-size: 1rem;          /* Kindle escala globalmente */
  line-height: 1.8;
  color: #333;
  background-color: #fff9ef;
}

/* ❌ Lo que NO debes hacer en Kindle E-Ink */
.reader-content-moderno {
  display: flex;            /* ❌ No funciona */
  flex-direction: column;   /* ❌ No funciona */
  font-family: 'Roboto', sans-serif; /* ❌ @font-face no existe */
  background: linear-gradient(...);  /* ❌ No soportado */
  box-shadow: 0 2px 4px ...;        /* ⚠️ Puede ignorarse */
}
```

### 3.5. Soporte de HTML

| Elemento | Compatibilidad | Alternativa |
|---|---|---|
| `<p>`, `<h1>`-`<h6>`, `<div>`, `<span>` | ✅ | |
| `<a href="...">` | ✅ | Pero sin target blank, sin navegación fluida |
| `<img src="...">` | ✅ | PNG/JPEG. Máximo 1200px ancho. `<200KB` |
| `<table>`, `<tr>`, `<td>`, `<th>` | ✅ | Tablas simples, sin colspan/rowspan complejos |
| `<ul>`, `<ol>`, `<li>` | ✅ | |
| `<br>`, `<hr>` | ✅ | |
| `<blockquote>`, `<pre>`, `<code>` | ✅ | |
| `<form>` | ⚠️ | Muy limitado. Inputs de texto simples funcionan |
| `<input type="text">` | ⚠️ | Funciona básicamente |
| `<input type="checkbox/radio">` | ❌ | No funciona |
| `<select>`, `<option>` | ❌ | No funciona |
| `<textarea>` | ❌ | No funciona |
| `<button>` | ⚠️ | Funciona como `<div>` clickeable |
| `<details>` / `<summary>` | ❌ | No funciona |
| `<audio>` | ❌ | **No hay alternativa web** |
| `<video>` | ❌ | **No hay alternativa web** |
| `<canvas>` | ❌ | Renderizar del lado del servidor |
| `<svg>` | ❌ | Usar PNG estático |
| `<iframe>` | ❌ | No funciona |
| `<picture>` | ❌ | Usar `<img>` simple |
| `<source>` | ❌ | No funciona |
| `<figure>` / `<figcaption>` | ⚠️ | Puede no renderizarse correctamente |
| `<nav>` / `<header>` / `<footer>` | ✅ | Semánticamente, pero sin estilos especiales |
| `<main>` / `<section>` / `<article>` | ✅ | Semánticamente OK |
| `<style>` tag | ✅ | CSS inline o en `<style>` |
| `<script>` | ✅ | JS inline o externo |
| `<link rel="stylesheet">` | ⚠️ | Puede fallar en carga externa |
| `<meta>` tags | ⚠️ | viewport básico funciona |
| `data-*` atributos | ✅ | |
| `id` / `class` | ✅ | |
| `style="..."` (inline) | ✅ | Más confiable que CSS externo |

```html
<!-- ✅ Estructura HTML segura para Kindle E-Ink -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lectura en Kindle</title>
<style>
  body { font-family: serif; font-size: 1rem; line-height: 1.8; 
         padding: 1rem; color: #333; background: #fff9ef; }
  h1 { font-size: 1.5rem; text-align: center; margin: 1rem 0; }
  .nav { text-align: center; margin: 1rem 0; }
  .nav a { margin: 0 0.5rem; }
  img { max-width: 100%; height: auto; }
  table { width: 100%; border-collapse: collapse; }
  td, th { border: 1px solid #ccc; padding: 0.5rem; }
  .fallback { color: #666; font-style: italic; }
</style>
</head>
<body>
  <h1>Capítulo 1: El Viaje Comienza</h1>
  <div class="nav">
    <a href="index.html">← Inicio</a> | 
    <a href="cap2.html">Siguiente →</a>
  </div>
  
  <p>Texto del capítulo aquí...</p>
  
  <img src="mapa-viaje.png" alt="Mapa del viaje">
  
  <!-- Audio: mostrar fallback informativo -->
  <p class="fallback">🎧 Audio disponible en app Kindle o Cloud Reader.</p>
</body>
</html>
```

### 3.6. Políticas de Seguridad CORS y CSP

> ⚠️ **Limitación conocida:** El navegador Experimental Browser de Kindle aplica restricciones **CORS estrictas** y puede ignorar cabeceras CSP personalizadas. Esto afecta:

- **Carga de fuentes externas:** Bloqueada por CORS y falta de `@font-face`
- **Peticiones AJAX a dominios externos:** Solo funcionan si el servidor remoto permite CORS explícitamente
- **Service Workers:** No soportados, pero irrelevante
- **Cookies de terceros:** Bloqueadas

```nginx
# Configuración CORS para servidor de contenido Kindle
# (Aunque Kindle puede ignorar estas cabeceras, servirlas no hace daño)
location /api/ {
    add_header Access-Control-Allow-Origin "*";
    add_header Access-Control-Allow-Methods "GET, POST";
    add_header Access-Control-Allow-Headers "Content-Type";
    
    # Kindle respeta mejor sin CSP restrictivo
    add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self' data:;";
}
```

---

## 4. Kindle Cloud Reader (La Alternativa Web Moderna)

### ¿Qué es?

Kindle Cloud Reader es una **aplicación web progresiva (PWA)** alojada en `read.amazon.com`. A diferencia del navegador del Kindle físico, Cloud Reader corre en el navegador del usuario (Chrome, Firefox, Safari, Edge), por lo que **no tiene las limitaciones del E-Ink**.

### Stack Tecnológico

- **Framework:** React (según análisis de bundle)
- **Almacenamiento offline:** Service Workers + IndexedDB
- **Sincronización:** API REST de Amazon
- **Audio:** Web Audio API para Audible streaming
- **Fuentes:** Google Fonts / fuentes del sistema del SO

### Capacidades Técnicas

| Aspecto | Cloud Reader | Kindle E-Ink |
|---|---|---|
| HTML5 semántico | ✅ Completo | ⚠️ Limitado |
| CSS3 moderno (Flexbox, Grid) | ✅ Completo | ❌ |
| JavaScript ES2020+ | ✅ | ❌ Parcial ES6 |
| Service Workers | ✅ | ❌ |
| Web Audio API | ✅ | ❌ |
| `<audio>` / `<video>` | ✅ | ❌ |
| Offline | ✅ (Service Worker) | ❌ |
| Fuentes personalizadas | ✅ | ❌ (solo sistema) |
| SVG | ✅ | ❌ |
| Canvas | ✅ | ❌ |
| Animaciones CSS | ✅ | ❌ (E-Ink no anima) |

### Detección Programática

```typescript
function detectPlatform(): 'kindle-eink' | 'cloud-reader' | 'mobile' | 'desktop' {
  const ua = navigator.userAgent;
  
  // Kindle E-Ink físico
  if (/Kindle\//.test(ua) && !/Silk\//.test(ua) && /Linux/.test(ua)) {
    return 'kindle-eink';
  }
  
  // PWA standalone (Cloud Reader u otra)
  if (window.matchMedia('(display-mode: standalone)').matches) {
    return 'cloud-reader';
  }
  
  // App móvil vía Capacitor
  if (typeof (window as any).Capacitor !== 'undefined') {
    return 'mobile';
  }
  
  return 'desktop';
}
```

> 💡 **Tip:** Cloud Reader es el **entorno de pruebas ideal** para desarrollar tu SPA Angular antes de adaptarla para Kindle físico. Lo que funciona en Cloud Reader, funcionará también en la app móvil.

---

## 5. App Kindle Móvil (iOS/Android)

### Entorno WebView

| Plataforma | WebView | Versión Safari/Chrome | Soporte JS |
|---|---|---|---|
| **iOS** | WkWebView | Safari 17+ | ES2020+ completo |
| **Android** | Android System WebView | Chrome 100+ | ES2020+ completo |

### Ionic + Capacitor

**El stack Angular + Ionic + Capacitor funciona sin problemas** para crear una app de lectura que se distribuye independientemente de la app Kindle nativa.

```bash
# Crear proyecto Ionic/Angular
npm install -g @ionic/cli
ionic start kindle-reader-app blank --type=angular
cd kindle-reader-app
npm install @capacitor/core @capacitor/cli
npx cap init

# Añadir plataformas
npm install @capacitor/ios @capacitor/android
npx cap add ios
npx cap add android

# Para audio, instalar plugin de medios
npm install @capacitor-community/media
```

### Plugins Capacitor Relevantes para Lectura

| Plugin | Propósito | Enlace |
|---|---|---|
| `@capacitor/screen-reader` | Accesibilidad TTS | [Docs](https://capacitorjs.com/docs/apis/screen-reader) |
| `@capacitor-community/media` | Audio y video | [GitHub](https://github.com/capacitor-community/media) |
| `@capacitor/filesystem` | Almacenamiento offline | [Docs](https://capacitorjs.com/docs/apis/filesystem) |
| `@capacitor/storage` | Preferencias locales | [Docs](https://capacitorjs.com/docs/apis/storage) |
| `@capacitor/haptics` | Feedback táctil en swipe | [Docs](https://capacitorjs.com/docs/apis/haptics) |

---

## 6. Audio en el Ecosistema Kindle

### 6.1. La Realidad del Audio en Kindle

| Plataforma | ¿Soporta Audio Web? | Mecanismo |
|---|---|---|
| **Kindle Físico E-Ink** | ❌ **NO** | Solo Audible nativo + TTS del sistema |
| **Kindle Cloud Reader** | ✅ Sí | `<audio>` + Web Audio API |
| **App Móvil Ionic** | ✅ Sí | `<audio>` + Plugin Capacitor |
| **Web General** | ✅ Sí | `<audio>` + Web Audio API |

### 6.2. Kindle Físico: Sin Audio Web

> 🚫 **Limitación conocida:** El navegador Experimental Browser **no soporta** la etiqueta `<audio>`, ni `Web Audio API`, ni ningún mecanismo de reproducción de sonido basado en web. Tampoco hay plugins ni workarounds conocidos.

**Lo que SÍ existe en el Kindle físico (no controlable desde web):**

1. **Audible nativo:** Integración con libros de Audible comprados en la tienda Amazon. No accesible desde el navegador.
2. **Text-to-Speech (TTS):** El Kindle puede leer en voz alta libros con TTS habilitado. Es una función del firmware, no controlable desde JavaScript.
3. **VoiceView:** Lector de pantalla para personas con discapacidad visual. No controlable desde web.

### 6.3. Estrategia de Audio Multiplataforma

```typescript
// Servicio de audio adaptativo por plataforma
@Injectable({ providedIn: 'root' })
export class AudioService {
  private platform: string;
  
  constructor() {
    this.platform = detectPlatform();
  }
  
  canPlayAudio(): boolean {
    return this.platform !== 'kindle-eink';
  }
  
  getAudioFallbackMessage(): string {
    if (this.platform === 'kindle-eink') {
      return '🔊 Audio disponible en Kindle Cloud Reader o app Kindle.';
    }
    return '';
  }
  
  playChapter(chapterUrl: string): void {
    if (!this.canPlayAudio()) {
      console.warn('Audio no disponible en Kindle E-Ink');
      return;
    }
    
    const audio = new Audio(chapterUrl);
    audio.play().catch(err => {
      console.error('Error reproduciendo audio:', err);
    });
  }
}
```

```html
<!-- Componente de audio con fallback para Kindle E-Ink -->
<ng-container *ngIf="canPlayAudio(); else noAudio">
  <audio controls>
    <source [src]="chapter.audioUrl" type="audio/mpeg">
    Tu navegador no soporta audio.
  </audio>
  <div class="audio-sync">
    <button ion-button (click)="play()">▶ Reproducir</button>
    <button ion-button (click)="pause()">⏸ Pausar</button>
    <ion-range [(ngModel)]="currentTime" [max]="duration"></ion-range>
  </div>
</ng-container>

<ng-template #noAudio>
  <div class="audio-fallback">
    <p class="fallback-message">{{ getAudioFallbackMessage() }}</p>
    <ion-button href="https://www.audible.com" target="_blank">
      🎧 Escuchar en Audible
    </ion-button>
  </div>
</ng-template>
```

### 6.4. Audio Sincronizado con Texto (Tipo Audiolibro)

Para Cloud Reader y App Móvil:

```typescript
interface AudioSyncPoint {
  time: number;     // segundos
  wordIndex: number; // índice de palabra en el texto
}

class AudioSyncReader {
  private audio: HTMLAudioElement;
  private syncPoints: AudioSyncPoint[];
  
  constructor(audioUrl: string, syncData: AudioSyncPoint[]) {
    this.audio = new Audio(audioUrl);
    this.syncPoints = syncData;
    
    this.audio.addEventListener('timeupdate', () => {
      this.highlightCurrentWord();
    });
  }
  
  private highlightCurrentWord(): void {
    const currentTime = this.audio.currentTime;
    // Encontrar el sync point más cercano
    let activePoint = this.syncPoints[0];
    for (const point of this.syncPoints) {
      if (point.time <= currentTime) {
        activePoint = point;
      } else {
        break;
      }
    }
    // Resaltar palabra activa en el DOM
    document.querySelectorAll('.word').forEach((el, idx) => {
      el.classList.toggle('active', idx === activePoint.wordIndex);
    });
  }
}
```

---

## 7. UI/UX para Lectura Multiplataforma

### 7.1. Tipografía

| Aspecto | Kindle E-Ink | Cloud Reader / App Móvil |
|---|---|---|
| Fuentes disponibles | Bookerly, Caecilia, Helvetica, Monospace, serif, sans-serif | Cualquier Google Font o `@font-face` |
| Tamaño base | `1rem` = 16px (escalado por usuario Kindle) | `1rem` = 16px (controlable) |
| Recomendación | `font-family: serif` o `Bookerly` | `font-family: 'Merriweather', serif` |
| Unidades | `rem`, `em`, `px` | Cualquier unidad CSS |
| `font-weight` | Normal (400) y bold (700) | Cualquier peso variable |

```css
/* Tipografía compartida (base) */
.reader-text {
  font-size: 1rem;
  line-height: 1.8;
  -webkit-font-smoothing: antialiased;
}

/* Kindle E-Ink: solo fuentes del sistema */
.kindle-eink .reader-text {
  font