/**
 * ============================ CANTO ============================
 *
 * Los tokens del lenguaje visual del producto, en un solo sitio.
 * Documento normativo: `docs/diseno/mockups/estilo-canto.html` (DIS-002).
 *
 * Lo carga cada frontal ANTES de su propia hoja, así que cualquiera puede
 * redefinir un token después si tiene motivo — y el panel de plataforma lo hace.
 *
 * ---------------- POR QUÉ EXISTE ESTE FICHERO ----------------
 *
 * Hasta el 21-8-2026 estos tokens estaban copiados en las cuatro hojas, y con
 * dos vocabularios distintos: `oficina` y `plataforma` en castellano (`--tinta`,
 * `--canto`, `--rojo`) y las dos apps de campo en inglés (`--ink`, `--accent`,
 * `--red`), con los mismos valores.
 *
 * El coste real de eso no era la duplicación: era que **el acento de la vertical
 * estaba en seis ficheros**. DIS-002 y el CLAUDE.md dicen que es *"el único token
 * que cambia al levantar una vertical nueva"*, y `web/medicion/estilo.css` tenía
 * esa frase escrita literalmente encima de una de las cuatro copias. Levantar
 * PharmaFlow habría sido buscar `#0e6e62` por el repositorio.
 *
 * Ahora se cambia aquí, en una línea, y cambia en todo el producto.
 *
 * ---------------- LOS NOMBRES EN INGLÉS ----------------
 *
 * Se conservan como alias, y no es dejadez. Renombrarlos obligaría a tocar
 * `var(--ink)` en 2.275 líneas de CSS de las dos apps de campo para no mover ni
 * un píxel, y ese es exactamente el cambio que rompe algo sin que nadie se
 * entere. Apuntan al mismo token, no a otra copia: cambiar `--canto` mueve
 * `--accent` con él.
 *
 * Unificar el vocabulario es un cambio aparte, y se puede hacer un día con
 * calma, hoja a hoja, sin que nada dependa de ello.
 */

:root {
  /* ---------------------------------------------------------- superficie */
  --tinta: #1d1d1f;
  --subtinta: #55565a;
  --hairline: #d2d2d7;
  --panel: #f5f5f7;
  --blanco: #ffffff;

  /* ------------------------------------------------------------- el canto
   *
   * El color del material, y el único color de acción de todo el sistema
   * (DIS-002 §04). No hay azul genérico, ni un segundo acento.
   *
   * **ESTE ES EL TOKEN QUE CAMBIA AL LEVANTAR UNA VERTICAL**, y ahora sí es
   * uno: GlassFlow #0E6E62 · PharmaFlow #1B4FA0. El de las dos CurlFlow está
   * pendiente y lo elige Raúl. El de MetalFlow era #8A4B2A, y esa vertical
   * salió del catálogo el 14-8-2026.
   */
  --canto: #0e6e62;
  --canto-s: #e2f0ed;
  --canto-h: #0b564c;

  /* --------------------------------------------------------- semánticos
   *
   * Verificados AA. Solo hablan de ESTADO, nunca de acción: si algo es verde
   * es porque ha ido bien, no porque se pueda pulsar. Lo pulsable es el canto.
   */
  --verde: #137a3c;
  --verde-s: #e6f5ec;
  --ambar: #8a5200;
  --ambar-s: #fdf2de;
  --rojo: #c62e23;
  --rojo-s: #fdecea;

  /* ------------------------------------------------------------- medida */
  --r-sup: 14px;
  --r-ctrl: 9px;
  --r-pill: 11px;
  /* Densidad primero: 32px. El modo cómodo de 40 es preferencia del usuario,
     no el arranque (DIS-002 §05). */
  --fila: 32px;
  --toque: 44px;
  --sf: -apple-system, 'SF Pro Text', 'SF Pro Display', 'Helvetica Neue', Helvetica, sans-serif;
  --mono: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;

  /* ============================================================= alias
   *
   * Los nombres con los que las dos apps de campo llaman a los tokens de
   * arriba. No son copias: son referencias, así que cambiar el original los
   * mueve. Ver la cabecera.
   *
   * `--tap` NO está aquí a propósito. Las apps de campo usan 56px donde la
   * oficina usa 44 (`--toque`), y eso no es una copia mal hecha: es un dedo con
   * guante en una obra contra un ratón en una mesa. Cada app se lo declara.
   */
  --ink: var(--tinta);
  --subink: var(--subtinta);
  --white: var(--blanco);
  --accent: var(--canto);
  --accent-soft: var(--canto-s);
  /* Dos nombres para el canto pulsado: `instalador` lo llamó `-hard` y
     `medicion` `-hueso`. Los dos apuntan al mismo sitio. */
  --accent-hard: var(--canto-h);
  --accent-hueso: var(--canto-h);
  --green: var(--verde);
  --green-soft: var(--verde-s);
  --amber: var(--ambar);
  --amber-soft: var(--ambar-s);
  --red: var(--rojo);
  --red-soft: var(--rojo-s);
}

/* ======================= LA ESPERA DEL ARRANQUE =======================
 *
 * Lo único que este fichero define además de tokens, y por el mismo motivo que
 * los tokens están aquí: la alternativa era la misma pantalla copiada en las
 * cuatro hojas. Nació en `medicion` el 21-8-2026 y subió aquí el 7-9-2026, al
 * ponerla en los otros tres frontales.
 *
 * Tapa la maqueta mientras la app decide qué pantalla toca. Existe por lo que
 * tapa: el módulo va diferido, así que el navegador pinta primero lo que hay en
 * el HTML —la pantalla de acceso— y encima iba apareciendo la de verdad según
 * contestaba `/yo`. Eran dos o tres pantallas en medio segundo.
 *
 * Va con la marca y no con un rectángulo vacío porque son las tres décimas en
 * las que se abre la app: lo que se ve ahí es lo que parece la app.
 *
 * Canto, igual que el resto: fondo de panel, la letra de siempre, el verde solo
 * en el acento de la marca y en el aro. Ni sombra, ni degradado, ni logotipo
 * inventado. */
.espera {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  background: var(--panel);
  opacity: 1;
  transition: opacity 0.22s ease;
}

/* Se va con una transición y luego se apaga del todo: mientras se desvanece ya
   no se puede tocar, que si no se traga el primer toque de la pantalla que hay
   debajo. */
.espera.se-va {
  opacity: 0;
  pointer-events: none;
}

.espera-marca {
  margin: 0;
  font-size: 26px;
  font-weight: 600;
  letter-spacing: -0.022em;
  color: var(--tinta);
  animation: espera-entra 0.34s ease-out both;
}

.espera-marca em {
  font-style: normal;
  color: var(--canto);
}

.espera-txt {
  margin: 0;
  font-size: 13px;
  color: var(--subtinta);
  animation: espera-entra 0.34s ease-out 0.06s both;
}

/* Con `prefers-reduced-motion` el aro se queda quieto —la regla de arriba del
   todo apaga toda animación— y lo que dice que se está esperando es el texto de
   debajo, no el giro. */
.espera-rueda {
  width: 30px;
  height: 30px;
  border: 3px solid var(--hairline);
  border-top-color: var(--canto);
  border-radius: 50%;
  animation: espera-gira 0.9s linear infinite;
}

@keyframes espera-gira {
  to {
    transform: rotate(360deg);
  }
}

@keyframes espera-entra {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* ======================= EL DESPLEGABLE =======================
 *
 * La otra cosa que este fichero define además de tokens, y por el mismo motivo
 * que `.espera`: la alternativa era copiarla en las cuatro hojas. Su
 * comportamiento está en `desplegable.js`, al lado.
 *
 * Existe porque la lista desplegada de un `<select>` la pinta el sistema y no
 * la hoja: `appearance: none` llega a la caja cerrada y ni una regla más allá.
 *
 * Canto, como todo lo demás: borde igual por los cuatro lados, sin sombra y sin
 * degradado. La lista se separa del fondo con el borde y no con una sombra, que
 * es lo que la mayoría de sistemas de diseño hacen y aquí no se admite. */
.desp {
  position: relative;
}

.desp-boton {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  min-height: var(--fila);
  padding: 0 10px;
  font: inherit;
  color: var(--tinta);
  text-align: left;
  background: var(--blanco);
  border: 1px solid var(--hairline);
  border-radius: var(--r-ctrl);
  cursor: pointer;
}

/* La flecha. Un triángulo de bordes y no una imagen ni una fuente de iconos:
   es la misma tinta del texto, así que hereda el color sin una segunda regla. */
.desp-boton::after {
  content: '';
  flex: none;
  width: 0;
  height: 0;
  border: 4px solid transparent;
  border-top-color: var(--subtinta);
  transform: translateY(2px);
}

.desp-boton[aria-expanded='true']::after {
  transform: translateY(-2px) rotate(180deg);
}

/* El foco manda el acento, igual que en cualquier campo. Abierto también: lo
   que está pasando es que se está eligiendo ahí. */
.desp-boton:focus-visible,
.desp-boton[aria-expanded='true'] {
  border-color: var(--canto);
  outline: none;
}

.desp-boton[aria-invalid='true'] {
  border-color: var(--rojo);
}

.desp-boton[aria-invalid='true']:focus-visible {
  border-color: var(--canto);
}

/* Sin nada elegido, la tinta baja: es un rótulo de qué se pide, no un valor. */
.desp-txt-vacia {
  color: var(--subtinta);
}

.desp-lista {
  position: absolute;
  z-index: 30;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  max-height: 264px;
  overflow-y: auto;
  padding: 4px;
  background: var(--blanco);
  border: 1px solid var(--hairline);
  border-radius: var(--r-ctrl);
}

/* Abierta hacia arriba: lo decide `abreArriba` en `desplegable.js`, midiendo el
   hueco que queda a cada lado dentro del contenedor que se desplaza. */
.desp.desp-arriba .desp-lista {
  top: auto;
  bottom: calc(100% + 4px);
}

.desp-op {
  display: block;
  width: 100%;
  min-height: var(--fila);
  padding: 6px 8px;
  font: inherit;
  color: var(--tinta);
  text-align: left;
  background: none;
  border: 0;
  border-radius: 7px;
  cursor: pointer;
}

.desp-op:hover {
  background: var(--panel);
}

/* La que está puesta lleva el canto suave; la que tiene el foco, el aro. Son
   dos cosas distintas —lo elegido y dónde estoy— y por eso se ven distintas. */
.desp-op[aria-selected='true'] {
  color: var(--canto);
  background: var(--canto-s);
}

.desp-op:focus-visible {
  outline: 2px solid var(--canto);
  outline-offset: -2px;
}

.desp-op[disabled] {
  color: var(--subtinta);
  cursor: not-allowed;
  opacity: 0.55;
}

/* El rótulo de un grupo de opciones, el viejo `<optgroup>`. Ni negrita ni
   mayúsculas: es una separación, no un encabezado que compita con lo elegible. */
.desp-grupo {
  padding: 8px 8px 4px;
  color: var(--subtinta);
  font-size: 11.5px;
}

.desp-grupo + .desp-op,
.desp-lista [role='group'] .desp-op {
  padding-left: 16px;
}

/* ======================= SIN ESTILOS INLINE =======================
 *
 * Producción aplica `style-src 'self'`: cualquier `style="…"` del marcado se
 * rechaza, aunque lo haya escrito nuestro propio JavaScript. Estas utilidades
 * pequeñas viven en la hoja común para que los cuatro frontales puedan expresar
 * los ajustes de composición sin abrir `unsafe-inline` ni duplicarlos. */
.definiciones-svg {
  position: absolute !important;
}
.margen-superior-4 {
  margin-top: 4px !important;
}
.margen-superior-8 {
  margin-top: 8px !important;
}
.margen-superior-10 {
  margin-top: 10px !important;
}
.margen-superior-12 {
  margin-top: 12px !important;
}
.margen-superior-14 {
  margin-top: 14px !important;
}
.margen-inferior-12 {
  margin-bottom: 12px !important;
}
.margen-inferior-14 {
  margin-bottom: 14px !important;
}
.margen-inferior-16 {
  margin-bottom: 16px !important;
}
.margen-0-inferior-12 {
  margin: 0 0 12px !important;
}
.margen-6-0 {
  margin: 6px 0 0 !important;
}
.margen-8-0-14 {
  margin: 8px 0 14px !important;
}
.margen-8-0 {
  margin: 8px 0 0 !important;
}
.margen-12-16 {
  margin: 12px 16px !important;
}
.margen-12-16-0 {
  margin: 12px 16px 0 !important;
}
.sin-margen {
  margin: 0 !important;
}
.al-final {
  margin-left: auto !important;
}
.contenido-al-inicio {
  justify-content: flex-start !important;
}
.relleno-8 {
  padding: 8px !important;
}
.relleno-16 {
  padding: 16px !important;
}
.bloque-pie {
  padding: 12px 16px !important;
  border-top: 1px solid var(--hairline) !important;
}
.texto-preformateado {
  white-space: pre-wrap !important;
}
.texto-contexto-pequeno {
  color: var(--subtinta) !important;
  font-size: 11.5px !important;
}
.relleno-suavizado {
  display: block !important;
  width: 1px !important;
  min-width: 1px !important;
  max-width: 1px !important;
  flex: none !important;
}

/* ============ LAS CASILLAS DE UN CÓDIGO DE UN SOLO USO ============

   Seis huecos de una cifra, que es como se pide un código en todas partes. El
   foco manda el acento, igual que en cualquier campo de la casa, y no hay más
   señal que el borde: un código a medio escribir no es un error.

   `ch` y no píxeles en el ancho: la casilla se mide por la cifra que lleva
   dentro, así que sigue cuadrada si algún día cambia el cuerpo de la letra. */
.codigo {
  display: flex;
  gap: 8px;
  justify-content: center;
}

.codigo-casilla {
  width: 3.2ch;
  height: var(--toque);
  padding: 0;
  font: inherit;
  font-size: 20px;
  font-variant-numeric: tabular-nums;
  text-align: center;
  color: var(--tinta);
  background: var(--blanco);
  border: 1px solid var(--hairline);
  border-radius: var(--r-ctrl);
}

.codigo-casilla:focus-visible {
  border-color: var(--canto);
  outline: none;
}

/* ============================================================ LA ENTRADA
 * Los logos de la pantalla de entrar (Raúl, 27-9-2026): el símbolo de Occam y,
 * si la empresa de esa dirección ha subido el suyo en el panel (V023), el suyo
 * al lado, separados por un filete. Sin logo subido, solo el de Occam.
 *
 * En pantalla ancha ocupan la mitad derecha y la entrada se queda a la
 * izquierda; cómo se aparta la entrada es de cada frontal, porque cada uno la
 * monta distinto. En el móvil van encima de la entrada y no la mueven de sitio.
 *
 * El verde de fondo es un encargo expreso y la excepción a que el acento sea
 * solo de lo que se pulsa: plano, sin degradado. Los logos van en una placa
 * blanca porque el de un cliente trae sus colores, y sobre verde puede no
 * leerse. */
.entrada-marcas {
  display: flex;
  justify-content: center;
  margin: 0 0 20px;
}

.entrada-placa {
  display: flex;
  align-items: center;
  gap: 18px;
}

.entrada-occam {
  flex: none;
  width: 40px;
  height: 40px;
  color: var(--tinta);
}

/* Alto fijo y el ancho que pida su proporción, con un tope: así se acota
   cualquier logo, apaisado o cuadrado, sin deformarlo (`contain`). El alto va
   fijo y no `auto` porque un SVG sin `width` ni `height` propios no tiene
   tamaño, y con `auto` el navegador lo dejaba en una esquina (V024). */
.entrada-empresa {
  display: none;
  width: auto;
  height: 40px;
  max-width: 160px;
  object-fit: contain;
  object-position: left center;
}

.entrada-marcas.con-empresa .entrada-empresa {
  display: block;
  padding-left: 18px;
  border-left: 1px solid var(--hairline);
}

@media (min-width: 1100px) {
  .entrada-marcas {
    position: fixed;
    inset: 0 0 0 50%;
    z-index: 1;
    align-items: center;
    margin: 0;
    background: var(--canto);
  }

  .entrada-placa {
    gap: 32px;
    padding: 36px 44px;
    border-radius: 20px;
    background: var(--blanco);
  }

  .entrada-occam {
    width: 72px;
    height: 72px;
  }

  .entrada-empresa {
    height: 72px;
    max-width: 240px;
  }

  .entrada-marcas.con-empresa .entrada-empresa {
    padding-left: 32px;
  }
}
