/* CCD-FVF — sistema visual.
   Paleta institucional de la FVF, tomada del escudo oficial (assets/img/escudo-fvf.png):
   vinotinto #510e26 · vinotinto secundario #7a1838 · dorado #be9c52.
   Son los mismos valores de la plantilla institucional de documentos de la Federación;
   no se inventan tonos nuevos ni se "ajustan" para que cuadre un contraste: si un par
   no llega al mínimo, se cambia el fondo o el tinte, nunca el color de marca.
   Tipografía: Barlow Condensed (títulos) + Barlow (texto) — familia deportiva.
   Contrastes verificados a 4.5:1 (texto) y 3:1 (no textual) en los dos esquemas,
   claro y oscuro — WCAG 2.1 AA, informe v3 §9.2.
   La verificación no es una promesa del comentario: la calcula
   `local/verificar-contraste.mjs`, que corre dentro de `local/preparar.ps1`.
   Si se cambia un color de aquí, ese script decide si el cambio pasa. */

:root {
  /* Color semántico: nunca hex crudo en los componentes */
  --vinotinto: #510e26;        /* oficial FVF */
  --vinotinto-claro: #7a1838;  /* oficial FVF, secundario */
  --vinotinto-oscuro: #380a1a; /* derivado, para pie y velos */
  --dorado: #be9c52;           /* oficial FVF, muestreado del escudo */
  --dorado-claro: #dcc08b;     /* derivado, para fondos oscuros */
  --crema: #f6f1e9;
  --blanco: #ffffff;
  --tinta: #1f1a1c;
  --tinta-suave: #574a4e;
  --borde: #e4dccb;
  --exito: #2f6b46;
  --peligro: #a12d23;
  /* #8a6a1f daba 4.02:1 sobre su propio tinte: por debajo del mínimo de texto */
  --aviso: #755916;

  --fondo: var(--crema);
  --superficie: var(--blanco);
  --texto: var(--tinta);
  --texto-suave: var(--tinta-suave);
  --primario: var(--vinotinto);
  --acento: var(--dorado);
  --enlace-hover: var(--vinotinto-claro);

  /* Escala de 8 px */
  --e1: .5rem; --e2: 1rem; --e3: 1.5rem; --e4: 2rem; --e6: 3rem; --e8: 4rem; --e12: 6rem;
  --radio: 10px;
  --sombra: 0 1px 2px rgba(31,26,28,.06), 0 8px 24px rgba(31,26,28,.08);
  --ancho: 1140px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --fondo: #1a0f14;
    --superficie: #26141c;
    --texto: #f6f1e9;
    --texto-suave: #cbb6bc;
    --borde: #3e2530;
    --primario: var(--dorado-claro);
    --enlace-hover: #e2cf9f;
    /* Los colores de estado del esquema claro son ilegibles sobre fondo oscuro
       (el verde daba 2.47:1). Aquí van sus equivalentes claros. */
    --exito: #6fbe8e;
    --peligro: #f08a80;
    --aviso: #dcb45c;
    --sombra: 0 1px 2px rgba(0,0,0,.4), 0 8px 24px rgba(0,0,0,.35);
  }
}

*, *::before, *::after { box-sizing: border-box; }

/* `hidden` debe ganar siempre: cualquier `display` de un componente (p. ej. el
   `flex` de .aviso) pisa el `display:none` del navegador y el elemento se vería. */
[hidden] { display: none !important; }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

body {
  margin: 0;
  background: var(--fondo);
  color: var(--texto);
  font-family: 'Barlow', system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-size: 1rem;          /* 16px: evita el zoom automático de iOS */
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  font-family: 'Barlow Condensed', 'Barlow', system-ui, sans-serif;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: .01em;
  margin: 0 0 var(--e2);
  text-wrap: balance;
}
h1 { font-size: clamp(2.4rem, 6vw, 4.2rem); text-transform: uppercase; }
h2 { font-size: clamp(1.8rem, 4vw, 2.8rem); text-transform: uppercase; }
h3 { font-size: 1.35rem; }
p  { margin: 0 0 var(--e2); max-width: 68ch; }

a { color: var(--primario); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--enlace-hover); }

/* Anillo de dos colores: el dorado solo daba 2.36:1 sobre el crema del fondo.
   El halo claro se ve sobre vinotinto (pie, héroe, botón principal) y el aro
   oscuro se ve sobre crema; siempre hay uno de los dos con contraste de sobra,
   sin depender del esquema de color. */
:focus-visible {
  outline: 3px solid var(--vinotinto-oscuro);
  outline-offset: 3px;
  box-shadow: 0 0 0 3px var(--crema);
  border-radius: 4px;
}

.contenedor { width: min(100% - 2.5rem, var(--ancho)); margin-inline: auto; }
.salto-contenido {
  position: absolute; left: -9999px; top: 0; background: var(--vinotinto); color: var(--crema);
  padding: var(--e1) var(--e2); z-index: 100;
}
.salto-contenido:focus { left: var(--e2); top: var(--e2); }

/* ---------------------------------------------------------------- botones */
.boton {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  min-height: 48px; padding: .75rem 1.6rem;
  font-family: 'Barlow Condensed', sans-serif; font-size: 1.1rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .04em; text-decoration: none;
  border: 2px solid transparent; border-radius: var(--radio); cursor: pointer;
}
.boton--principal { background: var(--vinotinto); color: var(--crema); }
.boton--secundario { background: transparent; color: var(--primario); border-color: currentColor; }
.boton[disabled], .boton[aria-disabled='true'] { opacity: .45; cursor: not-allowed; }

/* ---------------------------------------------------------------- tarjetas */
.tarjeta {
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  padding: var(--e3);
  box-shadow: var(--sombra);
}

.etiqueta {
  display: inline-block; padding: .2rem .7rem; border-radius: 999px;
  font-size: .78rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
}
.etiqueta--certifica { background: rgba(47,107,70,.14); color: var(--exito); }
.etiqueta--audiencia { background: rgba(138,106,31,.16); color: var(--aviso); }

/* ---------------------------------------------------------------- cabecera */
.cabecera {
  position: sticky; top: 0; z-index: 20;
  background: color-mix(in srgb, var(--fondo) 92%, transparent);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--borde);
}
.cabecera__fila { display: flex; align-items: center; justify-content: space-between; gap: var(--e2); min-height: 72px; }
.marca { display: flex; align-items: center; gap: .75rem; padding: .25rem 0; /* 48px de alto táctil */
         font-family: 'Barlow Condensed', sans-serif;
         font-weight: 700; font-size: 1.25rem; text-transform: uppercase; color: var(--texto); text-decoration: none; }
/* El escudo oficial no es cuadrado (188x220): se fija el alto y el ancho sale solo,
   si no queda aplastado. */
.marca__escudo { height: 42px; width: auto; flex: none; }
.nav { display: flex; gap: var(--e3); align-items: center; }
/* :not(.boton) — si no, `.nav a` (0-1-1) pisa a `.boton--principal` (0-1-0) y el
   botón de la cabecera pierde su color de texto. */
.nav a:not(.boton) { font-weight: 500; text-decoration: none; color: var(--texto); }
.nav a:not(.boton):hover, .nav a:not(.boton)[aria-current='page'] { color: var(--primario); text-decoration: underline; }
@media (max-width: 760px) { .nav__enlaces { display: none; } }

/* ---------------------------------------------------------------- pie */
.pie { background: var(--vinotinto-oscuro); color: var(--crema); padding: var(--e6) 0 var(--e4); margin-top: var(--e12); }
/* Los enlaces del pie van en línea dentro de un párrafo: sin esto miden 19 px de
   alto y quedan por debajo del objetivo táctil mínimo. */
.pie a { color: var(--dorado-claro); display: inline-block; padding: .8rem 0; }
.pie__rejilla { display: grid; gap: var(--e4); grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.pie__legal { border-top: 1px solid rgba(246,241,233,.18); margin-top: var(--e4); padding-top: var(--e2);
              font-size: .85rem; color: rgba(246,241,233,.75); }

/* ---------------------------------------------------------------- utilidades */
.rejilla { display: grid; gap: var(--e3); }
.rejilla--3 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.seccion { padding: var(--e12) 0; }
.centrado { text-align: center; }
.solo-lectores {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------------------------------------------------------------- avance del curso
   Barra de progreso y lista de módulos. El color de relleno es el vinotinto de la
   marca; el fondo, un gris del sistema, para que el contraste no dependa del tinte. */
.barra {
  height: .6rem;
  background: var(--borde);
  border-radius: 999px;
  overflow: hidden;
  margin: var(--e2) 0 var(--e3);
}

.barra__relleno {
  height: 100%;
  /* El relleno ocupa el ancho entero y se encoge con scaleX: así el porcentaje se
     anima por la tarjeta gráfica en vez de recalcular la disposición de la página
     sesenta veces por segundo. */
  width: 100%;
  background: var(--vinotinto-claro);
}

.lista-modulos {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: .4rem;
}

.modulo {
  display: flex;
  align-items: center;
  gap: .7rem;
  padding: .6rem .8rem;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

/* Un módulo hecho se distingue por el tinte Y por el signo ✔ del marcado: el color
   solo no basta para quien no lo percibe (WCAG 1.4.1). */
.modulo--hecho {
  border-color: var(--exito);
  background: rgba(47, 107, 70, .08);
}

.lista-simple {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: .3rem;
}

/* Pase de lista: las dos opciones tienen que verse de un vistazo mientras se dicta,
   así que van en línea y con área de clic grande — se marca desde el teléfono. */
.opcion-lista {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  padding: .35rem .5rem;
  margin-right: .3rem;
  border-radius: var(--radio);
  cursor: pointer;
}

.opcion-lista input { width: 1.05rem; height: 1.05rem; }

/* ------------------------------------------------------------------- tablón
   Un aviso fijado se distingue por el borde Y por el chinche del texto: el color
   solo no basta para quien no lo percibe (WCAG 1.4.1). */
.anuncio {
  padding: var(--e3);
  margin-bottom: var(--e2);
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

.anuncio h3 { margin: 0 0 .3rem; font-size: 1.05rem; }
.anuncio p { margin: 0 0 .3rem; }

.anuncio--fijado {
  border-color: var(--dorado);
  background: rgba(190, 156, 82, .07);
}

.anuncio textarea,
#form-anuncio textarea {
  width: 100%;
  padding: .6rem;
  font: inherit;
  color: var(--texto);
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

/* ============================================================== movimiento
   Curvas y tiempos, en un solo sitio.

   Las curvas del navegador (`ease`, `ease-out`) son flojas: no tienen el
   arranque que hace que un movimiento parezca intencionado. Estas son las
   mismas que usan las interfaces que se sienten bien.

   Regla que ordena todo lo de abajo: **entrar y salir van rápido y con
   ease-out**; lo que se mueve por la pantalla va con ease-in-out. `ease-in`
   no se usa nunca en interfaz: empieza lento justo en el instante que la
   persona está mirando, y hace que todo parezca perezoso. */
:root {
  --sale:  cubic-bezier(.23, 1, .32, 1);      /* entrar / salir */
  --anda:  cubic-bezier(.77, 0, .175, 1);     /* moverse por la pantalla */

  /* Tiempos por tipo de elemento. Nada de interfaz pasa de 300 ms: un
     desplegable de 180 ms se siente más despierto que uno de 400 ms. */
  --t-pulsar: 120ms;   /* respuesta al dedo */
  --t-corta:  160ms;   /* etiquetas, tinte al pasar por encima */
  --t-media:  220ms;   /* paneles, avisos, entradas de lista */
  --t-larga:  280ms;   /* cambios grandes de una pantalla */

  --transicion: var(--t-media) var(--sale);
}

/* El tinte al pasar por encima solo existe donde hay un puntero de verdad.
   En una pantalla táctil, `:hover` se dispara al tocar y se queda pegado:
   el botón se ve "encendido" después de pulsarlo, que es justo lo que no
   se quiere en una cancha con el teléfono en la mano. */
@media (hover: hover) and (pointer: fine) {
  .boton--principal:hover { background: var(--vinotinto-claro); color: var(--crema); }
  .boton--secundario:hover { background: rgba(190,156,82,.14); }
  .tarjeta--pulsable:hover { border-color: var(--dorado); transform: translateY(-1px); }
}

/* Pulsar tiene que responder al instante. 120 ms es el techo de lo que se
   percibe como inmediato; con los 200 ms de antes el botón parecía llegar
   tarde a su propia pulsación. */
.boton {
  transition:
    background var(--t-corta) var(--sale),
    color      var(--t-corta) var(--sale),
    border-color var(--t-corta) var(--sale),
    transform  var(--t-pulsar) var(--sale);
}
.boton:active { transform: scale(.97); }

/* Lo mismo para todo lo demás que se pulsa. */
.opcion-lista, .tarjeta--pulsable, .pestana {
  transition: background var(--t-corta) var(--sale), transform var(--t-pulsar) var(--sale);
}
.opcion-lista:active, .tarjeta--pulsable:active { transform: scale(.99); }

/* ------------------------------------------------------------ progreso
   Antes esto animaba `width`, que obliga al navegador a recalcular la
   disposición en cada fotograma. `transform` va por la tarjeta gráfica y no
   toca nada más de la página. Se ancla a la izquierda para que crezca desde
   donde tiene que crecer. */
.barra__relleno {
  transform-origin: left center;
  transition: transform var(--t-larga) var(--sale);
}

/* ------------------------------------------------------------ entradas
   Aparecer de golpe se lee como un fallo; aparecer desde la nada, también.
   Nada en el mundo real surge de un tamaño cero, así que se entra desde el
   97 %: casi imperceptible, y sin él la entrada parece de dibujos animados. */
@media (prefers-reduced-motion: no-preference) {
  .entra {
    animation: entra var(--t-media) var(--sale) both;
  }

  /* Cuando llega una lista entera, se escalona. El retraso es corto a
     propósito: por encima de 80 ms entre elementos la pantalla se siente
     lenta en vez de viva. El escalonado nunca bloquea: se puede pulsar el
     tercer elemento mientras el sexto todavía está entrando. */
  .escalona > * {
    animation: entra var(--t-media) var(--sale) both;
    animation-delay: calc(var(--i, 0) * 45ms);
  }
}

@keyframes entra {
  from { opacity: 0; transform: translateY(6px) scale(.985); }
  to   { opacity: 1; transform: none; }
}

/* ------------------------------------------------------------ el aviso
   Es lo que dice si algo salió bien o mal, así que tiene que llegar rápido y
   quedarse quieto. Se usa transición y no fotogramas porque los avisos se
   encadenan: una transición se puede redirigir a mitad de camino, unos
   fotogramas vuelven a empezar desde cero y dan un salto. */
.aviso {
  transition:
    opacity var(--t-media) var(--sale),
    transform var(--t-media) var(--sale);
}
/* No se anima la salida del aviso manteniéndolo en la página con altura cero:
   eso lo deja dentro del árbol de accesibilidad y un lector de pantalla seguiría
   leyendo un mensaje que ya no está. `hidden` tiene que seguir significando
   oculto. Se anima la entrada, que es la que se ve. */

/* ------------------------------------------------------------ esqueleto
   Mientras se espera al servidor no se pone "Cargando…": se dibuja la forma
   de lo que va a venir. Quien mira ya sabe si va a haber una tabla o unas
   tarjetas, y la espera se siente más corta aunque dure exactamente lo mismo.
   El brillo es lento y de poco contraste: un destello rápido cansa la vista
   en una pantalla que se mira todo el día. */
.esqueleto {
  --hueso: color-mix(in srgb, var(--texto) 9%, transparent);
  background: var(--hueso);
  border-radius: var(--radio);
  position: relative;
  overflow: hidden;
}

@media (prefers-reduced-motion: no-preference) {
  .esqueleto::after {
    content: '';
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--texto) 5%, transparent), transparent);
    animation: brillo 1.4s linear infinite;
  }
}

@keyframes brillo { to { transform: translateX(100%); } }

.esqueleto--titulo { height: 2.2rem; width: min(22rem, 60%); margin-bottom: var(--e3); }
.esqueleto--linea  { height: .95rem; margin-bottom: .55rem; }
.esqueleto--linea:nth-child(3n)   { width: 88%; }
.esqueleto--linea:nth-child(3n+1) { width: 96%; }
.esqueleto--linea:nth-child(3n+2) { width: 72%; }
.esqueleto--tarjeta { height: 7.5rem; }
.esqueleto--fila { height: 3.1rem; margin-bottom: .5rem; }

/* ------------------------------------------------------------ vacío y fallo
   Dos estados que casi nunca se dibujan y que la gente sí ve. Un hueco en
   blanco no dice si no hay nada o si algo se rompió, y esa diferencia es
   justo la que hace falta saber. */
.estado {
  display: grid;
  gap: var(--e1);
  justify-items: start;
  padding: var(--e4) var(--e3);
  border: 1px dashed var(--borde);
  border-radius: var(--radio);
  color: var(--texto-suave);
}
.estado h3 { margin: 0; color: var(--texto); }
.estado p { margin: 0; }
.estado--fallo { border-style: solid; border-color: var(--peligro); }

/* ------------------------------------------------------------ requisitos
   Lo que falta para el certificado. El estado no se distingue solo por color: cada
   fila lleva su marca (✔ / ○) y un texto para lector de pantalla, porque quien no
   percibe el verde tiene el mismo derecho a saber si cumple (WCAG 1.4.1). */
.veredicto { font-family: 'Barlow Condensed', sans-serif; font-size: 1.3rem; font-weight: 600; margin: 0 0 var(--e2); }
.requisitos { display: grid; gap: .6rem; }
.requisito { display: flex; gap: .8rem; align-items: start; padding: .7rem .8rem;
             border: 1px solid var(--borde); border-radius: var(--radio); }
.requisito__marca { font-size: 1.2rem; line-height: 1.2; flex: none; }
.requisito--ok { border-color: var(--exito); background: rgba(47,107,70,.08); }
.requisito--ok .requisito__marca { color: var(--exito); }
.requisito--falta { border-color: var(--aviso); background: rgba(138,106,31,.08); }
.requisito--falta .requisito__marca { color: var(--aviso); }

/* El puesto en la lista de espera: se lee de un vistazo mientras se decide a quién
   admitir, que es cuando importa que quien pidió primero esté primero. */
.puesto {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 2rem; height: 2rem; border-radius: 999px;
  font-family: 'Barlow Condensed', sans-serif; font-size: 1.1rem;
  background: rgba(190,156,82,.18); color: var(--texto);
}

/* Una pregunta que pide revisión se distingue por el tinte Y por el texto de la
   columna "qué mirar": el color solo no basta (WCAG 1.4.1). */
.fila--revisar { background: rgba(138,106,31,.10); }
