/* whereubro — hoja de estilos unica. */

/* El atributo hidden tiene que ganar siempre.
   Cualquier regla propia que fije display (.btn es inline-flex) pisa el
   [hidden] del navegador, porque el CSS del autor manda sobre el suyo. El
   resultado es que element.hidden = true deja de ocultar nada y no avisa: el
   boton de activar notificaciones seguia a la vista aun estando ya activadas. */
[hidden] { display: none !important; }

:root {
    /* Los controles nativos siguen a este token: sin él, el tema oscuro venía
       con las barras de scroll y los desplegables en claro. */
    color-scheme: light dark;

    /* La misma paleta que las páginas públicas: papel cálido, tinta marrón y
       miel. Antes la web era ultramar y la aplicación azul frío, y al entrar se
       notaba el salto como si fueran dos productos.

       Los nombres se quedan en inglés (--bg, --accent) porque son los de una
       interfaz, no los de una identidad; los valores son los de site.css. */
    --bg: #1B1512;
    --surface: #241C18;
    --surface-2: #2F251F;
    --border: #3A2E27;
    --text: #F4EBE2;
    --text-dim: #B5A092;
    --accent: #E0A03A;
    /* Semánticos, separados del acento a propósito: "está bien", "esto ya tiene
       tiempo" y "esto ha fallado" no pueden confundirse con la marca. */
    --ok: #93B27A;
    --warn: #E07B4A;
    --danger: #D9605C;

    /* Cada color de estado va dos veces: el de arriba pinta fondos, bordes y
       marcadores; este pinta el texto de ese mismo estado.
       El motivo es que un distintivo usa el color para las dos cosas a la vez
       —letra saturada sobre un fondo del mismo tono al 12 %— y ahí la letra se
       queda en 3-4:1. Separarlos deja el fondo como estaba y sube solo la
       letra. En oscuro varios coinciden con el color base porque ya cumplían. */
    --accent-texto: #E0A03A;
    --ok-texto: #93B27A;
    --warn-texto: #E28253;
    --danger-texto: #E07D79;

    /* --border marca separaciones que se pueden intuir; el contorno de un campo
       de texto es lo único que dice dónde empieza el campo, así que necesita
       3:1 contra la superficie. En claro el input era --surface-2 sobre
       --surface (1.13:1) con un borde de 1.49:1: prácticamente invisible. */
    --borde-control: #776F6A;

    --radius: 14px;
    --tabbar-h: 60px;

    /* Lo que ocupa de verdad la barra inferior.
       En el iPhone, con la web añadida a la pantalla de inicio, el sistema
       reserva una franja abajo para el indicador de inicio. Como el padding va
       por dentro de la altura (box-sizing: border-box), sumarla sin ampliar la
       altura dejaba el contenido en 26 px: los iconos y sus textos salían
       diminutos. En el navegador no se notaba, porque ahí esa franja es cero. */
    --tabbar-total: calc(60px + env(safe-area-inset-bottom, 0px));
}

/* Tema claro: la superficie sube a casi blanco cálido para que las tarjetas se
   despeguen del papel, que es más tostado. */
@media (prefers-color-scheme: light) {
    :root {
        --bg: #F7F1EB;
        --surface: #FFFCF9;
        --surface-2: #F1E8DF;
        --border: #DECFC0;
        --text: #2B211B;
        --text-dim: #6E5B4E;
        --accent: #B4761A;
        --ok: #4F6B41;
        --warn: #A65A20;
        --danger: #A8403C;
        --accent-texto: #855713;
        --ok-texto: #4B663E;
        --warn-texto: #904E1C;
        --danger-texto: #A13D3A;
        --borde-control: #8E847B;
    }
}

/* El conmutador de tema tiene que ganar a la preferencia del sistema en los dos
   sentidos, no solo al pasar a oscuro. */
:root[data-theme="light"] {
    color-scheme: light;
    --bg: #F7F1EB;
    --surface: #FFFCF9;
    --surface-2: #F1E8DF;
    --border: #DECFC0;
    --text: #2B211B;
    --text-dim: #6E5B4E;
    --accent: #B4761A;
    --ok: #4F6B41;
    --warn: #A65A20;
    --danger: #A8403C;
    --accent-texto: #855713;
    --ok-texto: #4B663E;
    --warn-texto: #904E1C;
    --danger-texto: #A13D3A;
    --borde-control: #8E847B;
}

:root[data-theme="dark"] {
    color-scheme: dark;
    --bg: #1B1512;
    --surface: #241C18;
    --surface-2: #2F251F;
    --border: #3A2E27;
    --text: #F4EBE2;
    --text-dim: #B5A092;
    --accent: #E0A03A;
    --ok: #93B27A;
    --warn: #E07B4A;
    --danger: #D9605C;
    --accent-texto: #E0A03A;
    --ok-texto: #93B27A;
    --warn-texto: #E28253;
    --danger-texto: #E07D79;
    --borde-control: #776F6A;
}

* { box-sizing: border-box; }

html, body {
    margin: 0;
    height: 100%;
    background: var(--bg);
    color: var(--text);
    font: 16px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    -webkit-font-smoothing: antialiased;
}

h1 { font-size: 1.35rem; margin: 0 0 .5rem; }
h2 { font-size: 1rem; margin: 0 0 .5rem; }
a { color: var(--accent-texto); }

/* Foco de teclado. No había ninguna regla en toda la aplicación: se veía lo que
   pintase el navegador, que sobre estos marrones a veces es un contorno negro
   invisible. Va con offset para que se lea también sobre los botones de acento,
   y en el mismo sitio para todo lo que se puede enfocar. */
/* Sin border-radius: el contorno ya sigue la forma que tenga el elemento, y
   redondearlo aquí le cambiaba las esquinas a los botones de la web pública,
   que son rectos a propósito. */
:where(a, button, input, select, textarea, summary, [tabindex]:not([tabindex="-1"])):focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* Toda la interfaz se toca con el dedo: sin esto el navegador móvil espera
   300 ms por si llega un segundo toque, y cada botón responde tarde. */
button, a, .tab, summary, label, select, input[type="submit"] {
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
}

/* Salto al contenido: primer elemento enfocable de la página, escondido hasta
   que alguien lo enfoca con el tabulador. Sin él, llegar al mapa con el teclado
   obliga a pasar por la barra de navegación entera en cada página. */
.salto {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 100;
    padding: .7rem 1.1rem;
    background: var(--surface);
    color: var(--text);
    border: 1px solid var(--borde-control);
    border-radius: 0 0 var(--radius) 0;
    text-decoration: none;
}
.salto:focus { left: 0; }

/* --- Botones --- */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .55rem;
    padding: .7rem 1.1rem;
    border: 1px solid transparent;
    border-radius: var(--radius);
    background: var(--accent);
    /* Casi negro, no blanco. El blanco sobre la miel se quedaba en 2.27:1 en
       oscuro y 3.79:1 en claro —el peor contraste de todo el proyecto, y en el
       botón principal—; este da 8.62:1 y 5.16:1. El mismo valor sirve para los
       dos temas porque las dos mieles son claras. */
    color: #140A02;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
    text-decoration: none;
    /* Objetivo tactil comodo con una sola mano. */
    min-height: 46px;
}

/* Atenuar un botón desactivado con opacidad rebaja también su contraste, así que
   se apaga cambiando el color y no la transparencia. */
.btn:disabled {
    background: var(--surface-2);
    color: var(--text-dim);
    border-color: var(--border);
    cursor: default;
}

.btn--ghost {
    background: transparent;
    border-color: var(--borde-control);
    color: var(--text);
}

.btn--danger { background: transparent; border-color: var(--borde-control); color: var(--danger-texto); }

.btn--google { background: #fff; color: #1f2328; border-color: #dadce0; width: 100%; }
.btn__icon { width: 20px; height: 20px; }

/* --- Portada --- */

.landing {
    min-height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2rem;
    padding: 2rem 1.25rem 3rem;
}

.landing__card {
    width: 100%;
    max-width: 24rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 20px;
    padding: 2rem 1.5rem;
    text-align: center;
}

.landing__logo { width: 46px; height: 46px; fill: var(--accent); }
.landing__lead { color: var(--text-dim); margin: .25rem 0 1.5rem; }
.landing__note { color: var(--text-dim); font-size: .82rem; margin: 1rem 0 0; }

.landing__features {
    list-style: none;
    padding: 0;
    margin: 0;
    max-width: 24rem;
    display: grid;
    gap: .6rem;
    color: var(--text-dim);
    font-size: .88rem;
}

.landing__features strong { color: var(--text); }

.alert {
    padding: .7rem .9rem;
    border-radius: 10px;
    font-size: .88rem;
    text-align: left;
    margin: 0 0 1rem;
}

/* La mezcla baja de 16 % a 12 %: cuanto más color lleva el fondo, más se acerca
   a la letra y menos se lee. Con el color de texto aparte, 12 % cumple en los
   dos temas. */
.alert--error { background: color-mix(in srgb, var(--danger) 12%, transparent); color: var(--danger-texto); }
.alert--info { background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--accent-texto); }

/* --- Mapa --- */

.mapview { position: fixed; inset: 0; bottom: var(--tabbar-total); }

/* MapLibre marca su contenedor como position:relative; se fija aqui la altura de
   forma explicita para no depender de que hoja gane por orden de carga. */
.mapview__canvas { position: absolute; inset: 0; width: 100%; height: 100%; }

.panel {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    background: var(--surface);
    border-top: 1px solid var(--border);
    border-radius: 18px 18px 0 0;
    padding: .5rem 1rem 1rem;
    max-height: 62%;
    display: flex;
    flex-direction: column;
    box-shadow: 0 -8px 28px rgba(0,0,0,.28);
    transition: transform .22s ease;
    /* El panel va encima del mapa: sin esto, seguir arrastrando al final de la
       lista mueve el mapa de debajo, o recarga la página en el móvil. */
    overscroll-behavior: contain;
}

.panel.is-collapsed { transform: translateY(calc(100% - 56px)); }

.panel__head { display: flex; align-items: center; justify-content: space-between; }
.panel__head h1 { font-size: 1rem; margin: .35rem 0; }

.panel__toggle {
    background: none; border: 0; padding: .4rem; cursor: pointer;
    color: var(--text-dim);
    min-width: 44px; min-height: 44px;
}
.panel__toggle svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2; }
.panel.is-collapsed .panel__toggle svg { transform: rotate(180deg); }

.panel__status { min-height: 1.2rem; margin: .1rem 0 .4rem; font-size: .85rem; color: var(--text-dim); }
.panel__status.is-error { color: var(--danger-texto); }
.panel__status.is-ok { color: var(--ok-texto); }

.panel__foot { padding-top: .6rem; }
.panel__foot .btn { width: 100%; }

.people { list-style: none; margin: 0; padding: 0; overflow-y: auto; overscroll-behavior: contain; display: grid; gap: .5rem; }
.people__empty { color: var(--text-dim); font-size: .9rem; padding: .5rem 0; }

.person {
    display: grid;
    grid-template-columns: 40px 1fr auto;
    align-items: center;
    gap: .75rem;
    padding: .6rem;
    background: var(--surface-2);
    border-radius: 12px;
}

/* Un nombre sale de la cuenta de Google y puede ser larguísimo. Una celda de
   grid no baja de su contenido salvo que se le diga: sin esto el 1fr se
   estiraba y empujaba el botón fuera de la fila.
   Solo la columna del texto, que es la segunda: dárselo también a la de los
   botones los encogía por debajo de su etiqueta y el texto se salía de la caja. */
.person > *:nth-child(2), .member > *:nth-child(2) { min-width: 0; }

/* --- Avatar ---
   Un solo componente para el marcador del mapa, las listas de gente, los
   miembros del círculo y la actividad. Lo pinta `avatarElement()` en app.js.

   El marco llega con sus cuatro colores puestos en el elemento y aquí se elige
   cuál pinta, con el mismo escalonado que la paleta: base oscuro, media query
   para el claro y los dos [data-theme] para que el conmutador gane en los dos
   sentidos. Hacerlo así, y no eligiendo el color en JavaScript, es lo que hace
   que el avatar siga al cambio de tema sin recargar la página. */
.avatar {
    --avatar-color: var(--marco-oscuro, var(--accent));
    --avatar-ink: var(--tinta-oscura, #140A02);
    position: relative;
    border-radius: 50%;
    display: grid; place-items: center;
}

@media (prefers-color-scheme: light) {
    .avatar {
        --avatar-color: var(--marco-claro, var(--accent));
        --avatar-ink: var(--tinta-clara, #140A02);
    }
}

:root[data-theme="light"] .avatar {
    --avatar-color: var(--marco-claro, var(--accent));
    --avatar-ink: var(--tinta-clara, #140A02);
}

:root[data-theme="dark"] .avatar {
    --avatar-color: var(--marco-oscuro, var(--accent));
    --avatar-ink: var(--tinta-oscura, #140A02);
}

/* La foto se recorta con su propio border-radius y no con overflow:hidden en el
   contenedor: la pegatina va dentro del mismo elemento y overflow la cortaría. */
.avatar__foto { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; display: block; }
.avatar__iniciales { color: var(--avatar-ink); font-weight: 700; line-height: 1; }

/* La pegatina se apoya en un disco de la superficie para leerse también encima
   de una foto, que es donde no hay ningún color previsible debajo. */
.avatar__pegatina {
    position: absolute; right: 0; bottom: 0;
    width: 42%; height: 42%;
    display: grid; place-items: center;
    background: var(--surface);
    border-radius: 50%;
    box-shadow: 0 0 0 1px var(--border);
    font-size: .62rem;
    line-height: 1;
    pointer-events: none;
}

.person__avatar {
    width: 40px; height: 40px;
    background: var(--avatar-color);
    font-size: .95rem;
}

.person__name { font-weight: 600; overflow-wrap: anywhere; }
.person__meta { font-size: .8rem; color: var(--text-dim); }
.person__meta.is-stale { color: var(--warn-texto); }
.person__meta.is-none { color: var(--text-dim); font-style: italic; }

.person__btn {
    border: 1px solid var(--borde-control);
    background: transparent;
    color: var(--text);
    border-radius: 10px;
    padding: .5rem .75rem;
    font: inherit; font-size: .85rem; font-weight: 600;
    cursor: pointer;
    min-height: 44px;
}
.person__btn:disabled { color: var(--text-dim); border-color: var(--border); cursor: default; }

/* Marcadores */

/* El anillo es el marco que ha elegido cada cual, no un estado. Antes codificaba
   tres cosas con color —miel normal, verde tú, ámbar dato viejo— y los tres se
   han mudado a la forma y a la saturación para dejarle el sitio. */
.marker {
    width: 38px; height: 38px;
    border-radius: 50%;
    border: 3px solid var(--avatar-color);
    background: var(--surface);
    display: grid; place-items: center;
    font-weight: 700; font-size: .8rem;
    box-shadow: 0 2px 10px rgba(0,0,0,.35);
    cursor: pointer;
}
/* Sobre el mapa el disco se queda en la superficie y el color va en el anillo:
   un círculo claro con aro de color se lee sobre cualquier tesela, y un disco
   entero de color no. Por eso las iniciales aquí van en la tinta normal y no en
   la del marco. */
.marker .avatar__iniciales { color: var(--text); }

/* El nombre propio, en la misma tarjeta que el avatar: es la misma idea —lo tuyo
   gana a lo que puso el proveedor— y la misma pantalla. */
.perfil__ayuda { margin: 0 0 .6rem; font-size: .82rem; color: var(--text-dim); }

.perfil__nombre { display: flex; gap: .5rem; margin-bottom: 1.25rem; }

.perfil__nombre input {
    flex: 1;
    font: inherit;
    padding: .6rem .7rem;
    color: var(--text);
    background: var(--surface-2);
    border: 1px solid var(--borde-control);
    border-radius: var(--radius);
    min-width: 0;
}

/* Para lectores de pantalla: la etiqueta existe aunque no se vea, porque el
   marcador de posicion NO es una etiqueta y desaparece al escribir. */
.visually-hidden {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* --- Entrar y crear cuenta ----------------------------------------------- */

.acceso { padding: 3rem 0 4rem; max-width: 26rem; }
.acceso h1 { margin-bottom: 1.25rem; }

.acceso__proveedor { display: block; text-align: center; }

/* El separador entre las dos formas de entrar: una linea con la palabra en
   medio. Con ::before y ::after para no meter divs vacios en el HTML. */
.acceso__o {
    display: flex;
    align-items: center;
    gap: .75rem;
    margin: 1.5rem 0;
    color: var(--text-dim);
    font-size: .85rem;
}
.acceso__o::before, .acceso__o::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--border);
}

.acceso__form { display: grid; gap: .35rem; }
.acceso__form label { font-size: .82rem; color: var(--text-dim); margin-top: .6rem; }

.acceso__form input {
    font: inherit;
    padding: .7rem .8rem;
    color: var(--text);
    background: var(--surface);
    border: 1px solid var(--borde-control);
    border-radius: var(--radius);
}

.acceso__form .btn { margin-top: 1.25rem; }

.acceso__estado { margin: .75rem 0 0; font-size: .85rem; min-height: 1.2em; }

.acceso__pies {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: .5rem 1rem;
    margin-top: 1.5rem;
    font-size: .85rem;
}

/* Un boton que se lee como enlace: cambia el modo del formulario, no navega, y
   por eso NO es un <a>. */
.acceso__enlace {
    font: inherit;
    font-size: .85rem;
    padding: 0;
    color: var(--accent-texto);
    background: none;
    border: 0;
    cursor: pointer;
    text-decoration: underline;
}

/* --- Marcas de quedada --------------------------------------------------- */

/* Una marca NO es una persona y no debe poder confundirse con una: va anclada
   por abajo —senala un sitio y tiene que apuntar a el— y lleva el tiempo escrito
   dentro, que ningun marcador de persona tiene. */
.ping {
    display: grid;
    justify-items: center;
    gap: 2px;
    cursor: pointer;
    /* Que el globo se abra al tocar el glifo y no al rozar el hueco. */
    line-height: 1;
}

.ping__glifo {
    width: 34px; height: 34px;
    display: grid; place-items: center;
    font-size: 1.15rem;
    background: var(--surface);
    border: 2px solid var(--border);
    border-radius: 50%;
    box-shadow: 0 2px 10px rgba(0,0,0,.35);
}

.ping__tiempo {
    font-size: .68rem;
    font-weight: 600;
    color: var(--text);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 1px 6px;
    white-space: nowrap;
}

/* La mia se distingue por el anillo del acento, no por color de estado. */
.ping.is-mine .ping__glifo { border-color: var(--accent); }

/* Ya paso la hora: se apaga, pero NO desaparece —quien llega tarde mira el mapa
   justo para eso—. El apagado va DENTRO del filter y no en `opacity`, por lo
   mismo que en .marker.is-stale: MapLibre escribe `opacity` en el estilo en
   linea de cada marcador y una regla de la hoja no puede ganarle. */
.ping.is-past { filter: grayscale(1) opacity(.6); }

/* La quedada dentro de la lista de gente. Forma propia: en esa lista todo lo
   demas son personas, y esto es un sitio. */
.quedada-fila__glifo {
    width: 40px; height: 40px;
    display: grid; place-items: center;
    font-size: 1.25rem;
    background: var(--surface-2);
    border: 2px solid var(--border);
    border-radius: 50%;
    flex: 0 0 auto;
}

.quedada-fila__glifo.is-mine { border-color: var(--accent); }
.quedada-fila__meta { color: var(--accent-texto); }

/* --- El formulario de la quedada ----------------------------------------- */

.quedada { display: grid; gap: .5rem; padding: 0 1rem 1rem; }
.quedada__punto { margin: 0; font-size: .82rem; color: var(--text-dim); }
.quedada__etiqueta { margin: .25rem 0 0; font-size: .78rem; color: var(--text-dim); }

.quedada__campo { display: grid; gap: .25rem; font-size: .82rem; color: var(--text-dim); }
.quedada__campo select {
    font: inherit;
    padding: .4rem .5rem;
    color: var(--text);
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: 8px;
}

.quedada__emojis, .quedada__tiempos { display: flex; flex-wrap: wrap; gap: .4rem; }

.quedada__chip {
    font: inherit;
    font-size: .85rem;
    padding: .35rem .6rem;
    min-width: 40px;
    color: var(--text-dim);
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 999px;
    cursor: pointer;
}

.quedada__chip.is-active {
    color: var(--text);
    border-color: var(--accent);
    background: var(--surface-2);
}

/* Sustituir en silencio algo que la gente ya vio en el mapa es de lo que se
   descubre tarde, asi que se avisa antes. En --warn-texto y no en --warn: es
   letra pequena. */
.quedada__aviso { margin: 0; font-size: .78rem; color: var(--warn-texto); }

.quedada__acciones { display: flex; gap: .5rem; margin-top: .25rem; }

.ping__quitar {
    font: inherit;
    font-size: .8rem;
    margin-top: .4rem;
    padding: .3rem .6rem;
    color: var(--danger-texto);
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 8px;
    cursor: pointer;
}

/* Un dato viejo pierde el color. Es más fuerte que cambiarlo de tono —se apaga
   el marcador entero, foto incluida, mientras los frescos siguen encendidos— y
   sobre todo no consume el anillo. El filtro de grises usa los mismos pesos de
   luminancia que WCAG, así que un marco que contrasta en color contrasta igual
   en gris: no hay nada nuevo que comprobar en tests/contraste.php.

   El desvanecido va DENTRO del filtro y no en `opacity`, que sería lo natural:
   MapLibre escribe `opacity` en el estilo en línea de cada marcador y una regla
   de la hoja no puede ganarle. El síntoma era que el dato viejo se veía gris
   pero igual de sólido que los demás. */
.marker.is-stale { filter: grayscale(1) opacity(.55); }

/* Tú mismo: un segundo aro por fuera. Geometría, no color, porque el color ya
   dice de quién es el avatar. */
.marker.is-self {
    box-shadow:
        0 0 0 2px var(--surface),
        0 0 0 4px var(--avatar-color),
        0 2px 10px rgba(0,0,0,.35);
}

/* --- Paginas de contenido --- */

.page {
    max-width: 34rem;
    margin: 0 auto;
    padding: 1.25rem 1.25rem calc(var(--tabbar-total) + 2rem);
}

.page__lead { color: var(--text-dim); font-size: .9rem; margin-top: 0; }
.page__status { min-height: 1.2rem; font-size: .88rem; color: var(--text-dim); }
.page__status.is-error { color: var(--danger-texto); }
.page__status.is-ok { color: var(--ok-texto); }

.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 1rem;
    margin-bottom: 1rem;
}

.card__note { color: var(--text-dim); font-size: .86rem; margin: 0 0 .8rem; }
.card__hint { color: var(--text-dim); font-size: .78rem; margin: .7rem 0 0; }

/* Una línea de formulario con su etiqueta al lado: "cuánto dura" y su selector. */
.form-linea { display: flex; align-items: center; gap: .6rem; margin-top: .7rem; font-size: .88rem; color: var(--text-dim); }
.form-linea select {
    background: var(--surface-2); color: var(--text); border: 1px solid var(--borde-control);
    border-radius: 10px; padding: .5rem .6rem; font: inherit; min-height: 44px;
}

.badge--warn { background: color-mix(in srgb, var(--warn) 12%, transparent); color: var(--warn-texto); }

/* Acciones sobre una persona del círculo: compartir o no, y expulsar si eres
   quien lo administra. En fila y sin partir palabras, que apiladas parecen dos
   avisos y no dos botones. */
.member__acciones { display: flex; flex-direction: column; gap: .35rem; align-items: stretch; }
.member__acciones .person__btn { white-space: nowrap; }

/* Pasos que tiene que dar el usuario a mano, cuando el navegador no nos deja
   hacerlo por él: añadir la web a la pantalla de inicio en iOS, por ejemplo. */
.pasos { color: var(--text-dim); font-size: .82rem; line-height: 1.5; margin: .8rem 0 0; padding-left: 1.2rem; }
.pasos li + li { margin-top: .45rem; }

.form-row { display: flex; gap: .5rem; }
.form-row input {
    flex: 1;
    /* Un campo dentro de una tarjeta se distingue por el borde, no por el
       fondo: en claro --surface-2 sobre --surface da 1.13:1. */
    min-width: 0;
    padding: .7rem .8rem;
    border-radius: 10px;
    border: 1px solid var(--borde-control);
    background: var(--surface-2);
    color: var(--text);
    font: inherit;
    min-height: 46px;
}

.members, .invites, .log { list-style: none; margin: 0; padding: 0; display: grid; gap: .6rem; }
.members__empty, .log__empty { color: var(--text-dim); font-size: .9rem; }

.member {
    display: grid;
    grid-template-columns: 40px 1fr auto;
    gap: .75rem;
    align-items: center;
    padding: .6rem;
    background: var(--surface-2);
    border-radius: 12px;
}

.member__perms { font-size: .78rem; color: var(--text-dim); }
.badge {
    display: inline-block;
    padding: .1rem .45rem;
    border-radius: 999px;
    font-size: .72rem;
    background: var(--border);
    margin-right: .3rem;
}
.badge--on { background: color-mix(in srgb, var(--ok) 12%, transparent); color: var(--ok-texto); }
.badge--off { background: color-mix(in srgb, var(--danger) 12%, transparent); color: var(--danger-texto); }

.invite {
    display: flex; align-items: center; justify-content: space-between; gap: .5rem;
    padding: .6rem .75rem;
    background: var(--surface-2);
    border-radius: 12px;
    font-family: ui-monospace, SFMono-Regular, monospace;
    letter-spacing: .06em;
}

.log__item {
    display: grid;
    /* Flecha, avatar, texto y estado. La flecha es lo que sustituye a las dos
       listas separadas de antes. */
    grid-template-columns: auto 32px 1fr auto;
    align-items: center;
    gap: .3rem .6rem;
    padding: .6rem .75rem;
    background: var(--surface-2);
    border-radius: 12px;
    font-size: .9rem;
}
/* Más pequeño que en las listas: aquí la cara acompaña a una línea de texto, no
   la encabeza. */
.log__avatar {
    width: 32px; height: 32px;
    background: var(--avatar-color);
    font-size: .78rem;
}
/* Entrante y saliente. Solo la entrante lleva color: es la que habla de ti. */
.log__dir { font-size: 1rem; line-height: 1; color: var(--text-dim); }
.log__dir.is-in { color: var(--accent-texto); }

.log__when { color: var(--text-dim); font-size: .8rem; }
.log__status { font-size: .78rem; align-self: center; }
.log__status.is-answered { color: var(--ok-texto); }
.log__status.is-timeout, .log__status.is-error { color: var(--warn-texto); }
.log__status.is-denied { color: var(--danger-texto); }

/* --- Barra inferior --- */

.tabbar {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    height: var(--tabbar-total);
    padding-bottom: env(safe-area-inset-bottom, 0px);
    display: flex;
    background: var(--surface);
    border-top: 1px solid var(--border);
    z-index: 20;
}

.tab {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    color: var(--text-dim);
    text-decoration: none;
    font-size: .7rem;
}
.tab svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.8; }
.tab.is-active { color: var(--accent-texto); }

/* --- Pagina de respuesta --- */

.respond {
    min-height: 100%;
    display: grid;
    place-items: center;
    padding: 1.5rem;
}

.respond__card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 20px;
    padding: 2.5rem 1.75rem;
    text-align: center;
    max-width: 22rem;
    width: 100%;
}

.respond__detail { color: var(--text-dim); }
.respond__hint { color: var(--text-dim); font-size: .78rem; margin-top: 1.5rem; }
.respond__actions { margin-top: 1.25rem; display: grid; gap: .5rem; }

.respond__pulse { display: flex; gap: 6px; justify-content: center; margin-bottom: 1.25rem; }
.respond__pulse span {
    width: 10px; height: 10px; border-radius: 50%;
    background: var(--accent);
    animation: pulse 1.1s infinite ease-in-out;
}
.respond__pulse span:nth-child(2) { animation-delay: .16s; }
.respond__pulse span:nth-child(3) { animation-delay: .32s; }
.respond__pulse.is-done span { animation: none; background: var(--ok); }
.respond__pulse.is-error span { animation: none; background: var(--danger); }

@keyframes pulse {
    0%, 80%, 100% { transform: scale(.6); opacity: .5; }
    40% { transform: scale(1); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    * { animation: none !important; transition: none !important; }
}

/* --- Planes --- */

.plans { list-style: none; margin: 0; padding: 0; display: grid; gap: .75rem; }

.plan {
    background: var(--surface-2);
    border-radius: 12px;
    padding: .85rem;
    display: grid;
    gap: .6rem;
}

.plan__head { display: flex; justify-content: space-between; align-items: baseline; gap: .5rem; }
.plan__time { font-size: .8rem; color: var(--warn-texto); white-space: nowrap; }
.plan__note { margin: 0; font-size: .78rem; color: var(--warn-texto); }

.plan__members { display: flex; align-items: center; gap: .3rem; flex-wrap: wrap; }
.plan__count { font-size: .78rem; color: var(--text-dim); margin-left: .25rem; }

.chip {
    width: 28px; height: 28px;
    border-radius: 50%;
    background: var(--border);
    display: grid; place-items: center;
    font-size: .68rem; font-weight: 700;
    overflow: hidden;
}
.chip img { width: 100%; height: 100%; object-fit: cover; }

.plan__share {
    display: flex; align-items: center; gap: .5rem;
    background: var(--surface); border-radius: 10px; padding: .45rem .6rem;
}
.plan__share code {
    flex: 1;
    font-size: .76rem;
    color: var(--text-dim);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.plan__tools { display: flex; gap: .5rem; flex-wrap: wrap; }
.plan__leave { justify-self: start; color: var(--danger-texto); }

.field { display: grid; gap: .3rem; margin-bottom: .9rem; }
.field > span { font-size: .82rem; color: var(--text-dim); }
.field input, .field select {
    padding: .7rem .8rem;
    border-radius: 10px;
    border: 1px solid var(--borde-control);
    background: var(--surface-2);
    color: var(--text);
    font: inherit;
    min-height: 46px;
}

.join-terms {
    list-style: none; padding: 0; margin: 0 0 1.5rem;
    display: grid; gap: .55rem;
    text-align: left;
    font-size: .88rem; color: var(--text-dim);
}
.join-terms li { padding-left: 1.2rem; position: relative; }
.join-terms li::before {
    content: '·'; position: absolute; left: .35rem;
    color: var(--accent-texto); font-weight: 700;
}
.join-terms strong { color: var(--text); }

/* Distintivo de quien comparte solo durante un plan. */
.badge--plan { background: color-mix(in srgb, var(--warn) 12%, transparent); color: var(--warn-texto); }

/* --- Selector de idioma dentro de la aplicación --- */

.idiomas { display: flex; gap: .1rem; align-items: center; font-size: .75rem; }

.idiomas__opcion {
    /* Tres letras no dan un objetivo que se pueda tocar: la caja se lleva a 44
       px sin agrandar el texto. */
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: .3rem .6rem;
    color: var(--text-dim);
    text-decoration: none;
    border-radius: 8px;
    letter-spacing: .04em;
}

.idiomas__opcion:hover { color: var(--text); }

.idiomas__opcion.is-active {
    color: var(--accent-texto);
    background: color-mix(in srgb, var(--accent) 12%, transparent);
}

.ajustes-idioma { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.ajustes-idioma h2 { margin: 0; }

/* Texto que solo existe para quien no ve la pantalla: etiquetas de campos cuyo
   nombre ya está dicho a la vista por el título de su tarjeta. No usa
   display:none ni visibility:hidden porque eso también lo esconde del lector. */
.solo-lectores {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* Marcador de una posición aproximada: borde discontinuo para que no se lea como
   un punto exacto. El área real se dibuja además sobre el mapa.
   Solo cambia el trazo y no el color, así que convive con el marco. */
.marker.is-approx {
    border-style: dashed;
}

/* Selector de detalle por persona */
.precision {
    display: flex;
    gap: .3rem;
    flex-wrap: wrap;
    margin-top: .5rem;
}

.precision__opcion {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    border: 1px solid var(--borde-control);
    background: transparent;
    color: var(--text-dim);
    border-radius: 999px;
    padding: .3rem .9rem;
    font: inherit;
    font-size: .78rem;
    cursor: pointer;
}

.precision__opcion.is-active {
    border-color: var(--accent);
    color: var(--accent-texto);
    background: color-mix(in srgb, var(--accent) 12%, transparent);
}

.member--con-precision { grid-template-columns: 40px 1fr; }

/* Los botones van bajo el nombre, no bajo el avatar. La regla apunta al
   contenedor y no a los botones: desde que se envolvieron en .member__acciones
   dejaron de ser hijos del grid, y grid-column sobre un nieto no hace nada. El
   <span> caía entonces en la columna del avatar, 40 px, con el texto saliéndose
   de la caja — y de la zona en la que el botón responde al clic, que en
   «Expulsar» significaba que pulsar sobre la palabra no hacía nada. */
.member--con-precision > .member__acciones,
.member--con-precision > .person__btn { grid-column: 2; justify-self: start; }

/* --- Un interruptor con su explicación --- */

.ajuste {
    display: flex;
    align-items: flex-start;
    gap: .75rem;
    padding: .6rem 0;
    /* Objetivo táctil cómodo: la fila entera responde, no solo la casilla. */
    min-height: 44px;
    cursor: pointer;
}
.ajuste input { width: 22px; height: 22px; margin-top: .15rem; flex: none; accent-color: var(--accent); }
.ajuste input:disabled { cursor: default; }
.ajuste__nombre { display: block; font-weight: 600; }
.ajuste__pista { display: block; font-size: .82rem; color: var(--text-dim); margin-top: .15rem; }

/* Lo que decides sobre una persona concreta. Tres estados, así que un <select>
   y no una casilla: «como en tus ajustes» no es lo mismo que «no». */
.ajuste-persona {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    margin-top: .4rem;
    font-size: .82rem;
    color: var(--text-dim);
}
.ajuste-persona select {
    min-height: 44px;
    border: 1px solid var(--borde-control);
    border-radius: 10px;
    background: transparent;
    color: var(--text);
    font: inherit;
    font-size: .82rem;
    padding: 0 .5rem;
}

/* --- Tu avatar --- */

.perfil__vista { display: grid; place-items: center; padding: .5rem 0 1.25rem; min-height: 96px; }
.perfil__cargando { color: var(--text-dim); font-size: .9rem; }

.perfil__avatar {
    width: 96px; height: 96px;
    background: var(--avatar-color);
    font-size: 2.2rem;
}
/* La pegatina crece con el avatar salvo en su tipografía, que va en rem. */
.perfil__avatar .avatar__pegatina { font-size: 1.5rem; }

/* El <label> hace de botón para el <input type=file>, que va oculto porque su
   control nativo no se deja dar forma. */
.perfil__foto { display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: 1.5rem; }
.perfil__foto .btn { cursor: pointer; }

.perfil__rejilla {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    margin-bottom: 1rem;
}

/* A mano y no con <input type=radio>: lo que hay que enseñar es el color del
   marco, y un control nativo no se deja pintar por dentro. */
.perfil__opcion {
    display: grid; place-items: center;
    width: 52px; height: 52px;
    padding: 0;
    border: 2px solid transparent;
    border-radius: 50%;
    background: transparent;
    cursor: pointer;
}
.perfil__opcion.is-active { border-color: var(--borde-control); }
.perfil__opcion:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.perfil__muestra {
    width: 36px; height: 36px;
    border-radius: 50%;
    background: var(--marco-oscuro);
}
@media (prefers-color-scheme: light) { .perfil__muestra { background: var(--marco-claro); } }
:root[data-theme="light"] .perfil__muestra { background: var(--marco-claro); }
:root[data-theme="dark"] .perfil__muestra { background: var(--marco-oscuro); }

.perfil__glifo { font-size: 1.5rem; line-height: 1; color: var(--text-dim); }

/* Las categorias de emoji. Se desplazan en horizontal a proposito: ocho no
   caben en el ancho de un movil, y partirlas en dos filas moveria el resto de
   la tarjeta cada vez que se cambia de pestana. */
.perfil__tabs {
    display: flex;
    gap: .4rem;
    overflow-x: auto;
    margin-bottom: .75rem;
    padding-bottom: .25rem;
    scrollbar-width: thin;
}

.perfil__tab {
    flex: 0 0 auto;
    padding: .35rem .7rem;
    font: inherit;
    font-size: .82rem;
    color: var(--text-dim);
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 999px;
    cursor: pointer;
}

.perfil__tab:hover { color: var(--text); }

.perfil__tab.is-active {
    color: var(--text);
    font-weight: 600;
    border-color: var(--accent);
    background: var(--surface-2);
}

.plan__precision { display: grid; gap: .35rem; }
.plan__etiqueta { font-size: .74rem; color: var(--text-dim); }

/* --- Lo que no tiene vuelta atrás -------------------------------------------
   Borrar la cuenta va en su propia tarjeta y con el borde en rojo, separado de
   lo de cada día. Es la misma regla que sigue la pestaña del círculo: terminar
   un círculo no está junto a cambiar el detalle con alguien.

   El rojo pinta el borde y el botón; para ESCRIBIR va `--danger-texto`, que es
   el que aguanta una línea pequeña sobre el papel. */
.card--peligro {
    border-color: var(--danger);
}
.card--peligro h2 {
    color: var(--danger-texto);
}

.btn--peligro {
    background: var(--danger);
    /* Casi negro sobre el rojo, por lo mismo que sobre la miel: el blanco se
       queda corto de contraste. */
    color: #140A02;
    border-color: var(--danger);
}
.btn--peligro:hover {
    background: var(--danger);
    color: var(--papel);
}

/* El campo de confirmación, a lo ancho y separado del botón: escribir la
   contraseña y pulsar «Eliminar» no puede quedar a un pixel de distancia. */
#borrarForm input {
    display: block;
    width: 100%;
    margin: .5rem 0 1rem;
}
