/* ============================================================
   Aulendo · public.css — estilos de todas las paginas publicas sobre
   el layout auth: login, recuperacion, inscripcion, asistencia, aviso,
   verificacion y descarga de certificado. Nucleo compartido (escena,
   tarjeta, campos, alertas, boton) + trozos por pagina, comentados.
   Paleta y tipografias segun design/aulendo-guia-de-marca.md
   ============================================================ */

/* Tipografias self-hosted (subset latin): la CSP es font-src 'self',
   nunca Google Fonts. Mismas declaraciones que styles.css. */
@font-face {
    font-family: "Manrope";
    src: url("../fonts/manrope-500.woff2") format("woff2");
    font-weight: 500;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: "Inter";
    src: url("../fonts/inter-400.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: "Inter";
    src: url("../fonts/inter-500.woff2") format("woff2");
    font-weight: 500;
    font-style: normal;
    font-display: swap;
}

:root {
    /* Colores de marca */
    --indigo:      #4F46E5;   /* primario: acciones, enlaces, foco */
    --indigo-deep: #4338CA;   /* hover de acciones primarias */
    --ink:         #1E1B4B;   /* texto principal */
    --cyan:        #06B6D4;   /* acento grafico (nunca texto) */
    --mist:        #EEF2FF;   /* fondos suaves, paneles */

    /* Grises funcionales (escala fria "slate") */
    --slate-100: #F1F5F9;
    --slate-200: #E2E8F0;
    --slate-300: #CBD5E1;
    --slate-400: #94A3B8;
    --slate-500: #64748B;
    --slate-600: #475569;

    /* Estados */
    --error:        #DC2626;
    --error-bg:     #FEF2F2;
    --error-border: #FECACA;

    /* Tipografia */
    --font-headings: "Manrope", system-ui, sans-serif;
    --font-body:     "Inter", system-ui, sans-serif;

    --focus-ring: 0 0 0 3px rgba(79, 70, 229, 0.18);
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html,
body {
    height: 100%;
}

body {
    font-family: var(--font-body);
    font-weight: 400;
    color: var(--ink);
    /* Amanecer sobre niebla: claro arriba, niebla hacia el horizonte.
       Anclado al viewport (fixed) para que al scrollear no se repita el
       degradado ni aparezca una costura, y la niebla quede alineada con
       la .scene fija del horizonte. */
    background: linear-gradient(180deg, #FFFFFF 0%, #FAFBFF 45%, var(--mist) 100%);
    background-attachment: fixed;
    background-repeat: no-repeat;
}

/* ------------------------------------------------------------
   Escena de fondo: sendero + sol (motivo del simbolo, a escala
   de paisaje). Decorativa: no intercepta clicks ni lectores.
   ------------------------------------------------------------ */

.scene {
    position: fixed;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
}

.scene-svg {
    position: absolute;
    inset: auto 0 0 0;
    width: 100%;
    height: min(58vh, 520px);
}

.trail--main {
    opacity: 0.16;
    stroke-dasharray: 1800;
    stroke-dashoffset: 1800;
    animation: draw-trail 1.6s cubic-bezier(0.65, 0, 0.35, 1) 0.25s forwards;
}

.trail--echo {
    opacity: 0.06;
    stroke-dasharray: 1800;
    stroke-dashoffset: 1800;
    animation: draw-trail 1.6s cubic-bezier(0.65, 0, 0.35, 1) 0.45s forwards;
}

@keyframes draw-trail {
    to { stroke-dashoffset: 0; }
}

.sun {
    opacity: 0;
    animation: sunrise 1.1s ease-out 0.9s forwards;
    transform-origin: 1015px 388px;
}

@keyframes sunrise {
    from { opacity: 0; transform: translateY(26px) scale(0.92); }
    to   { opacity: 1; transform: translateY(0)    scale(1); }
}

.sun-halo {
    animation: breathe 7s ease-in-out 2s infinite alternate;
    transform-origin: 1015px 388px;
}

@keyframes breathe {
    from { transform: scale(1); }
    to   { transform: scale(1.18); }
}

/* ------------------------------------------------------------
   Composicion de pagina
   ------------------------------------------------------------ */

.page {
    position: relative;
    min-height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 28px;
    padding: 48px 20px;
}

/* ------------------------------------------------------------
   Tarjeta de login
   ------------------------------------------------------------ */

.card {
    width: 100%;
    max-width: 400px;
    background: #FFFFFF;
    border: 1px solid var(--slate-200);
    border-radius: 16px;
    padding: 40px 36px 36px;
    box-shadow:
        0 1px 2px rgba(30, 27, 75, 0.04),
        0 12px 32px -12px rgba(30, 27, 75, 0.12);
    animation: fade-up 0.7s cubic-bezier(0.16, 1, 0.3, 1) both;
}

/* Entrada escalonada del contenido de la tarjeta */
.card > *,
.card form > * {
    animation: fade-up 0.6s cubic-bezier(0.16, 1, 0.3, 1) both;
}

.card-header               { animation-delay: 0.05s; }
.card h1                   { animation-delay: 0.12s; }
.subtitle                  { animation-delay: 0.18s; }
.card form > .field:nth-child(1) { animation-delay: 0.24s; }
.card form > .field:nth-child(2) { animation-delay: 0.30s; }
.login-button              { animation-delay: 0.36s; }

@keyframes fade-up {
    from { opacity: 0; transform: translateY(14px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* Sacudida sutil al mostrar un error (la dispara el JS del mockup) */
.card.shake {
    animation: shake 0.4s ease-in-out;
}

@keyframes shake {
    20%, 60% { transform: translateX(-6px); }
    40%, 80% { transform: translateX(6px); }
}

/* ------------------------------------------------------------
   Cabecera: logo + instancia
   ------------------------------------------------------------ */

.card-header {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
    margin-bottom: 28px;
}

/* El markup lleva width/height="212/64" como medida propia: sin ellos, el
   logo ocupa el 100% del ancho hasta que llega esta hoja (flash gigante al
   recargar con la cache fria). Estas reglas ganan igual. */
.logo {
    width: 138px;
    height: auto;
    display: block;
}

/* Chip con el nombre del instituto (instancia). El punto cian
   señala "lo vivo" segun la guia; el texto va en tinta. */
.instance {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-size: 13px;
    font-weight: 500;
    color: var(--ink);
    background: var(--mist);
    border-radius: 999px;
    padding: 5px 12px;
}

.instance-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--cyan);
}

/* ------------------------------------------------------------
   Titulos
   ------------------------------------------------------------ */

h1 {
    font-family: var(--font-headings);
    font-weight: 500;          /* nunca pesos mayores a 500 */
    font-size: 28px;
    letter-spacing: -0.4px;
    margin-bottom: 6px;
}

.subtitle {
    font-size: 15px;
    line-height: 1.6;
    color: var(--slate-500);
    margin-bottom: 26px;
}

/* Aviso de admision (docs/modulos/admision.md §5.1): va ARRIBA, antes de que la
   persona complete nada. Informa una condicion del grupo, no un error — de ahi
   que use la niebla de marca y no la superficie roja de `.alert`. */
.admission-notice {
    background: var(--mist);
    border-left: 3px solid var(--indigo);
    border-radius: 8px;
    padding: 12px 14px;
    margin: -14px 0 22px;
    font-size: 14px;
    line-height: 1.55;
    color: var(--ink);
}

/* ------------------------------------------------------------
   Alerta de error
   ------------------------------------------------------------ */

.alert[hidden] {
    display: none;
}

.alert {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    background: var(--error-bg);
    border: 1px solid var(--error-border);
    border-radius: 10px;
    padding: 11px 13px;
    margin-bottom: 20px;
}

.alert svg {
    width: 17px;
    height: 17px;
    flex-shrink: 0;
    color: var(--error);
    margin-top: 1px;
}

.alert p {
    font-size: 13.5px;
    line-height: 1.45;
    color: #991B1B;
}

/* ------------------------------------------------------------
   Campos del formulario
   ------------------------------------------------------------ */

.field {
    margin-bottom: 18px;
}

.field label {
    display: block;
    font-size: 13.5px;
    font-weight: 500;
    color: var(--slate-600);
    margin-bottom: 7px;
}

.field input {
    width: 100%;
    height: 46px;
    font-family: var(--font-body);
    font-size: 15px;
    color: var(--ink);
    background: #FFFFFF;
    border: 1px solid var(--slate-300);
    border-radius: 10px;
    padding: 0 14px;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.field input::placeholder {
    color: var(--slate-400);
}

.field input:hover {
    border-color: var(--slate-400);
}

.field input:focus {
    outline: none;
    border-color: var(--indigo);
    box-shadow: var(--focus-ring);
}

/* Validacion por campo: register.js marca el .field y escribe el motivo
   debajo del input cuando el backend responde 422 con {fields}. */
.field--error input,
.field--error select,
.field--error textarea {
    border-color: var(--error);
}

.field--error input:focus,
.field--error select:focus,
.field--error textarea:focus {
    border-color: var(--error);
    box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.15);
}

.field-error {
    font-size: 12.5px;
    color: #991B1B;
    margin-top: 6px;
}

/* Ayuda contextual bajo un campo (ej: codigo de pais del telefono). */
.field-hint {
    font-size: 12.5px;
    color: var(--slate-500);
    margin-top: 6px;
}

/* Chip del codigo de pais como prefijo del input de telefono (espejo de la
   variante admin en styles.css; el [hidden] explicito es necesario porque el
   display:flex de la clase le ganaria al display:none del user-agent). */
.phone-input {
    display: flex;
}

.phone-input .phone-code {
    display: flex;
    align-items: center;
    height: 46px;
    padding: 0 13px;
    font-size: 15px;
    color: var(--slate-500);
    background: var(--slate-100);
    border: 1px solid var(--slate-300);
    border-right: 0;
    border-radius: 10px 0 0 10px;
    white-space: nowrap;
}

.phone-input .phone-code[hidden] {
    display: none;
}

.phone-input .phone-code:not([hidden]) + input {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
}

/* Contraseña con boton para mostrar/ocultar */
.password-field {
    position: relative;
}

.password-field input {
    padding-right: 46px;
}

.password-toggle {
    position: absolute;
    top: 50%;
    right: 6px;
    transform: translateY(-50%);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border: none;
    border-radius: 8px;
    background: transparent;
    color: var(--slate-400);
    cursor: pointer;
    transition: color 0.15s ease, background-color 0.15s ease;
}

.password-toggle:hover {
    color: var(--slate-600);
    background: var(--slate-100);
}

.password-toggle:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
}

.password-toggle svg {
    width: 19px;
    height: 19px;
}

/* El atributo hidden no aplica a elementos SVG: se fuerza por CSS */
.password-toggle svg[hidden] {
    display: none;
}

/* ------------------------------------------------------------
   Boton primario
   ------------------------------------------------------------ */

.login-button {
    position: relative;
    width: 100%;
    height: 46px;
    margin-top: 6px;
    font-family: var(--font-body);
    font-size: 15px;
    font-weight: 500;
    color: #FFFFFF;
    background: var(--indigo);
    border: none;
    border-radius: 10px;
    cursor: pointer;
    transition: background-color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}

.login-button:hover {
    background: var(--indigo-deep);
    transform: translateY(-1px);
    box-shadow: 0 6px 16px -6px rgba(79, 70, 229, 0.5);
}

.login-button:active {
    transform: translateY(0);
    box-shadow: none;
}

.login-button:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring), 0 0 0 1px #FFFFFF inset;
}

.login-button:disabled {
    cursor: default;
}

/* Estado de carga: oculta el texto y muestra el spinner */
.button-spinner {
    position: absolute;
    inset: 0;
    display: none;
    align-items: center;
    justify-content: center;
}

.button-spinner::after {
    content: "";
    width: 18px;
    height: 18px;
    border: 2px solid rgba(255, 255, 255, 0.35);
    border-top-color: #FFFFFF;
    border-radius: 50%;
    animation: spin 0.7s linear infinite;
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

.login-button.loading .button-label   { visibility: hidden; }
.login-button.loading .button-spinner { display: flex; }

/* Enlace de recuperacion bajo el boton de ingreso */
.recovery-link {
    text-align: center;
    margin-top: 16px;
    font-size: 13.5px;
}

.recovery-link a {
    color: var(--indigo);
    font-weight: 500;
    text-decoration: none;
}

.recovery-link a:hover {
    text-decoration: underline;
}

/* Aviso informativo (ej: "te enviamos un codigo") */
.alert--info {
    background: var(--mist);
    border-color: #C7D2FE;
}

.alert--info svg {
    color: var(--indigo);
}

.alert--info p {
    color: var(--ink);
}

/* Estado de exito (contraseña actualizada) */
.success-state[hidden] {
    display: none;
}

.success-state {
    text-align: center;
    padding: 10px 0 4px;
}

.success-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 60px;
    height: 60px;
    margin: 0 auto 16px;
    border-radius: 50%;
    background: var(--mist);
    color: var(--indigo);
}

.success-icon svg {
    width: 28px;
    height: 28px;
}

/* Lo registrado no es una presencia: el tilde se apaga para no afirmar "listo"
   sobre un texto que dice que hay otro registro (revision de seguridad 07-31). */
.success-state.is-unconfirmed .success-icon {
    background: var(--slate-100);
    color: var(--slate-500);
}

.success-state h2 {
    font-family: var(--font-headings);
    font-weight: 500;
    font-size: 21px;
    margin-bottom: 8px;
}

.success-state p {
    font-size: 14.5px;
    color: var(--slate-500);
    margin-bottom: 20px;
}

/* Enlace con apariencia de boton primario (ej: "Ir a iniciar sesion"
   en el estado de exito). Sin estilos inline: la CSP los bloquearia. */
a.login-button--link {
    display: flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
}

a.login-button--link:hover {
    text-decoration: none;
}

/* ------------------------------------------------------------
   Pie de pagina
   ------------------------------------------------------------ */

.footer {
    animation: fade-up 0.6s cubic-bezier(0.16, 1, 0.3, 1) 0.5s both;
}

.footer p {
    font-size: 13px;
    color: var(--slate-500);
}

/* ------------------------------------------------------------
   Ajustes responsivos y accesibilidad
   ------------------------------------------------------------ */

@media (max-width: 460px) {
    .card {
        padding: 32px 24px 28px;
        border-radius: 14px;
    }

    h1 {
        font-size: 25px;
    }
}

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }

    .trail--main,
    .trail--echo {
        stroke-dashoffset: 0;
    }

    .sun {
        opacity: 1;
    }
}

/* ============================================================
   Registro publico de alumnos (Fase 7)
   ============================================================ */

.card--register {
    max-width: 560px;
}

.required {
    color: var(--error);
}

/* select y textarea con el mismo look que .field input */
.field select,
.field textarea {
    width: 100%;
    font-family: var(--font-body);
    font-size: 15px;
    color: var(--ink);
    background: #FFFFFF;
    border: 1px solid var(--slate-300);
    border-radius: 10px;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.field select {
    height: 46px;
    padding: 0 14px;
}

.field textarea {
    padding: 10px 14px;
    line-height: 1.6;
    resize: vertical;
}

.field select:hover,
.field textarea:hover {
    border-color: var(--slate-400);
}

.field select:focus,
.field textarea:focus {
    outline: none;
    border-color: var(--indigo);
    box-shadow: var(--focus-ring);
}

/* Pares de campos en una fila (se apilan en pantallas chicas) */
.field-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0 16px;
}

/* Resumen del grupo al que se inscribe */
.summary-box {
    background: var(--mist);
    border-radius: 12px;
    padding: 14px 16px;
    margin-bottom: 22px;
}

.summary-course {
    font-family: var(--font-headings);
    font-weight: 500;
    color: var(--ink);
}

.summary-dates {
    font-size: 13.5px;
    color: var(--slate-500);
    margin-top: 2px;
}

.summary-schedule {
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid var(--slate-200);
}

.summary-schedule-label {
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--slate-400);
    margin-bottom: 4px;
}

.summary-schedule ul {
    list-style: none;
    margin: 0;
    padding: 0;
    font-size: 13.5px;
    color: var(--slate-600);
}

.summary-schedule li + li {
    margin-top: 2px;
}

/* Honeypot: fuera de pantalla; no display:none para que los bots lo completen */
.hp-field {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/* Tarjeta de aviso (enlace invalido / inscripciones cerradas / cupo completo) */
.notice-state {
    text-align: center;
    padding: 8px 0 4px;
}

.notice-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    margin: 0 auto 18px;
    border-radius: 50%;
    background: var(--mist);
    color: var(--indigo);
}

.notice-icon svg {
    width: 28px;
    height: 28px;
}

.notice-state h1 {
    margin-bottom: 8px;
}

.notice-state p {
    color: var(--slate-500);
}

/* Solo entre parrafos CONSECUTIVOS: las tarjetas de aviso de siempre traen uno
   solo y no tienen que moverse. La baja de novedades trae dos, y sin esto se
   leian como un bloque unico. */
.notice-state p + p { margin-top: 12px; }

@media (max-width: 540px) {
    .card--register {
        max-width: 400px;
    }

    .field-grid {
        grid-template-columns: 1fr;
    }
}

/* Estados del certificado (descarga / verificacion publica) */
.notice-icon--ok  { background: #ECFDF5; color: #059669; }

/* "Revisa el codigo": ambar y no rojo a proposito. El rojo dice "este documento
   no vale"; esto dice "lo copiaste mal", que es lo contrario — el certificado
   probablemente este bien y el error es de transcripcion. */
.notice-icon--warn { background: #FFFBEB; color: #D97706; }

/* Baja de novedades: un POST clasico, no un fetch (esta pantalla se abre desde
   un cliente de correo, donde el JS puede no correr). El boton va centrado
   dentro de la tarjeta de aviso, que es texto centrado. */
.optout-form { margin-top: 20px; }
.notice-icon--bad { background: #FEF2F2; color: #DC2626; }
.card-note {
    margin-top: 16px;
    text-align: center;
    font-size: 13px;
    color: var(--slate-500);
}

/* Boton de descarga del certificado: <a> con apariencia de login-button */
a.login-button {
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    text-decoration: none;
}

/* ------------------------------------------------------------
   Feedback post-marcado de asistencia (estado de exito)
   ------------------------------------------------------------ */

/* .success-state p (misma especificidad, definida antes) pone slate-500 y
   margen 20px; estas reglas ganan por orden en la hoja. */
.attendance-summary {
    background: var(--mist);
    border-radius: 12px;
    padding: 14px 16px;
    margin-bottom: 20px;
}

.attendance-summary p {
    margin-bottom: 0;
    font-size: 14.5px;
    color: var(--ink);
}

.attendance-summary p + p {
    margin-top: 6px;
}

/* Tono del mensaje de proyeccion: verde en camino, ambar advertencia */
.attendance-summary p.is-positive { color: #047857; font-weight: 500; }
.attendance-summary p.is-warning  { color: #B45309; font-weight: 500; }
