/* static/css/chat.css — usa tokens de theme.css
   Interfaz de chat estilo "app de IA": sidebar con compañeros peludos/colectivos,
   info y cuenta (.app-shell de theme.css) + panel central de conversación
   con estado vacío centrado (saludo) que pasa a lista de mensajes en
   cuanto hay conversación. Topbar solo en móvil (gestionado por
   static/js/app.js: #app-sidebar-toggle abre/cierra el drawer). */

* { box-sizing: border-box; }

html, body {
    height: 100%;
}

body {
    display: flex;
    flex-direction: column;
}

/* El banner global de cookies es fixed/bottom y puede tapar el input del
   chat, que también vive pegado al fondo. Mientras esté visible (clase
   añadida por cookie_consent.html), reservamos espacio para que el input
   quede por encima: el padding se descuenta del alto de body (border-box),
   así que .chat-shell (flex:1 más abajo) recibe menos alto disponible y
   todo el layout se desplaza hacia arriba en vez de quedar tapado. */
body.has-cookie-banner {
    padding-bottom: 96px;
}
@media (max-width: 480px) {
    body.has-cookie-banner { padding-bottom: 128px; }
}
/* <1024px la sidebar pasa a position:fixed (theme.css, drawer off-canvas) —
   pero su regla base (no la de <1024px) ya trae "top:0; height:100dvh" sin
   condicionar a ningún breakpoint. Con top Y height fijados, el "bottom"
   del inset queda sobre-restringido y el navegador lo IGNORA (recalculado a
   partir de top+height, spec CSS2.1 §10.6.4) — así que reservar hueco vía
   "bottom" no tiene efecto. Hay que encoger el "height" en sí. */
@media (max-width: 1024px) {
    body.has-cookie-banner .chat-shell .app-sidebar { height: calc(100dvh - 96px); }
}
@media (max-width: 480px) {
    body.has-cookie-banner .chat-shell .app-sidebar { height: calc(100dvh - 128px); }
}

/* ============================================================
   SHELL — extiende .app-shell/.app-topbar/.app-content (theme.css)
   para que el panel de chat ocupe toda la altura disponible sin scroll
   de página (el scroll vive dentro de #chatWindow y de la sidebar).
============================================================ */
.chat-shell {
    flex: 1 1 auto;
    /* .app-shell (theme.css) fija min-height:100dvh, pensado para páginas
       que hacen scroll a nivel de página con sidebar sticky — eso ignoraría
       el padding-bottom del aviso de cookies de arriba. Aquí el alto lo da
       flex:1 dentro de body, así que se anula ese mínimo. */
    min-height: 0;
    /* Misma razón: la fila implícita de .app-shell es "auto" (crece con el
       contenido). El chat necesita el viewport fijo (solo #chatWindow hace
       scroll interno), así que forzamos la fila a no superar el alto
       disponible. */
    grid-template-rows: minmax(0, 1fr);
}
.chat-shell .app-main { min-height: 0; }
/* theme.css fija la sidebar a 100dvh a propósito (sticky en páginas que
   hacen scroll). En el chat su fila ya está acotada al alto real disponible
   (que puede ser menor con el aviso de cookies visible), así que aquí basta
   con el 100% de esa fila para que no se salga por debajo. Solo en desktop:
   en <1024px theme.css cambia la sidebar a position:fixed + inset (drawer
   off-canvas), y un height:100% aquí sobre-restringiría la caja (top+height
   ya la determinan del todo), anulando el "bottom" que le reserva hueco al
   aviso de cookies más abajo. */
@media (min-width: 1025px) {
    .chat-shell .app-sidebar { height: 100%; }
}

/* ============================================================
   SIDEBAR COLAPSABLE (solo escritorio) — el drawer de móvil (<1025px) ya
   tiene su propio botón/lógica compartida en static/js/app.js; esto es un
   colapso aparte, solo relevante en pantallas grandes donde la sidebar
   vive fija en el grid en vez de como drawer.
============================================================ */
@media (min-width: 1025px) {
    .chat-shell {
        grid-template-columns: 264px minmax(0, 1fr);
        transition: grid-template-columns var(--duration-slow) var(--ease-out);
    }
    .chat-shell .app-sidebar {
        /* Sin esto el contenido de la sidebar (labels, botones) se niega a
           encoger por debajo de su ancho mínimo y el colapso a 0 no llega a
           ocurrir — mismo motivo que el min-width:0 de más abajo. */
        min-width: 0;
        transition: padding var(--duration-slow) var(--ease-out);
    }
    .chat-shell.sidebar-collapsed {
        grid-template-columns: 0 minmax(0, 1fr);
    }
    .chat-shell.sidebar-collapsed .app-sidebar {
        padding-left: 0;
        padding-right: 0;
        overflow: hidden;
        border-right: none;
        pointer-events: none;
    }
}

/* .app-sidebar-brand (theme.css) ya es la píldora con degradado — aquí solo
   se re-declara como fila flex para que el link (icono+texto) y el botón de
   colapsar convivan dentro sin tocar su padding/alto/radio original. El
   link no puede ir DENTRO de un <button> ni viceversa (contenido
   interactivo anidado, inválido en HTML), así que el <a> pasa a envolver
   solo el icono+texto y el botón es su hermano — ambos dentro del mismo
   contenedor con fondo, sin cambiar las dimensiones de la píldora. */
.app-sidebar-brand {
    display: flex;
    align-items: center;
    gap: 6px;
}
.app-sidebar-brand-link {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    color: inherit;
    font: inherit;
    text-decoration: none;
}

/* Botón de colapsar, ahora dentro de la propia píldora (a la derecha del
   texto) en vez de flotando sobre su borde — se le resta 6px de alto al
   círculo respecto al icono (34px) para que quepa sin forzar la píldora a
   crecer, ya que .app-sidebar-brand no cambia su padding/alto original. */
.sidebar-collapse-btn {
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, .6);
    color: var(--color-primary-dark);
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-bounce);
}
.sidebar-collapse-btn:hover { background: rgba(255, 255, 255, .9); transform: scale(1.06); }
.sidebar-collapse-btn:active { transform: scale(.94); }
/* El drawer móvil ya se cierra con el hamburger del topbar — no dupliques
   el control aquí. */
@media (max-width: 1024px) {
    .sidebar-collapse-btn { display: none; }
}

.sidebar-expand-btn {
    position: fixed;
    top: var(--space-4);
    left: var(--space-4);
    z-index: var(--z-nav);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    box-shadow: var(--shadow-sm);
}
.sidebar-expand-btn:hover { box-shadow: var(--shadow-md); }
/* Solo tiene sentido en escritorio: en móvil la sidebar ya es un drawer
   off-canvas que se abre con el hamburger del topbar. El estado guardado en
   localStorage puede venir de una sesión de escritorio, así que forzamos el
   ocultado aquí en vez de confiar solo en el atributo "hidden" del JS. */
@media (max-width: 1024px) {
    .sidebar-expand-btn { display: none !important; }
}

/* Sin esto, el track/flex-item de .app-main hereda min-width:auto (el valor
   inicial) y se niega a encoger por debajo del ancho de su contenido más
   ancho (p.ej. el badge más largo o el input) — en <1024px theme.css usa
   "grid-template-columns: 1fr" (sin minmax(0,...)), así que sin este reset
   el shell se desborda del viewport en vez de que el texto/los badges
   hagan wrap. Mismo motivo por el que ya forzamos min-height:0 arriba,
   pero en el eje horizontal. */
.chat-shell .app-main,
.chat-content,
.chat-container,
#chatWindow {
    min-width: 0;
}

.chat-content {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    padding: var(--space-4) clamp(16px, 4vw, 32px);
    position: relative;
    /* .page-blob se posiciona a propósito medio fuera del lienzo (bleed
       decorativo). En el header original era position:fixed (recortado por
       el viewport); aquí es absolute dentro de este contenedor, así que sin
       overflow:hidden infla el scrollWidth real de la página y provoca
       scroll horizontal en móvil. */
    overflow: hidden;
}
@media (max-width: 1024px) {
    /* Sin .bottom-nav en el chat (el drawer de la sidebar cubre esa
       navegación), así que no hace falta reservar espacio extra abajo. */
    .chat-content { padding: var(--space-3); }
}

.avatar-initials-sm {
    width: 32px; height: 32px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--color-primary);
    color: var(--color-text-inverse);
    font-size: 13px;
    font-weight: 800;
    flex-shrink: 0;
}

/* Firma visual orgánica: un único blob muy sutil detrás del área de chat. */
.page-blob {
    position: absolute;
    top: -40px;
    right: -70px;
    width: 260px;
    height: 260px;
    opacity: .18;
    z-index: 0;
}
@media (max-width: 768px) {
    .page-blob { width: 180px; height: 180px; top: -20px; right: -60px; }
}

/* ============================================================
   SIDEBAR — botones "nuevo compañero peludo/colectivo" al estilo "+ nuevo chat"
============================================================ */
.sidebar-new-actions {
    display: grid;
    gap: 8px;
}
.sidebar-new-btn { width: 100%; justify-content: flex-start; }

/* min-width:0 en toda la cadena (grid item -> flex item) porque con el
   texto más largo de "compañeros peludos" el min-content por defecto ya no
   cabe en los 264px de la sidebar — mismo patrón de min-width:auto que en
   el resto de este archivo. Sin esto no envuelve en dos líneas: se recorta
   en silencio por el overflow-x implícito de .app-sidebar (overflow-y:auto
   activa overflow-x:auto también). */
.sidebar-pets { min-width: 0; }
.sidebar-pets .app-sidebar-label { min-width: 0; margin-bottom: 8px; }

/* Botón que abre el modal "Información del Compañero Peludo" — mismo
   lenguaje visual que .app-sidebar-nav (icono en píldora + etiqueta), con
   un estado "saved" (compañero peludo con ficha guardada) que lo tiñe de
   verde. */
.sidebar-pet-info-trigger {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    min-height: 44px;
    margin-top: 8px;
    padding: 10px 12px;
    border: 1px dashed var(--color-border-strong);
    border-radius: var(--radius-md);
    background: transparent;
    color: var(--color-text-muted);
    font-family: var(--font-body);
    font-size: var(--text-sm);
    font-weight: 600;
    text-align: left;
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease-out), border-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
}
.sidebar-pet-info-trigger span {
    /* Sin flex+min-width:0 el span (item flex) hereda min-width:auto y se
       niega a encoger por debajo del ancho de su propio texto, así que el
       ellipsis de abajo nunca llega a activarse — mismo motivo por el que
       hubo que resetearlo en otros sitios de este archivo (ver .chat-shell
       .app-main más arriba). */
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.sidebar-pet-info-trigger:hover { background: var(--color-surface-alt); color: var(--color-text); border-color: var(--color-border-strong); }
.sidebar-pet-info-trigger.saved {
    border-style: solid;
    border-color: var(--color-primary);
    background: var(--color-primary-light);
    color: var(--color-primary-dark);
}

/* ============================================================
   MODAL "Información del Compañero Peludo" — el <dialog class="chubi-modal">
   base (tamaño, [open], ::backdrop, header) vive en theme.css, compartido
   con cualquier otra página. Aquí solo el estilo del formulario interno,
   que es específico del chat. El backdrop se cierra a clic desde el
   listener en el <script> del template.
============================================================ */
.chubi-modal label {
    display: block;
    margin-bottom: 6px;
    font-weight: 600;
    font-size: var(--text-xs);
    color: var(--color-text);
}

.chubi-modal input,
.chubi-modal select,
.chubi-modal textarea {
    display: block;
    width: 100%;
    margin-bottom: var(--space-3);
    padding: 10px 12px;
    border: 1.5px solid var(--color-border);
    border-radius: var(--radius-md);
    font-family: var(--font-body);
    font-size: 16px; /* evita zoom en iOS */
    color: var(--color-text);
    background: var(--color-surface);
    transition: border-color var(--duration-fast) var(--ease-out), box-shadow var(--duration-fast) var(--ease-out);
}
.chubi-modal textarea { min-height: 72px; resize: vertical; }

.chubi-modal .age-input-row {
    display: flex;
    gap: 8px;
    margin-bottom: var(--space-3);
}
.chubi-modal .age-input-row input,
.chubi-modal .age-input-row select {
    margin-bottom: 0;
}
.chubi-modal .age-input-row input { flex: 2 1 0; min-width: 0; }
.chubi-modal .age-input-row select { flex: 1 1 82px; min-width: 82px; }

.chubi-modal input:focus,
.chubi-modal select:focus,
.chubi-modal textarea:focus {
    outline: none;
    border-color: var(--color-primary);
    box-shadow: var(--shadow-focus);
}

/* Selector de compañeros peludos/colectivos (en .sidebar-pets, fuera del form) */
.pet-management {
    display: none;
}
.pet-management-row {
    display: flex;
    gap: 6px;
    align-items: center;
}
.pet-management-row select {
    flex: 1 1 auto;
    width: 100%;
    min-height: 40px;
    padding: 8px 10px;
    border: 1.5px solid var(--color-border);
    border-radius: var(--radius-md);
    font-family: var(--font-body);
    font-size: var(--text-sm);
    color: var(--color-text);
    background: var(--color-surface);
}
.pet-management-row .btn-icon { flex-shrink: 0; width: 40px; height: 40px; }
.pet-management-row .btn-icon:disabled { opacity: .4; cursor: not-allowed; }

/* Fila de acciones del formulario (guardar / QR / cerrar) */
.form-actions {
    margin-top: var(--space-1);
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    align-items: center;
}
.form-actions button { margin: 0; }

.chubi-modal .form-actions button[type="submit"] {
    min-height: 40px;
    padding: 10px 18px;
    background-color: var(--color-primary);
    color: var(--color-text-inverse);
    border: none;
    border-radius: var(--radius-pill);
    font-size: var(--text-xs);
    font-weight: 700;
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-bounce);
}
.chubi-modal .form-actions button[type="submit"]:hover {
    background-color: var(--color-primary-dark);
    transform: translateY(-2px);
}

#downloadQRButton {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-height: 40px;
    padding: 10px 14px;
    background-color: var(--color-accent);
    color: var(--color-text-inverse);
    border: none;
    border-radius: var(--radius-pill);
    font-size: var(--text-xs);
    font-weight: 700;
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-bounce);
}
#downloadQRButton:hover { background-color: var(--color-accent-dark); transform: translateY(-2px); }

#closeDetailsButton {
    min-height: 40px;
    padding: 10px 14px;
    background-color: transparent;
    color: var(--color-text-muted);
    border: 1.5px solid var(--color-border-strong);
    border-radius: var(--radius-pill);
    font-size: var(--text-xs);
    font-weight: 700;
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
}
#closeDetailsButton:hover { background-color: var(--color-surface); color: var(--color-text); }

/* ============================================================
   SIDEBAR — cuenta (pie de la sidebar)
============================================================ */
.sidebar-user-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 12px;
}
.sidebar-user-info {
    display: grid;
    gap: 1px;
    min-width: 0;
}
.sidebar-user-info strong {
    font-size: var(--text-sm);
    color: var(--color-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.sidebar-user-info .text-muted { font-size: var(--text-xs); }

.sidebar-guest-cta { display: grid; gap: 8px; padding: var(--space-2) var(--space-1); }
/* theme.css estiliza cualquier <a> dentro de .app-sidebar-footer como item
   de navegación (fondo transparente, texto mudo, alineado a la izquierda) —
   correcto para los links del pie, pero pisa el botón de CTA de invitado.
   Un selector más específico (dos clases) gana sin depender del orden. */
.app-sidebar-footer .sidebar-guest-cta a.btn-primary {
    background: var(--color-primary);
    color: var(--color-text-inverse);
    justify-content: center;
    text-align: center;
}
.app-sidebar-footer .sidebar-guest-cta a.btn-primary:hover {
    background: var(--color-primary-dark);
    color: var(--color-text-inverse);
}

/* Enlace a la tienda externa — deliberadamente más discreto que el resto
   del nav (fuente más pequeña, separado con un borde) para no competir con
   las acciones principales de la sidebar; sigue siendo un enlace fácil de
   encontrar, no una acción destacada. Fuera del bloque user/guest a
   propósito: se ve igual para todo el mundo. */
.sidebar-store-link {
    margin-top: 6px;
    padding-top: var(--space-3);
    border-top: 1px solid var(--color-border);
    font-size: var(--text-xs) !important;
    color: var(--color-text-faint) !important;
}
.sidebar-store-link:hover { color: var(--color-primary-dark) !important; }
/* Sin la píldora de color que llevan los iconos del nav principal (theme.css
   .app-sidebar-footer a .icon) — aquí el icono va suelto y pequeño, a juego
   con el peso visual reducido que se busca para este enlace. */
.sidebar-store-link .icon {
    width: 16px !important;
    height: 16px !important;
    padding: 0 !important;
    background: none !important;
    border-radius: 0 !important;
    color: inherit !important;
}

/* ============================================================
   CONTENEDOR DEL CHAT
============================================================ */
.chat-container {
    position: relative;
    z-index: 1;
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
    max-width: 760px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

/* Ventana de mensajes */
#chatWindow {
    flex: 1 1 auto;
    min-height: 0;
    padding: var(--space-3) var(--space-2);
    overflow-y: auto;
    overflow-x: hidden;
    display: flex;
    flex-direction: column;
    gap: 12px;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
}

/* Estado vacío: saludo centrado, al estilo "¿por dónde empezamos?" */
#chatWindow.is-empty-state {
    justify-content: center;
    align-items: center;
}

.chat-empty-state {
    max-width: 540px;
    margin: 0 auto;
    padding: var(--space-2) var(--space-4);
    text-align: center;
    display: grid;
    justify-items: center;
    /* Compacto a propósito: este saludo tiene que caber sin scroll incluso
       en ventanas bajas (portátiles, zoom alto) — #chatWindow lo centra
       verticalmente, pero si no cabe, lo desborda y obliga a hacer scroll
       para ver un simple mensaje de bienvenida. */
    gap: 6px;
    animation: chubi-pop-in var(--duration-slow) var(--ease-bounce);
}
.chat-empty-avatar {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    object-fit: contain;
    background: var(--color-surface);
    padding: 6px;
    box-sizing: border-box;
    margin-bottom: 2px;
    box-shadow: var(--shadow-md);
}
.chat-empty-state h1 {
    font-size: var(--text-xl);
    margin: 0;
}
.chat-empty-subtitle {
    color: var(--color-text-muted);
    font-size: var(--text-sm);
    max-width: 44ch;
    margin: 0;
}
.chat-empty-topics {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 6px;
    margin-top: 2px;
}

/* Selector de compañero peludo/colectivo en el estado vacío — opciones
   reales para elegir con quién chatear, no texto decorativo. Solo se
   muestra cuando no hay ninguno elegido todavía (ver updateEmptyStatePicker() en el
   <script>). Deliberadamente NO reutiliza .badge: el fondo de .badge
   (--color-surface-alt) apenas contrasta contra el verde pastel de la
   página — aquí necesitan leerse como opciones pulsables, no como etiquetas. */
.chat-empty-pets { display: grid; justify-items: center; gap: 10px; margin-top: 2px; }
.chat-empty-pets-label {
    margin: 0;
    font-size: var(--text-sm);
    font-weight: 700;
    color: var(--color-text);
}
.chat-empty-topics.chat-empty-pets-list { gap: 8px; }
.badge-chip {
    display: inline-flex;
    align-items: center;
    padding: 9px 20px;
    border: 1.5px solid var(--color-border);
    border-radius: var(--radius-pill);
    background: var(--color-surface);
    color: var(--color-primary-dark);
    font-family: var(--font-body);
    font-size: var(--text-sm);
    font-weight: 700;
    box-shadow: var(--shadow-xs);
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease-out), border-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out), box-shadow var(--duration-fast) var(--ease-bounce), transform var(--duration-fast) var(--ease-bounce);
}
.badge-chip:hover {
    background: var(--color-primary);
    border-color: var(--color-primary);
    color: var(--color-text-inverse);
    box-shadow: var(--shadow-sm);
    transform: translateY(-2px);
}
.badge-chip:active { transform: scale(.96); }
.badge.badge-chip:active { transform: scale(.96); }

.chat-empty-state .disclaimer {
    font-size: var(--text-xs);
    color: var(--color-text-faint);
    margin-top: var(--space-2);
    max-width: 48ch;
}

/* Burbujas de mensaje */
.message {
    padding: 12px 18px;
    border-radius: var(--radius-lg);
    max-width: 80%;
    word-break: break-word;
    line-height: 1.5;
    font-size: var(--text-sm);
    animation: chubi-pop-in var(--duration-slow) var(--ease-bounce);
}

.message.user {
    background-color: var(--color-primary);
    color: var(--color-text-inverse);
    border-bottom-right-radius: 6px;
    align-self: flex-end;
    text-align: left;
    box-shadow: var(--shadow-xs);
}

.message.bot {
    background-color: var(--color-surface);
    color: var(--color-text);
    border: 1.5px solid var(--color-border);
    border-bottom-left-radius: 6px;
    align-self: flex-start;
    text-align: left;
    box-shadow: var(--shadow-xs);
}

.message.bot p { margin: 0 0 10px 0; }
.message.bot p:last-child { margin-bottom: 0; }

.message.bot ul { padding-left: 20px; margin: 10px 0 0 0; }
.message.bot li { margin-bottom: 5px; }

.message.bot strong { color: var(--color-primary-dark); font-weight: 700; }

/* Indicador de "Escribiendo..." */
#typing-indicator {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 18px;
}
#typing-indicator img {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    object-fit: contain;
    background: var(--color-surface);
    padding: 3px;
    box-sizing: border-box;
}
#typing-indicator span {
    width: 8px;
    height: 8px;
    background-color: var(--color-text-faint);
    border-radius: 50%;
    animation: typing-dot 1.4s infinite ease-in-out;
}
#typing-indicator span:nth-child(2) { animation-delay: .2s; }
#typing-indicator span:nth-child(3) { animation-delay: .4s; }

@keyframes typing-dot {
    0%, 80%, 100% { transform: scale(0); }
    40% { transform: scale(1); }
}

.disclaimer {
    font-size: var(--text-xs);
    color: var(--color-text-muted);
    margin-top: 10px;
    display: block;
}

.error-message {
    color: var(--color-danger-dark);
    font-weight: 700;
    align-self: center;
    text-align: center;
    background: var(--color-danger-bg);
    border: 1px solid var(--color-danger);
    border-radius: var(--radius-md);
    padding: 10px 16px;
}

.info-message {
    color: var(--color-text-muted);
    font-weight: 600;
    align-self: center;
    text-align: center;
    background: transparent;
    border: none;
    padding: 4px;
    font-size: var(--text-xs);
}

/* ============================================================
   INPUT DE MENSAJE (siempre visible, sin taparse con el teclado)
============================================================ */
.input-container {
    flex-shrink: 0;
    display: flex;
    align-items: flex-end;
    gap: 8px;
    padding: var(--space-2);
    background-color: var(--color-surface);
    border: 1.5px solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-md);
    padding-bottom: calc(var(--space-2) + env(safe-area-inset-bottom, 0px));
}

.hidden-input { display: none; }

#userMessage {
    flex-grow: 1;
    padding: 10px 8px;
    border: none;
    border-radius: var(--radius-md);
    font-family: var(--font-body);
    font-size: 16px; /* evita zoom en iOS */
    color: var(--color-text);
    background: transparent;
    height: auto;
    min-height: 44px;
    max-height: 140px;
    resize: none;
    overflow-y: auto;
}
#userMessage:focus { outline: none; }

/* Botón enviar: icono circular sobre fondo primario. */
#sendButton {
    flex-shrink: 0;
    width: 44px;
    height: 44px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background-color: var(--color-primary);
    color: var(--color-text-inverse);
    border: none;
    border-radius: var(--radius-pill);
    cursor: pointer;
    box-shadow: var(--shadow-sm);
    transition: background-color var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-bounce), box-shadow var(--duration-fast) var(--ease-bounce);
}
#sendButton .icon { transition: transform var(--duration-fast) var(--ease-bounce); }
#sendButton:hover:not(.disabled) {
    background-color: var(--color-primary-dark);
    transform: translateY(-2px) scale(1.06);
    box-shadow: var(--shadow-md);
}
#sendButton:hover:not(.disabled) .icon { transform: translateX(2px) scale(1.1); }
#sendButton:active:not(.disabled) { transform: scale(.92); }
#sendButton.disabled {
    background-color: var(--color-border-strong);
    color: var(--color-text-faint);
    cursor: not-allowed;
    box-shadow: none;
}

/* Previsualización de imagen adjunta */
#imagePreviewContainer {
    text-align: left;
    flex-shrink: 0;
}
#imagePreviewContainer > div { position: relative; display: inline-block; animation: chubi-pop-in var(--duration-base) var(--ease-bounce); }
#imagePreviewContainer img {
    max-width: 96px;
    max-height: 96px;
    border-radius: var(--radius-md);
    border: 1.5px solid var(--color-border);
    display: block;
}
#imagePreviewContainer button {
    position: absolute;
    top: -8px;
    right: -8px;
    width: 22px;
    height: 22px;
    background: var(--color-danger);
    color: var(--color-text-inverse);
    border: 2px solid var(--color-surface);
    border-radius: 50%;
    cursor: pointer;
    line-height: 1;
    padding: 0;
    font-size: 14px;
}

/* Mensaje de límite alcanzado */
.limit-message-container {
    flex-shrink: 0;
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    padding: var(--space-5);
    text-align: center;
    box-shadow: var(--shadow-sm);
    animation: chubi-pop-in var(--duration-slow) var(--ease-bounce);
    align-self: center;
    max-width: 420px;
}
.limit-message-container p {
    font-size: var(--text-sm);
    color: var(--color-text);
    margin-bottom: var(--space-3);
}
.limit-message-container button {
    min-height: 44px;
    background-color: var(--color-primary);
    color: var(--color-text-inverse);
    padding: 12px 24px;
    border: none;
    border-radius: var(--radius-pill);
    cursor: pointer;
    font-size: var(--text-sm);
    font-weight: 700;
    box-shadow: var(--shadow-sm);
    transition: background-color var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-bounce), box-shadow var(--duration-fast) var(--ease-bounce);
}
.limit-message-container button:hover { background-color: var(--color-primary-dark); transform: translateY(-3px) scale(1.02); box-shadow: var(--shadow-md); }
.limit-message-container button:active { transform: scale(.96); }

/* ============================================================
   RESPONSIVE
============================================================ */
@media (max-width: 768px) {
    .message { max-width: 88%; font-size: var(--text-xs); padding: 10px 14px; }
}

/* ============================================================
   TOAST DE ACTUALIZACIÓN DEL SERVICE WORKER — mismo componente que
   static/css/landing.css (.sw-update-toast), copiado aquí porque chat.html
   no carga landing.css. El chat es ahora la raíz de la app, así que
   necesita el mismo registro de Service Worker que antes solo vivía en
   index.html (ver el <script> al final de templates/chat.html).
============================================================ */
.sw-update-toast {
    display: none;
    position: fixed;
    bottom: var(--space-5);
    left: 50%;
    transform: translateX(-50%);
    background-color: var(--color-text);
    color: #fff;
    padding: var(--space-4) var(--space-5);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    z-index: var(--z-toast);
    animation: chubi-sw-toast-in .3s var(--ease-out);
}
@keyframes chubi-sw-toast-in {
    from { transform: translateX(-50%) translateY(100px); opacity: 0; }
    to { transform: translateX(-50%) translateY(0); opacity: 1; }
}
.sw-update-content { display: flex; align-items: center; gap: var(--space-4); }
.sw-update-content span { font-size: var(--text-sm); }
.sw-update-btn {
    padding: 8px 16px;
    background-color: var(--color-accent);
    color: #fff;
    border: none;
    border-radius: var(--radius-pill);
    font-size: var(--text-xs);
    font-weight: 700;
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease-out);
}
.sw-update-btn:hover { background-color: var(--color-accent-dark); }
