- /change-race-character (3€), /change-faction-character (5€, valida condiciones:
sin hermandad/correo/subastas/capitán-arena y oro <= cap por nivel),
/level-up-character (10€), /gold-character (oro por correo SOAP). Cada uno borra
su ruta antigua y actualiza el link del panel.
- SumUp: hook precheck en PaidServiceConfig (condiciones cambio de facción);
columna home_stripelog.metadata para campos extra (gold_amount).
- /quest-character: rastreador de estado de misiones/cadenas (clase, Hijos de
Hodir, misión por ID) en personaje offline; cooldowns por categoría, Turnstile,
IDs de misión verificados en wotlkdb 3.3.5a. Tabla home_questsearchhistory.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- /rename-character y /customize-character: renombrar/personalizar pagados por SumUp
(getRenamePrice/getCustomizePrice). SumUp ahora es service-aware: columna
home_stripelog.service; createSumUpCheckout guarda service+character;
fulfillSumUpCheckout despacha a la acción del servicio (.char rename/customi) o,
sin service, acredita PD. [service]/checkout acepta provider:'sumup';
PaidServiceForm acepta provider+confirmText; service-success maneja el return SumUp.
Se eliminan las antiguas /rename y /customize (Stripe).
- /revive-character (comparte ReviveServiceContent); se elimina /revive.
- Renombres de ruta + todos sus enlaces:
/account -> /my-account, /recruit -> /recruit-a-friend, /unstuck -> /unstuck-character.
(/select-account y /api/account/* intactos.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- CharacterSelect: componente reutilizable que colorea las opciones por clase
(class="priest big-font"…) y el <select> con la clase seleccionada. Usado en
unstuck, revive, gold, transfer, trade-points, servicios de pago y recruit.
getGameCharacters ahora devuelve classCss.
- /unstuck (+revive): diseño del original (info + NOTA, prompt, opciones coloreadas,
botón "Desbloqueado"/"Revivido" con refresh).
- /vote-points: seed de los 4 sitios con logos y URLs (sql/seed_votesites.sql);
botón voted-button para sitios en cooldown; etiqueta "Nota:" separada.
- account-info.png (imagen nueva) y CSS de los paneles de cuenta: se añade
background-blend-mode: saturation y background-size en #account-settings y
.account-fieldset para que la imagen salga como el original.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- /security-token: diseño completo del original (info + advertencia + NOTA 7 días),
fecha en formato HH:MM:SS DD-MM-YYYY, botón "Token enviado", enlace a /recover.
- /recover: 4 opciones (contraseña por usuario, nombre de cuenta, token de seguridad
y enlace de activación por correo); recuperación de token nueva; Turnstile por envío.
- /vote-points: caja de info con las 7 secciones Q&A + panel "Sitios de votación" con
tarjetas inline-div (imagen, PV, último voto), botón refrescar; abre el sitio y acredita
PV al volver. lib/vote.ts + getVoteSitesForAccount.
- /rename-guild: renombra una hermandad de la que la cuenta es Maestro por 1000 PD +
token de seguridad; SOAP .guild rename con comillas; reembolsa los PD si SOAP falla.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- /transfer-d-points: transferir PD a la cuenta dueña de un personaje
(requiere token de seguridad; movimiento atómico con FOR UPDATE).
- /trade-points: comercio PD<->oro mediante códigos de 1 solo uso
(contraseña + token + Turnstile; oro al creador por SOAP; expira 1h;
lock de 5s tras canjear; rollback total si falla la entrega).
- /promo-code: canje de códigos por PD/PV (sensibles a mayúsculas/minúsculas,
usos limitados, 1 canje por cuenta).
- /admin/promo: panel para crear / editar / activar / desactivar / borrar
códigos de promoción.
- Tablas nuevas (sql/): home_tradecode, home_promocode, home_promoredemption.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bloqueaba /api/account/security-token (HTTP 500) y, por tanto, la activación
de 2FA. Las tablas home_* usan el id de cuenta de AzerothCore, no auth_user
(vacío tras la migración de Django). Aplicado en producción.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Activación de 2FA (TOTP) para el login del juego, guardando el secreto en
acore_auth.account.totp_secret tal como lo lee el bnetserver 3.4.3.
- lib/two-factor.ts: TOTP (HMAC-SHA1, 30s, 6 dígitos, ±1) idéntico al core
(verificado contra los vectores RFC 6238), Base32, otpauth, y codificado
del secreto: crudo por defecto o AES-128-GCM (ciphertext‖IV12‖tag12) si se
define TOTP_MASTER_SECRET (mismo hex que TOTPMasterSecret del servidor).
- Flujo seguro sin bloqueos: el secreto se genera y queda PENDIENTE en la
sesión; sólo se escribe en la cuenta tras verificar un código válido.
- /api/account/2fa: activar (password + token de seguridad), verificar y
desactivar (con código actual). QR generado en el servidor (el secreto no
sale a terceros).
- Página + componente fieles al markup (preview, pasos, copiar clave, ojos).
Verificado E2E: activar -> QR/secreto -> verificar -> totp_secret = 20 bytes
(igual al secreto escaneado) -> desactivar -> NULL.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
SumUp eliminó los webhooks, así que la acreditación no puede depender de que
el navegador vuelva al return_url. Se añade reconciliación consultando el
estado en la API de SumUp de los checkouts pendientes (fulfilled=0):
- reconcileSumUpCheckouts() en lib/sumup.ts: recorre los pendientes recientes
y acredita los que estén PAID (reclamo atómico idempotente).
- /d-points y /account reconcilian los pendientes de la cuenta al cargar, para
reflejar el saldo aunque el usuario no pasara por la página de éxito.
- /api/dpoints/reconcile: backstop global protegido con CRON_SECRET, pensado
para un systemd timer que lo llame periódicamente.
Verificado E2E con tarjeta de test: pago SumUp sin volver a la web -> el
backstop acredita los PD (idempotente). Credenciales y CRON_SECRET viven en
.env.local (fuera de git).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Los SVG no tenían tamaño intrínseco y se renderizaban enormes encima del
texto. Se porta el layout flex de .dnt-methods del tema original y se
dimensionan los iconos (22px, en línea con el texto) igual que se veía
PayPal. Los SVG llevan ahora width/height explícitos.
Verificado además el flujo Stripe de extremo a extremo (tarjeta de prueba
4242): pago -> página de éxito -> 100 PD acreditados por €1 con reclamo
atómico idempotente. Datos de prueba restaurados tras la verificación.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Elimina las pestañas de PayPal/dLocal/Crypto/Skrill y por país; deja
Información + Stripe + SumUp (las dos únicas pasarelas que se usarán).
- Stripe: totalmente funcional reutilizando createCheckoutSession + webhook
+ página de éxito. Nueva ruta /api/dpoints/checkout crea la sesión con
importe elegido por el usuario (1 unidad = 100 PD).
- SumUp: integración real (lib/sumup.ts) mediante checkout hospedado,
habilitada al definir SUMUP_API_KEY/SUMUP_MERCHANT_CODE; si no, avisa.
- Nuevo servicio de entrega `dpoints` (lib/paid-services.ts) que acredita
PD en home_api_points; entrega idempotente vía reclamo atómico.
- Página /d-points-success entrega ambos proveedores (session_id/ref).
- Iconos SVG generados para cada pasarela (stripe/sumup, marca + wordmark).
- Moneda configurable con DP_CURRENCY (por defecto EUR).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reproduce fielmente el panel de compra de PD de UltimoWoW como componente
cliente con pestañas (Información, PayPal, dLocal Go, Crypto, Skrill y
métodos alternativos por país: Argentina, Chile, Colombia, Perú).
- Página servidor con login requerido (redirige a /login y /select-account
como battlepay); inyecta username de la cuenta de juego e IP reales.
- Pestañas, tabla de rangos con mostrar/ocultar, y calculadora ARS
(dolarapi) migradas a estado/efectos de React.
- Formularios con casilla de T&C que habilita el botón; PayPal usa
PAYPAL_BUSINESS_EMAIL por entorno; dLocal/NOWPayments muestran aviso
hasta configurar su backend (no se fabrican credenciales/gateways).
- Banderas por país y logo de NOWPayments añadido a nw-logos.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Reescrita la página: box «Información» con la guía completa de Recluta a un
amigo (marca → nombre del reino) + box «Panel de Recluta a un amigo».
- Nuevo RecruitPanel: estadísticas (cuenta reclutada, amigos reclutados, amigos
al nivel 80, recompensas reclamadas X/6) + tabla de recompensas (objetivo,
objeto con icono y color de calidad, estado) con botón Reclamar para las
disponibles + sección «Recompensas disponibles». Sustituye a RecruitClaim.
- lib/recruit-claim: getRecruitStats (isRecruited + recruitedCount).
- Colores de calidad de objeto .q0-.q5 en globals.css.
- Sembradas las 6 recompensas en home_recruitreward (seed en sql/).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Página al estilo del tema con instrucciones de instalación (Interface/AddOns)
y una lista de addons (nombre + descripción + botón Descargar) — set inicial de
addons populares de WotLK con enlaces a sus páginas oficiales; editable en la
constante ADDONS de la página. Devuelve 200.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
El <form> dentro del <p> «Nombre de la cuenta» era HTML inválido y el mensaje
salía inline (en inglés «Wrong password» partía en «Add Wrong / Password»).
Se quita el form: input+botón (onClick, Enter) en un span-bloque .add-account-box
debajo del nombre, y el mensaje en .add-account-msg (display:block) en su propia
línea. Igual en ES y EN.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Junto al «Nombre de la cuenta» hay un botón «+» que pide la contraseña y crea
una nueva cuenta de juego bajo la Battle.net. Ruta /api/account/add-game-account:
verifica la contraseña (authenticate contra battlenet_accounts), calcula el
siguiente battlenet_index (máx 8) y crea la fila `account` con SRP6 Grunt
derivado de la contraseña (gameMakeRegistration) — igual que la activación, así
la cuenta sirve para entrar al juego. Recarga completa al crear/cambiar.
GameAccountSwitcher siempre presente (select si >1, texto si 1) + «+».
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- El desplegable WOW1/WOW2… ya no es un box aparte: va dentro del campo «Nombre
de la cuenta» (select compacto .account-select). Con una sola cuenta, texto plano.
- FIX iconos: el cambio de cuenta hacía router.refresh() (navegación suave) que en
algunos navegadores dejaba caer las hojas de estilo/FA y no se recuperaban. Ahora
hace window.location.reload() (recarga completa) → todo se recarga bien.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Si la Battle.net tiene más de una cuenta de juego, /account muestra un
desplegable «Cargar datos de la cuenta» (WOW1, WOW2…). Al cambiar, fija la
cuenta activa en la sesión vía /api/auth/select-account y refresca → toda la
página (datos, personajes, servicios, compras) opera sobre la cuenta elegida
(la sesión.accountId manda). Con una sola cuenta no aparece (como hasta ahora).
components/GameAccountSwitcher.tsx (client) + getGameAccounts en la page.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- «Nombre de la cuenta» muestra WOW<n> (de la cuenta de juego <bnetId>#<n>:
15#1 → WOW1; con varias, WOW1/WOW2/WOW3…) vía wowAccountName().
- maskEmail() pasa el correo a minúsculas siempre, sin importar cómo esté
guardado en la BD.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Los fieldsets Datos básicos/Estado de la cuenta ahora replican el markup nuevo:
iconos Font Awesome por campo (account-ficon), .separate account-info,
«Nombre de la cuenta», correos enmascarados (maskEmail), PD | PV en una línea
(dp-color/vp-color), Token, «2FA: Desactivado» (fa-lock-open red-info), Cuenta
baneada con enlace «Consultar historial» (/ban-history), reclutada y amigos.
Se quita Créditos Battlepay. Clases account-ficon/account-info al tema; claves
i18n accountName/twofaLabel/twofaOff/banHistoryLink.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
accountTools en el orden del markup: cambiar contraseña, 2FA (email-icon,
label purple-info), transferir PD, comercio de PD, código promoción, token,
recluta, renombrar hermandad, votar, adquirir PD. «Cambiar correo» (que
tenemos y no está en la lista) al final; panel admin el último (solo admin).
Tool.labelClass para el morado del 2FA. Iconos nuevos del sprite: trade-pd-icon
(-299 -928) y color .purple-info (#b172ff) añadidos al tema. Claves i18n nuevas
(svc2FA/TransferDP/TradePD/Promo/RenameGuild/DPoints). Rutas nuevas → 404 aún.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- characterTools reordenado y completado según el markup del usuario (14 items):
...gold, Rastreador de misiones (/quest), transfer, Recuperar personaje
(/restore-character), Recuperar ítems (/restore-items), Tienda (/store),
Enviar regalo (/send-gift). Se retira battlepay del panel (queda en cabecera).
Claves i18n nuevas (svcQuest/RestoreChar/RestoreItems/StoreItems/SendGift).
- Sprite de iconos actualizado a account-icons.png (de uw-ryu) que incluye el
icono de regalo; CSS: .acc-icon → .png, send-gift-icon (-424 -553) y promo-icon
reubicado (-174 -928), verificado que las 25 posiciones restantes coinciden.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Tercer panel plegable «HISTORIALES» (id account-history) con 4 herramientas:
Historial de PD y PV, transacciones, sanciones y seguridad (points-history/
trans-history/ban-history/security-history; iconos pointsh/dnth/banh/securityh).
Arranca CERRADO como los otros dos (el usuario lo abre al click). Prop
defaultOpen añadido a Panel (no usado aquí). Claves i18n en Account (es/en).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
La insignia de rango (antes fija a 1_Newbie/Nivel 1) ahora se calcula por los
PD de la cuenta: 14 niveles (getAccountRank en lib/account.ts) con umbrales
0/100/200…/900/1000/5000/10000/>10000 → imágenes nw-ranks 1_Newbie…14_GrandMaster
y título «Nivel N». Verificado end-to-end: dp=5500 → 12_Mentor «Nivel 12».
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ruta con el markup del tema (guía por tipo de problema + fieldset «Medios de
contacto»: Ticket/Discord/Foros/Correo). Las menciones de marca «UltimoWoW»
usan el nombre del reino (realmlist); emails y URLs se mantienen. Devuelve 200.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
«NovaWoW es una comunidad…» ahora usa el nombre del reino (realmlist).
Se elimina la constante SERVER_NAME (ya sin uso).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
brandify() sustituye «UltimoWoW»/«Nova WoW» por el nombre del reino (realmlist)
en título y contenido de las noticias, SOLO en el texto visible (fuera de las
etiquetas < >) para no romper las URLs de los enlaces (foro.ultimowow.com), y
respetando MAYÚSCULAS (ULTIMOWOW→TRINITY, UltimoWoW→Trinity). No toca dominios.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Menú de navegación: el desplegable «NovaWoW» ahora muestra el nombre del
reino de realmlist (Header pasa realmName a SiteHeader).
- Home: el título «NovaWoW WOTLK 3.4.3» y el nombre del recuadro de estado
(antes home_serverselection.name) usan el nombre del reino de realmlist.
Ahora el reino es «Trinity». El logo (alt) y el texto de intro se mantienen
como marca.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
El tema tiene `a:visited{color:#2471a9}` (espec. 0,1,1) que ganaba a
`.nw-page-link` (0,1,0) → Anterior/Siguiente y los números visitados salían
azules. Se añaden selectores `.nw-page-link:link/:visited/:hover` y
`.nw-page-current:link/:visited` (espec. 0,2,0) para ganar y mantener el
estilo del tema (crema + actual en dorado).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- /changelogs pasa a 5 commits por página.
- Botones de paginación (.nw-page-link) con el estilo de los botones del tema:
fondo tenue hsla, borde, padding y hover como el resto de la web; la página
actual en dorado. También afecta a la paginación del foro (consistencia).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
getCommits ahora recibe page/limit y devuelve {commits, totalPages} (del
header X-PageCount de Gitea). La página lee ?page, muestra 10 commits y usa
el componente Pagination (Anterior/1 2 3…/Siguiente).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Apuntaba a un tema del foro externo (foro.novawow.com); ahora va a la página
interna /changelogs (API de Gitea).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ruta que lista los últimos 50 commits del repo vía la API pública de Gitea
(lib/changelog.ts getCommits → /api/v1/repos/Inna/NovaWoW/commits). Cada
entrada: título (1ª línea), fecha, autor · sha (enlace al commit) y cuerpo
del mensaje (sin trailers Co-Authored-By). Estilo del tema (como noticias).
GITEA_URL/GITEA_REPO configurables por env (defaults al repo actual).
revalidate 300s para no golpear Gitea en cada visita.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- «Top de logros» ahora suma los PUNTOS de logros (no el nº): JOIN a
acore_world.achievement_points (id→points), poblada desde el DB2 Achievement
del build 3.4.3.54261 (wago.tools). Columna «Puntos de logros». Seed en
sql/achievement_points.sql (1912 logros).
- Fix: el logro «Nivel 80» es el id 13 (logros de nivel WotLK van de +10:
6=Nv10,7=Nv20…12=Nv70,13=Nv80), no el 20. «Primeros del reino» ahora se
puebla correctamente.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extiende la ruta dinámica [realm] para servir también /<slug>-players (slug
del reino en realmlist). PlayersBoard (server) consulta acore_characters:
- Personajes creados por clase (conteo por clase y facción) + totales.
- Top de muertes con honor (characters.totalKills/todayKills, LIMIT 10).
- Top de logros (nº de logros por personaje vía character_achievement;
los «puntos» no existen en la BD del servidor, vienen del DBC del cliente).
- Primeros del reino - Nivel 80 (primer personaje por fecha del logro 20 =
Nivel 80, overall/por clase/por raza; vacío si aún no hay nivel 80).
Imágenes reales del tema (nw-classes/nw-races/nw-icons). lib/players.ts con
los mapas de clase/raza/facción. RealmInfo extraído a su componente. Enlace
JUGADORES de la cabecera ahora dinámico (/<slug>-players), como REINO.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
El menú de la cabecera enlazaba a /novawow-realm fijo. Ahora Header (server)
calcula el slug desde realmlist (getRealmName + realmSlug) y lo pasa a
SiteHeader como realmHref → el enlace REINO apunta a /trinity-realm (o al
reino que haya). Acompaña a la ruta dinámica [realm].
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
La página del reino pasa de /novawow-realm (fija) a una ruta dinámica
app/[locale]/[realm] cuyo slug es <nombre-del-reino>-realm, con el nombre
tomado de acore_auth.realmlist (LIMIT 1). Ej.: realm «Trinity» → /trinity-realm.
realmSlug() normaliza el nombre (minúsculas, sin espacios). Si el slug no
coincide con el reino actual → notFound(). Convive con el catch-all [...rest]
y las rutas estáticas mantienen prioridad (verificado: /login, /account OK;
/foo y /novawow-realm → 404).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ruta con el markup del tema: título «Reino - <NOMBRE>» (nombre tomado de
acore_auth.realmlist con LIMIT 1, por si hay varios reinos; lib/realm.ts
getRealmName) y dos columnas realm-information-half con Rates y Horarios.
force-dynamic + generateMetadata con el nombre del reino.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
El override box-sizing:content-box incluía `select`, agrandándolo a 60px de
alto y 320px de ancho. El default del navegador para <select> es border-box
(40px), igual que la web original sin Tailwind. Se quita `select` del override
(los inputs de texto siguen en content-box, que sí es su default). Corrige el
campo de /download-client y todos los selects del sitio (recover, admin,
servicios de personaje).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ruta con el markup del tema + lógica interactiva (componente cliente
ClientDownload): selector de idioma (esES/esMX/enUS/enGB) que muestra el
selector de SO y la descripción del idioma; al elegir SO «Mac OS Catalina»
aparece la guía de CrossOver; el botón DESCARGAR abre el magnet link
correspondiente (btih por idioma + trackers comunes) o muestra error si
falta elegir. Clases del tema (game-download-select/g-download-button).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Guarda el script de siembra usado para poblar django_wow.home_noticia con las
50 noticias reales, para reimportar en el futuro. Cabecera con instrucciones
y aviso sobre el DELETE (vacía la tabla antes de insertar).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
La home ya lee las noticias de home_noticia; se sembraron las 50 noticias
reales del sitio en la BD. Ajustes de render: fecha en formato español largo
(«21 de junio de 2026») y contenido en <p> (con <br> y enlaces), como el
markup original.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
El botón Personalizar del banner ahora despliega un panel con checkboxes por
categoría (Necesarias fija+desactivada, Analíticas, Marketing) y «Guardar
preferencias», tal como el markup del usuario. Al guardar, escribe la cookie
uw_cookie_consent con la selección granular y sincroniza con Zaraz. Categorías
alineadas a las del panel (Necesarias/Analíticas/Marketing); ConsentStatus y
acceptAll/rejectAll usan las mismas. Estilos del panel en globals.css.
Verificado: Personalizar abre el panel, marcar Analíticas + Guardar deja la
cookie {necessary,analytics:true,marketing:false} y /cookies lo refleja.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Banner real `uw-cookie-content` (Rechazar/Personalizar/Aceptar todas) fijo
abajo y site-wide (montado en el layout, componente CookieBanner). Aparece
en la primera visita, guarda la decisión en la cookie uw_cookie_consent (1
año) y se sincroniza con Cloudflare Zaraz si está presente
(zaraz.consent.setAll / .modal). Estilos en globals.css.
- «Personalizar» abre el modal granular de Zaraz (o /cookies si no hay Zaraz).
- window.UWCookies {showBanner, revokeConsent, acceptAll, rejectAll}.
- Página /cookies: panel «Tu estado de consentimiento» (ConsentStatus) que
muestra los datos EN VIVO de la API de Zaraz (zaraz.consent.getAll()) por
propósito; si Zaraz no está, cae a la preferencia guardada por categoría.
Verificado con navegador: el banner aparece, «Aceptar todas» lo oculta y
escribe la cookie, y el panel de /cookies refleja el estado.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Crea la ruta de Declaración de Cookies con el markup del tema y las 5 tablas
de cookies (uw-cookie-table, estilizadas en globals.css) + estilos de listas
y botones (btn-uw). Los enlaces internos .php se cablean a las rutas Next
(/privacy-policy, /contact-us).
Sistema de consentimiento = Cloudflare Zaraz (elección del usuario):
components/CookieConsent.tsx expone window.UWCookies.showBanner()
(zaraz.consent.modal=true) y revokeConsent() (zaraz.consent.setAll(false)),
que Cloudflare activa cuando el dominio pasa por su proxy con Zaraz Consent;
degrada con aviso si Zaraz no está presente. El footer ya enlazaba aquí.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Crea la ruta Contáctanos con el markup del tema y el texto completo.
El footer ya enlazaba aquí. Título por metadata; devuelve 200.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Crea la ruta de Aviso legal con el markup del tema y el texto completo.
El footer ya enlazaba aquí. Título por metadata; devuelve 200.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Crea la ruta de Política de Reembolso con el markup del tema y el texto
completo. El footer ya enlazaba aquí. Título por metadata; devuelve 200.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Crea la ruta de Política de Privacidad con el markup del tema y el texto
completo. El footer ya enlazaba aquí. Título por metadata; devuelve 200.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>