/* ==========================================================================
   COMPONENTS.CSS
   Sistema de componentes reutilizables del sitio. Cada componente se
   documenta con su propósito y su(s) variante(s).

   Esta entrega define los sistemas pero NO los usa todavía en secciones
   de contenido (eso llega en próximas entregas) — sí se usan en Header
   y Footer, que sí forman parte de esta entrega.
   ========================================================================== */

/* --------------------------------------------------------------------
   CONTENEDOR
   Envoltorio de ancho máximo usado en todas las secciones del sitio.
   -------------------------------------------------------------------- */

.container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-pad);
}

/* --------------------------------------------------------------------
   FIRMA VISUAL: MARCAS DE ESQUINA ("bracket-frame")
   Elemento distintivo del sitio: cuatro marcas en L, como las de un
   visor de calibración o un plano técnico. Se usa en tarjetas,
   imágenes destacadas y separadores de sección para reforzar el
   registro "ingeniería/precisión" del proyecto (ver Fase 2).

   Uso: agregar la clase .bracket-frame a cualquier contenedor con
   position relativa. No decorativo por defecto — se activa a
   propósito en componentes clave, no en todos los bloques del sitio.
   -------------------------------------------------------------------- */

.bracket-frame {
  position: relative;
}

.bracket-frame::before,
.bracket-frame::after,
.bracket-frame > .bracket-corner-tr,
.bracket-frame > .bracket-corner-br {
  content: '';
  position: absolute;
  width: var(--bracket-size);
  height: var(--bracket-size);
  border-color: var(--color-accent);
  pointer-events: none;
}

/* Esquina superior-izquierda */
.bracket-frame::before {
  top: -1px;
  left: -1px;
  border-top: var(--bracket-thickness) solid var(--color-accent);
  border-left: var(--bracket-thickness) solid var(--color-accent);
}

/* Esquina inferior-derecha */
.bracket-frame::after {
  bottom: -1px;
  right: -1px;
  border-bottom: var(--bracket-thickness) solid var(--color-accent);
  border-right: var(--bracket-thickness) solid var(--color-accent);
}

/* --------------------------------------------------------------------
   BOTONES
   Variantes: primario, secundario, fantasma (ghost).
   Tamaños: por defecto y "sm".
   Todos los botones comparten estructura para que ícono + texto
   queden alineados igual en cualquier variante.
   -------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-5);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.01em;
  line-height: 1;
  white-space: nowrap;
  border-radius: var(--radius-sm);
  border: 1.5px solid transparent;
  transition:
    background-color var(--duration-fast) var(--ease-standard),
    border-color var(--duration-fast) var(--ease-standard),
    color var(--duration-fast) var(--ease-standard),
    transform var(--duration-fast) var(--ease-standard);
}

.btn:active {
  transform: translateY(1px);
}

.btn svg {
  width: 1em;
  height: 1em;
  font-size: 1.1em; /* íconos ligeramente más grandes que el texto */
}

/* Primario — acción principal (ej. "Solicitar Diagnóstico Técnico") */
.btn--primary {
  background-color: var(--qa-navy-800);
  color: var(--color-text-inverse);
  border-color: var(--qa-navy-800);
}

.btn--primary:hover {
  background-color: var(--qa-navy-700);
  border-color: var(--qa-navy-700);
}

/* Secundario — acción de apoyo, contorno */
.btn--secondary {
  background-color: transparent;
  color: var(--qa-navy-800);
  border-color: var(--qa-navy-800);
}

.btn--secondary:hover {
  background-color: var(--qa-navy-800);
  color: var(--color-text-inverse);
}

/* Fantasma — mínima jerarquía, se usa sobre todo dentro del header */
.btn--ghost {
  background-color: transparent;
  color: currentColor;
  border-color: transparent;
}

.btn--ghost:hover {
  background-color: rgba(255, 255, 255, 0.08);
}

/* Tamaño pequeño */
.btn--sm {
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-xs);
}

/* --- Estados de botón ----------------------------------------------------
   Todo botón del sitio debe pasar por estos 5 estados. El estado
   :hover ya está definido por variante más arriba; aquí se cubren
   los que faltan y se aplican a TODAS las variantes por igual. */

/* Foco de teclado — además del outline global de base.css, el botón
   suma un desplazamiento del anillo para no recortarse contra bordes */
.btn:focus-visible {
  outline-offset: 3px;
}

/* Activo/presionado — ya definido arriba (.btn:active), se documenta
   aquí junto a los demás estados por completitud */

/* Deshabilitado */
.btn:disabled,
.btn[aria-disabled="true"] {
  cursor: not-allowed;
  background-color: var(--color-disabled-bg);
  border-color: var(--color-disabled-border);
  color: var(--color-disabled-text);
  transform: none;
}

.btn:disabled:hover,
.btn[aria-disabled="true"]:hover {
  background-color: var(--color-disabled-bg);
  border-color: var(--color-disabled-border);
}

/* Carga — para envíos de formulario en futuras entregas. Se activa
   agregando la clase .is-loading vía JS; el texto se conserva para
   lectores de pantalla pero se oculta visualmente detrás del spinner. */
.btn.is-loading {
  position: relative;
  color: transparent !important;
  pointer-events: none;
}

.btn.is-loading::after {
  content: '';
  position: absolute;
  width: 16px;
  height: 16px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  color: var(--color-text-inverse);
  animation: qa-spin var(--duration-slow) linear infinite;
}

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

/* --------------------------------------------------------------------
   TARJETAS
   Sistema base para tarjetas de contenido (servicios, industrias,
   casos de aplicación, etc. — se poblarán en próximas entregas).
   -------------------------------------------------------------------- */

.card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-6);
  background-color: var(--color-bg-elevated);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  transition:
    border-color var(--duration-base) var(--ease-standard),
    box-shadow var(--duration-base) var(--ease-standard),
    transform var(--duration-base) var(--ease-standard);
}

.card:hover {
  border-color: var(--qa-navy-500);
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}

.card__eyebrow {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-accent);
}

.card__title {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: var(--weight-semibold);
}

.card__body {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  line-height: var(--leading-normal);
}

/* Variante oscura — para usarse sobre fondo navy (ej. tarjetas dentro
   de la sección "Plataforma SCO V2.0") */
.card--inverse {
  background-color: var(--qa-navy-800);
  border-color: var(--qa-navy-700);
  color: var(--color-text-inverse);
}

/* Causa raíz del problema de contraste (corrección Entrega 8):
   base.css fija `color` directamente sobre las etiquetas h1-h6. En
   CSS, una declaración que apunta directamente a un elemento siempre
   gana sobre el valor heredado del contenedor, sin importar
   especificidad — por eso .card--inverse (arriba) nunca llegaba a
   los títulos, aunque ya declarara el color correcto. Esta regla es
   la corrección sistémica: cualquier encabezado (h1-h6) o .card__title
   dentro de una tarjeta oscura queda claro, en cualquier sección,
   presente o futura, sin tocar cada sección una por una. */
.card--inverse h1,
.card--inverse h2,
.card--inverse h3,
.card--inverse h4,
.card--inverse h5,
.card--inverse h6,
.card--inverse .card__title {
  color: var(--color-text-inverse);
}

/* Mismo criterio de la corrección anterior: .card__eyebrow (cyan-500)
   da 4.49:1 sobre navy-800 — justo por debajo de AA (4.5). Se sube un
   tono a cyan-300 SOLO dentro de tarjetas oscuras (no en la regla
   base) para no afectar un eventual uso futuro de .card__eyebrow
   sobre fondo claro, donde cyan-500 sí es la elección correcta. */
.card--inverse .card__eyebrow {
  color: var(--qa-cyan-300);
}

.card--inverse .card__body {
  color: var(--qa-steel-200);
}

/* Variante "lectura" — superficie ligeramente más clara que
   .card--inverse, para contenido pensado para leerse (Centro de
   Conocimiento, Entrega 11). Se combina con .card--inverse, no la
   reemplaza: solo sube el tono de fondo y el borde un escalón,
   heredando el resto (color de texto, radios, hover, hijos) tal
   cual. No crear una tarjeta nueva desde cero por esto. */
.card--reading {
  background-color: var(--qa-navy-700);
  border-color: var(--qa-navy-500);
}

/* --- Estados de tarjeta ---------------------------------------------------
   Reposo → :hover ya definido arriba. Se agregan aquí los estados
   restantes: seleccionable (para filtros de Industrias en Fase 4),
   deshabilitada, y foco de teclado (cuando la tarjeta completa es
   un elemento interactivo, ej. <a class="card">). */

.card:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 3px;
}

.card--selectable {
  cursor: pointer;
}

.card--selected {
  border-color: var(--color-accent);
  border-width: 2px;
  box-shadow: var(--elevation-2);
}

.card--selected .card__eyebrow {
  color: var(--qa-navy-800);
}

.card[aria-disabled="true"] {
  cursor: not-allowed;
  opacity: 0.55;
}

.card[aria-disabled="true"]:hover {
  border-color: var(--color-border);
  box-shadow: none;
  transform: none;
}

/* --------------------------------------------------------------------
   BADGES
   Etiquetas de estado. La variante "dev" (ámbar) es de uso EXCLUSIVO
   para señalar contenido de la Plataforma SCO V2.0 que aún está en
   desarrollo (ver Fase 3, observación 4 — nunca presentar como
   disponible). No usar el color ámbar fuera de este componente.
   -------------------------------------------------------------------- */

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
}

.badge--dev {
  color: #8A5A0F;
  background-color: var(--color-status-dev-bg);
  border-color: var(--color-status-dev);
}

.badge--neutral {
  color: var(--color-text-muted);
  background-color: var(--qa-paper-100);
  border-color: var(--color-border);
}

.badge--accent {
  /* Corrección sistémica (Entrega 10): el color original (navy-800
     sobre un 12% de opacidad cian) asumía un fondo CLARO detrás del
     chip. Desde la Entrega 4 toda la identidad es predominantemente
     oscura, y las 16 apariciones actuales de esta variante están
     sobre fondo navy — el resultado era ~1.2:1 de contraste real
     (prácticamente ilegible). Se corrige aquí, una sola vez, en vez
     de parchar cada badge en cada sección.
     Nota para el futuro: si esta variante vuelve a usarse alguna vez
     sobre un fondo CLARO (ej. una página de lectura larga del Centro
     de Conocimiento), crear `.badge--accent-on-light` en vez de
     revertir este cambio — hoy el 100% del uso real es sobre oscuro. */
  color: var(--qa-cyan-300);
  background-color: rgba(31, 169, 154, 0.16);
  border-color: var(--color-accent);
}

/* --------------------------------------------------------------------
   ICONOGRAFÍA
   Los íconos viven como <symbol> en assets/icons/sprite.svg y se
   consumen así: <svg class="icon"><use href="assets/icons/sprite.svg#nombre"/></svg>
   Estilo: trazo (outline), 24x24, sin relleno — grosor de línea
   constante en todo el set (ver sprite.svg para el listado disponible).
   -------------------------------------------------------------------- */

.icon {
  width: 1.25rem;
  height: 1.25rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex-shrink: 0;
}

.icon--sm { width: 1rem; height: 1rem; }
.icon--lg { width: 1.75rem; height: 1.75rem; }

/* --------------------------------------------------------------------
   FORMULARIOS
   Sistema base de campos. No se usa todavía en ninguna página (el
   formulario de Contacto se construye en una entrega dedicada), pero
   queda definido ahora para que todo el sitio use exactamente los
   mismos estilos de campo cuando llegue ese momento.
   -------------------------------------------------------------------- */

.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-bottom: var(--space-5);
}

.field__label {
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-text);
}

.field__label .field__required {
  color: var(--color-error-500);
  margin-left: var(--space-1);
}

.field__hint {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

/* Input, textarea y select comparten la misma superficie base */
.input,
.textarea,
.select {
  width: 100%;
  min-height: var(--hit-target-min);
  padding: var(--space-3) var(--space-4);
  font-family: var(--font-body);
  font-size: var(--text-base);
  color: var(--color-text);
  background-color: var(--color-bg-elevated);
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius-sm);
  transition: border-color var(--duration-fast) var(--ease-standard),
              box-shadow var(--duration-fast) var(--ease-standard);
}

.textarea {
  min-height: 120px;
  resize: vertical;
}

/* Estado: hover */
.input:hover,
.textarea:hover,
.select:hover {
  border-color: var(--qa-steel-400);
}

/* Estado: foco — anillo de foco propio además del outline global,
   para que el campo se distinga incluso cuando el navegador aplica
   estilos de foco distintos entre sí (Safari vs. Chrome, etc.) */
.input:focus-visible,
.textarea:focus-visible,
.select:focus-visible {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px rgba(31, 169, 154, 0.18);
}

/* Estado: deshabilitado */
.input:disabled,
.textarea:disabled,
.select:disabled {
  background-color: var(--color-disabled-bg);
  border-color: var(--color-disabled-border);
  color: var(--color-disabled-text);
  cursor: not-allowed;
}

/* Estado: placeholder */
.input::placeholder,
.textarea::placeholder {
  color: var(--qa-steel-400);
}

/* Estado: error — se activa agregando .field--error al contenedor */
.field--error .input,
.field--error .textarea,
.field--error .select {
  border-color: var(--color-error-500);
}

.field--error .input:focus-visible,
.field--error .textarea:focus-visible {
  box-shadow: 0 0 0 3px rgba(192, 57, 43, 0.15);
}

.field__error-message {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--color-error-500);
}

/* Corrección sistémica (Entrega 11): `display: flex` de la regla de
   arriba es una declaración de autor y le gana a la regla nativa del
   navegador `[hidden] { display: none }` — sin esto, cualquier
   mensaje de error con el atributo `hidden` en el HTML igual se
   mostraba al cargar la página. Mismo tipo de causa raíz que la
   corrección de contraste de h1-h6 en .card--inverse (Entrega 8):
   una declaración directa sobre el elemento vence al mecanismo que
   debería ocultarlo. Aplica a CUALQUIER uso futuro de este
   componente, no solo al formulario de Contacto. */
.field__error-message[hidden] {
  display: none;
}

/* Estado: válido/éxito — se activa con .field--success */
.field--success .input,
.field--success .textarea,
.field--success .select {
  border-color: var(--color-success-500);
}

.field__success-message {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--color-success-500);
}

/* Misma corrección preventiva que .field__error-message[hidden]
   arriba — no hay ningún uso con `hidden` todavía en el sitio, pero
   el componente queda consistente para cuando se use. */
.field__success-message[hidden] {
  display: none;
}

/* Checkbox y radio — mantienen el tamaño mínimo de accesibilidad
   mediante un área de toque invisible más grande que el cuadro visible */
.field-choice {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  min-height: var(--hit-target-min);
}

.field-choice input[type="checkbox"],
.field-choice input[type="radio"] {
  width: 20px;
  height: 20px;
  margin-top: 2px;
  accent-color: var(--color-accent);
  flex-shrink: 0;
}

/* --------------------------------------------------------------------
   EYEBROW
   Etiqueta corta sobre un título de sección (fuente mono, mayúsculas).
   -------------------------------------------------------------------- */

.eyebrow {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-accent);
  margin-bottom: var(--space-3);
}
