28 de agosto de 2026 · widget de clima de whatsincabo.com · construido, publicado y revisado por tres lentes independientes, uno de ellos adversario
Si el widget de clima mostraba en algún lado la probabilidad de lluvia de cada día.
No la mostraba. En los cuatro lugares donde aparecía la lluvia siempre eran milímetros. Y así se veía ese día:
| Fecha | El widget decía | Lo que el modelo decía de verdad |
|---|---|---|
| Hoy 28 ago | 0 mm | 75 % de probabilidad · 0.4 mm |
| Sáb 29 | 0 mm | 45 % · 0.1 mm |
| Dom 30 | 0 mm | 82 % · 1.5 mm |
| Lun 31 | no se veía | 91 % · 9.6 mm |
| Mié 2 sep | no se veía | 84 % · 29.4 mm |
Las dos columnas dicen la verdad. Ese es el punto: los milímetros contestan cuánto y el viajero pregunta si. Quien lee «0 mm» entiende «no va a llover», cuando el modelo estaba diciendo que había tres posibilidades de cada cuatro de que le lloviera un rato.
Y el pronóstico eran solo 3 días, metidos dentro de un cajón cerrado que se llama «Hourly forecast», detrás de doce renglones de horas. Toda la semana entrante quedaba fuera de la vista.
Una banda visible de siete días, la columna de la tabla de regiones convertida a porcentaje, y la probabilidad hora por hora.


Esa columna decía milímetros, y por eso ese día las ocho regiones decían exactamente «0.0 mm» cuando entre Cabo San Lucas y San José del Cabo había 65 puntos de diferencia. Una tabla hecha para comparar en la que no se podía comparar nada.
| Región | Antes | Ahora |
|---|---|---|
| Cabo San Lucas | 0.0 mm | 75 % |
| San José del Cabo | 0.0 mm | 10 % |
| Santiago | 0.0 mm | 33 % |
| Todos Santos | 0.0 mm | 49 % |
Cero peticiones nuevas. La llamada que ya hacíamos para el índice UV ahora trae también la lluvia.
| Antes | Ahora | |
|---|---|---|
| CSS que bloquea el render | 7 673 B | 7 673 B — byte por byte igual |
| JavaScript (va en el pie, comprimido) | 24.9 KB | 26.6 KB (+1.7 KB) |
| Peticiones al exterior | 1 cada 2 h (solo UV) | 1 cada 3 h (UV + lluvia, 8 regiones, 7 días) |
| Peso de esa petición | — | 41 KB, 0.81 s, siempre en segundo plano |
El CSS de la banda no está en la ruta crítica: se inyecta cuando alguien abre el panel. Si nadie lo abre, no cuesta nada.
Tres los encontré yo construyendo. Siete los encontraron los revisores de PC y móvil. Once los encontró el adversario. Todos están corregidos.
Por omisión, Open-Meteo busca la celda de tierra más cercana, y en una península angosta eso empuja el punto hacia el desierto. Cabo San Lucas caía 6.9 km adentro y Todos Santos 9.0 km.
Esa celda pronosticaba 35.7 °C donde el punto real da 31.5 y MET Norway —la fuente del resto del panel— decía 31.0. Casi cinco grados que no eran del clima sino del lugar. Además hacía que Scenic Route y Tourist Corridor compartieran celda, así que jamás podían diferir.
Corregido pidiendo la celda más cercana y no la de tierra. Las ocho regiones caen ahora en celdas distintas.
La cifra diaria de Open-Meteo es el máximo de las 24 horas incluidas las que ya pasaron. Anoche la columna de hoy decía 75 % por un chubasco de las 3 de la tarde que ya no iba a volver: una cifra correcta sobre un periodo que el lector ya no tiene.
Hoy se calcula solo sobre las horas que te quedan. Y se resuelve al servir, no al guardar en caché — meter la hora actual dentro de una caché de 3 horas es exactamente el error que ya pagamos con el UV.
Al arreglar lo anterior quedó el porcentaje midiendo las horas que faltan y los milímetros midiendo el día entero. En San José del Cabo eso se leía cero probabilidad de lluvia y aun así agua esperada. Dos números ciertos describiendo periodos distintos, que juntos no significan nada.
Los dos números de una columna miden ahora la misma ventana.
Separación medida: 0.00 px. Era el único par del panel con cero — los otros diez van de 8 a 14 px. Los dos bordes de 1 px se tocaban y el conjunto se leía como una sola tarjeta rota.
Causa: en este panel cada bloque declara su propio margen de arriba, y el mío solo declaraba el de abajo.
El texto de la banda arrancaba en x=38 mientras todos sus vecinos arrancan en 41–44. Cuatro a seis píxeles fuera de la columna que sigue el resto del panel, por 8 px de relleno lateral en vez de 12. Es justo lo que hace que un bloque se lea como «pegado de otro sitio».
Ahora arranca en 41.0, exactamente donde la tarjeta del mar. Las siete columnas siguen cabiendo a 320 px.
Decía Source: MET Norway Locationforecast para el contenido entero. Eso ya era falso antes de este trabajo: el índice UV y la temperatura del mar llevaban meses siendo Open-Meteo. La lluvia solo lo hizo evidente.
Ahora dice las dos. Es además lo que exige la licencia de las dos fuentes.
El gris del panel sobre blanco da 4.31 : 1, por debajo del 4.5 : 1 que exige la norma. Afectaba a los siete nombres de día, los siete de milímetros, el subtítulo y la nota entera — que es el texto más largo del bloque.
Todos a 5.51 : 1. Es un gris que el resto del sitio también usa; aquí se corrigió solo en este bloque para no tocar nada más sin tu visto bueno.
Las barras iban de claro a hondo según la probabilidad. Medida, no servía y encima estorbaba: entre 82 % y 91 % el color cambiaba 1.03 : 1 —invisible— así que cinco de las siete barras se leían como un bloque plano. Y en el extremo bajo daba 1.95 : 1, de modo que la barra mínima del 0 %, que existe justamente para que un cero se vea, no se veía.
Dos variables visuales para un solo dato, con una de las dos rota. Ahora es un solo color: 5.02 : 1 incluso en la barra de 1.4 px, y la altura carga sola con el dato.
Los dos revisores, por separado, leyeron esa columna como un error. Y tienen razón en la lectura: un cero al lado de un 82 % dice «no va a llover» y contradice al número de arriba.
Ahora dice «<0.1 mm», que es lo que el modelo dice de verdad: va a caer algo y no lo vas a notar. Que es exactamente la historia que esta banda existe para contar.
Estaban a 9 px cuando el piso del resto del panel es 10, y en móvil bajaban a 8.
A 10 px en todos lados. Los 9 px quedan solo por debajo de 400 px de ancho, donde la columna mide 37 px y no cabe más — y eso está medido, no supuesto.
Con la razón medida de por qué.
El revisor propuso igualarla a sus vecinas de arriba, que sí lo llevan. Lo probé: con ese degradado el fondo termina a cuatro puntos de la pista de las barras y la pista desaparece.
Se perdería el riel contra el que se lee la altura, que es el dato. Se queda blanca, que además empareja con los acordeones de abajo.
La fila mezcla «6.9 mm» y «13 mm». Un decimal por debajo de 10 y entero por arriba es legibilidad, no descuido: «31.0 mm» es precisión falsa.
Ninguno de estos lo toco sin que me digas.
El veredicto Good / Caution / Avoid se calcula con la lluvia de la hora en curso, no del día. Así que en un día de 91 % de probabilidad y 7 mm esperados, si no está lloviendo en ese momento la tabla dice «Good».
Ese defecto ya existía; lo que hice fue hacerlo visible al poner el porcentaje al lado. Cambiar ese umbral cambia lo que el widget le dice a la gente sobre sus planes, y eso es decisión tuya.
El revisor de móvil midió que la página mide 373 px en una pantalla de 360. Lo probó con mi banda oculta y con el encabezado oculto: da idéntico, así que no es mío.
Lo rastreé: es el menú de navegación del tema, cuyos elementos se extienden hasta x=548 sin ocultarse en móvil. A 320 px eso corta el panel entero por la derecha.
Es un defecto real y viejo del sitio, con ticket propio.
Este cambio no agrega peticiones, pero sí consolida a Open-Meteo como fuente de la lluvia además del UV y el mar. El permiso está; la llave nunca se emitió.
Medido, no visto.
| Qué | Resultado |
|---|---|
| Anchos probados, de 320 a 1920 px | 14 — cero colisiones, cero texto recortado, cero desbordes |
| ¿La barra corresponde a su número? | Desviación máxima 0.014 px sobre una pista de 48 |
| Alineación de las siete columnas | Diferencia máxima 0.016 px |
| Errores de JavaScript | 0, en los tres widgets |
| Contraste del texto / de las barras | 5.51 : 1 · 5.02 : 1 |
| Con Open-Meteo caído (simulado) | La lluvia y el UV desaparecen en vez de inventar ceros; el resto del panel sigue con las 8 regiones |
Los otros dos widgets —el sismógrafo y el radar de huracanes— comparten el mismo archivo, así que se revisaron también: los dos abren, con sus datos y sus fuentes, sin un solo error.


El que no busca confirmar que funciona, sino encontrar el caso en que miente. Encontró once cosas, y una era grave.
A las 00:08 de Cabo del 29 de agosto, el sitio en producción servía esto:
| Fecha real | Lo que decía la columna |
|---|---|
| 2026-08-28 (ayer) | «Today» · 75 % |
| 2026-08-29 (el día de verdad) | «Sat» · 45 % |
Toda la tira corrida un día. Y ese 75 % era el máximo de un día que ya había terminado, porque al fallar la condición también se perdía el recorte a las horas restantes. Nueve minutos antes esa columna decía 0 %; a las 00:03 saltó a 75 %.
La causa: las etiquetas se calculan al armar el paquete de datos, y ese paquete vive tres horas. La palabra «Today» se quedaba pegada al día de ayer hasta que caducara.
La fecha es el único dato que no caduca, así que ahora los días vencidos se tiran y las etiquetas se derivan de la fecha cada vez que se sirve. Probado contra una caché que todavía tenía el día 28 adentro: se sirve el 29 como «Today», con su recorte, y seis días en vez de siete. Menos días es correcto; un día mal rotulado no lo es.
Horas antes, los revisores de PC y móvil me habían hecho cambiar «0.0 mm» por «<0.1 mm» porque al lado de un 82 % se leía como contradicción. El adversario señaló que eso afirma una traza de lluvia donde el modelo dice que no se acumula nada.
Tiene razón, y la corrección de legibilidad no puede costar exactitud. Vuelve a decir «0.0 mm», y «<0.1 mm» queda solo para lo que de verdad está entre cero y una décima. Sí, un 82 % junto a un 0.0 mm se lee raro — y es la verdad. Para eso está la nota.
El veredicto se calcula con la lluvia de la hora en curso. Con datos reales de un lunes, la tabla quedaba así:
| Región | Rain today | Status |
|---|---|---|
| Santiago | 98 % | Good |
| Cabo San Lucas | 91 % | Good |
| La Paz | 50 % | Caution |
La región con más probabilidad de las ocho era la única en verde. El orden invertido.
La columna se llama ahora «Right now», así que cada cifra dice el periodo que mide y las dos pueden ser ciertas a la vez. El umbral no lo toqué — eso sigue siendo decisión tuya, abajo.
La caché del navegador no caducaba nunca. Abrir el panel, cerrarlo y reabrirlo tres veces daba una sola petición. Una pestaña dejada abierta seguía mostrando su «Today» original aunque afuera ya fuera otro día — lo que empeoraba el defecto de arriba.
Caduca a los 15 minutos.
La nota prometía «solo las horas que te quedan» siempre, aunque el servidor no hubiera recortado nada — ahora solo aparece si de verdad recortó. El título «Next 7 days» y la rejilla estaban clavados a mano, así que con seis días el título mentía y sobraba una columna vacía. Un valor imposible (150, −20, texto) se dibujaba tal cual: ahora se trata como «sin dato» — y el candado se puso en los dos sitios que dibujan, porque lo tenía la banda y no la tabla, y la tabla llegó a imprimir «150 %» mientras la banda del mismo dato decía «no data». Si falta la probabilidad pero hay milímetros reales, ya no se tiran. Sin lluvia en ninguna región, la tabla dejaba ocho celdas en blanco bajo un encabezado: ahora se quita la columna entera. Y el piso de barra rendía 1.2 px — menos que el grosor de una línea— así que no cumplía su único propósito: mínimo 2 px.
Vale la pena anotarlos: probabilidad nula, rain_outlook ausente, zona horaria del cliente (con el navegador en Tokio, Madrid o Kiritimati —los tres ya en el día siguiente— la banda sigue diciendo la hora de Cabo), coherencia al cambiar de región, movimiento reducido, zoom al 200 %, los respaldos cuando el feed caduca o da 404, y el escapado de HTML.