/* =====================================================================
   Nutrition Side — sistema de diseño
   Paleta y tipografía tomadas de docs/diseno/*.dc.html (maquetas reales).

   Dos superficies:
     por omisión  sitio público    — blanco y crema, navy y verde
     .oscuro      área de miembros — navy profundo, para ver video sin fatiga

   Mobile first. Lo que crece usa clamp(), no media queries sueltas.
   ===================================================================== */

@font-face {
  font-family: "Glacial Indifference";
  src: url("/fonts/glacial-indifference-bold.otf") format("opentype");
  font-style: normal;
  font-weight: 700;
  font-display: swap;
}

:root {
  /* --- marca: valores exactos de los archivos del logotipo --- */
  --oliva:  #8D8B55;
  --perla:  #E8E8E0;
  --rosa:   #F5E5D7;
  --blanco: #FFFFFF;
  --negro:  #000000;

  /* Compatibilidad con nombres usados por los componentes. No son tonos
     nuevos: remiten estrictamente a los cinco colores permitidos. */
  --oliva-oscuro: var(--negro);
  --oliva-hover:  var(--oliva);
  --negro-80:     var(--negro);
  --negro-60:     var(--negro);
  --negro-40:     var(--negro);

  /* El oliva del logotipo no puede sostener texto blanco: 3.53:1. Este es el
     MISMO tono (H58 S25 %) seis puntos de luminosidad más oscuro, y con blanco
     da 4.56:1. Se usa solo como SUPERFICIE de botón; como texto sobre perla o
     rosa seguiría fallando (3.70:1), así que ahí no se usa. */
  --oliva-boton:       #7A7849;
  --oliva-boton-hover: #6B6940;

  /* Alias heredados: toda la interfaz depende de la misma paleta. */
  --navy:        var(--negro);
  --navy-80:     var(--negro-80);
  --navy-60:     var(--negro-60);
  --navy-40:     var(--negro-40);
  --verde:       var(--oliva);
  --verde-hover: var(--oliva-hover);
  --verde-hondo: var(--oliva-oscuro);

  --crema:        var(--rosa);
  --arena:        var(--rosa);
  --menta:        var(--perla);
  --piedra:       var(--perla);
  --piedra-clara: var(--perla);
  --hueso:        var(--perla);

  /* --- texto accesible --- */
  --tinta:       var(--negro);
  --tinta-suave: rgba(0,0,0,.78);
  --tinta-tenue: rgba(0,0,0,.64);
  --hielo:       var(--blanco);
  --hielo-suave: var(--perla);
  --hielo-tenue: var(--perla);
  --hielo-apaga: var(--perla);

  /* --- semánticos ---
     Estos NO son colores de marca: son señales, y su única función es
     distinguirse. Estaban aliasados a la paleta del logotipo (--ok y --aviso al
     oliva, --error al negro), con el resultado de que un mensaje de error se
     veía idéntico al texto normal y una tarjeta «requiere atención» idéntica a
     una tranquila. Los tres pasan 4.5:1 sobre las tres superficies de la marca
     —blanco, perla y rosa—, medidos, no elegidos a ojo. */
  --ok:    #4A6B2A;   /* 6.13 blanco · 4.97 perla · 4.98 rosa */
  --aviso: #8A5A12;   /* 5.91 · 4.80 · 4.81 */
  --error: #A3301F;   /* 7.00 · 5.68 · 5.69 */

  /* --- tipografía --- */
  /* Jost conserva correctamente las tildes y la ñ en titulares grandes. */
  --tit: Jost, "Century Gothic", "Helvetica Neue", system-ui, sans-serif;
  --ui:  Jost, "Century Gothic", "Helvetica Neue", system-ui, sans-serif;

  /* Escala fluida: el valor menor manda en móvil, el mayor en escritorio */
  --t-display: clamp(2.25rem, 1.30rem + 4.2vw, 4.125rem);  /* 36 -> 66px */
  --t-h1:      clamp(1.95rem, 1.30rem + 2.9vw, 3.375rem);  /* 31 -> 54px */
  --t-h2:      clamp(1.60rem, 1.20rem + 1.8vw, 2.625rem);  /* 26 -> 42px */
  --t-h3:      clamp(1.25rem, 1.08rem + 0.8vw, 1.75rem);   /* 20 -> 28px */
  --t-cuerpo:  clamp(0.97rem, 0.93rem + 0.18vw, 1.06rem);  /* 15.5 -> 17px */
  --t-menor:   0.875rem;
  --t-micro:   0.75rem;

  /* --- ritmo --- */
  --r1: 4px;   --r2: 8px;   --r3: 12px;  --r4: 16px;
  --r5: 24px;  --r6: 32px;  --r7: 48px;  --r8: 64px;  --r9: 96px;

  --margen: clamp(1.25rem, 0.6rem + 3vw, 3.5rem);
  --ancho:  1240px;

  --curva:   18px;
  --pildora: 60px;    /* etiquetas y chips: ahí la píldora sí corresponde */
  --radio-btn: 10px;  /* botones: la píldora completa en TODA acción de la
                         página es de los tells más reconocibles de una interfaz
                         generada, y aquí además arrastraba el aire del
                         WordPress anterior. */

  --sombra:      0 1px 2px rgba(0,0,0,.06), 0 4px 16px rgba(0,0,0,.06);
  --sombra-alta: 0 8px 40px rgba(0,0,0,.12);

  --transicion: 160ms cubic-bezier(.4,0,.2,1);
}

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

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

body {
  margin: 0;
  font-family: var(--ui);
  font-size: var(--t-cuerpo);
  line-height: 1.6;
  color: var(--tinta);
  background: var(--blanco);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, video, svg { max-width: 100%; height: auto; display: block; }
button, input, select, textarea { font: inherit; color: inherit; }

h1, h2, h3, h4 {
  font-family: var(--tit);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -0.015em;
  text-wrap: balance;
  margin: 0;
}
h1 { font-size: var(--t-h1); }
h2 { font-size: var(--t-h2); }
h3 { font-size: var(--t-h3); letter-spacing: -0.01em; }
p  { margin: 0 0 1em; text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

a { color: inherit; text-decoration: none; }

/* Foco visible siempre. Es requisito de accesibilidad, no adorno. */
:focus-visible {
  outline: 2px solid var(--oliva-boton);
  outline-offset: 3px;
  border-radius: var(--r1);
}

/* Salto al contenido, para teclado y lector de pantalla */
.saltar {
  position: absolute; left: -9999px;
  background: var(--navy); color: var(--blanco);
  padding: var(--r3) var(--r5);
  border-radius: 0 0 var(--curva) 0;
  z-index: 100;
}
.saltar:focus { left: 0; top: 0; }

/* =====================================================================
   Estructura
   ===================================================================== */
.envoltura {
  width: 100%; max-width: var(--ancho);
  margin-inline: auto; padding-inline: var(--margen);
}
.seccion       { padding-block: clamp(3rem, 1.6rem + 6vw, 6rem); }
.seccion-corta { padding-block: clamp(2rem, 1.2rem + 3vw, 3.5rem); }

/* Patrones sutiles reutilizables: dan ritmo sin competir con el contenido. */
.patron-suave {
  background-color: var(--blanco);
  background-image: radial-gradient(rgba(141,139,85,.14) .8px, transparent .8px);
  background-size: 24px 24px;
}
.patron-lineal {
  background-color: var(--crema);
  background-image: linear-gradient(135deg, rgba(141,139,85,.07) 25%, transparent 25%,
    transparent 50%, rgba(141,139,85,.07) 50%, rgba(141,139,85,.07) 75%,
    transparent 75%, transparent);
  background-size: 34px 34px;
}
.catalogo-hero { padding-block: clamp(2.5rem, 2rem + 3vw, 4.5rem); }
.catalogo-productos {
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 380px));
  justify-content: start;
}
.rejilla.tres.catalogo-servicios {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  align-items: stretch;
}
@media (max-width: 980px) {
  .rejilla.tres.catalogo-servicios { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 620px) {
  .rejilla.tres.catalogo-servicios { grid-template-columns: 1fr; }
}

.crema { background: var(--crema); }
.menta { background: var(--menta); }
.arena { background: var(--arena); }
.navy  { background: var(--navy); color: var(--hielo); }
.navy h1, .navy h2, .navy h3 { color: var(--blanco); }

/* =====================================================================
   `hidden` tiene que ganar SIEMPRE.

   El navegador trae `[hidden] { display: none }`, pero es una regla de
   agente de usuario: cualquier clase nuestra que declare `display` la pisa
   por especificidad. Y aquí casi todas lo declaran —`.pila` es flex,
   `.aviso` es flex, `.btn` es inline-flex—, así que poner el atributo en
   el HTML o `el.hidden = true` desde el JS no ocultaba nada.

   Costó tres defectos a la vez en la pantalla de pago, y los tres parecían
   independientes: los campos de tarjeta se veían antes de elegir tarjeta,
   la caja de error se pintaba vacía como una barra rosa, y el botón de
   «Continuar» convivía con el de «Pagar» —dos botones de pago a la vez—.
   Era una sola causa.
   ===================================================================== */
[hidden] { display: none !important; }

.pila  { display: flex; flex-direction: column; }
.fila  { display: flex; align-items: center; flex-wrap: wrap; }
.entre { justify-content: space-between; }
.centro{ justify-content: center; }
.g1 { gap: var(--r1); } .g2 { gap: var(--r2); } .g3 { gap: var(--r3); }
.g4 { gap: var(--r4); } .g5 { gap: var(--r5); } .g6 { gap: var(--r6); }

/* Rejilla que se reacomoda sola, sin media query por columna */
.rejilla        { display: grid; gap: var(--r5); }
.rejilla.dos    { grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); }
.rejilla.tres   { grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); }
.rejilla.cuatro { grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr)); }

/* =====================================================================
   Tipografía de apoyo
   ===================================================================== */
.display {
  font-family: var(--tit); font-weight: 700; font-size: var(--t-display);
  line-height: 1.02; letter-spacing: -0.02em; text-wrap: balance;
}
.rotulo {
  font-size: var(--t-micro); letter-spacing: .22em; text-transform: uppercase;
  color: var(--tinta-tenue); font-weight: 500;
}
.navy .rotulo, .oscuro .rotulo { color: var(--hielo-apaga); }

.entrada { font-size: clamp(1.02rem, .95rem + .4vw, 1.2rem); color: var(--tinta-suave); max-width: 62ch; }
.navy .entrada, .oscuro .entrada { color: var(--hielo-suave); }

.menor { font-size: var(--t-menor); }
.tenue { color: var(--tinta-tenue); }
.oscuro .tenue, .navy .tenue { color: var(--hielo-apaga); }
.medio { font-weight: 600; }

/* =====================================================================
   Botones
   ===================================================================== */
/* =====================================================================
   BOTONES

   El primario era OLIVA DE MARCA con texto NEGRO. Medido, ese par da
   5.96:1 —pasa AA— pero se lee turbio: negro sobre un verde apagado es el
   contraste de una etiqueta, no el de una llamada a la acción.

   El blanco sobre el oliva de marca (#8D8B55) da 3.53:1 y NO pasa a tamaño
   de botón. Así que el oliva se oscurece seis puntos de luminosidad —mismo
   tono H58 S25 %, de L44 % a L38 %— y el blanco sube a 4.56:1. Sigue siendo
   el verde del logotipo, solo que capaz de sostener texto claro.

       #8D8B55 + negro   5.96:1   turbio
       #8D8B55 + blanco  3.53:1   FALLA
       #7A7849 + blanco  4.56:1   <- este

   El radio deja de ser píldora completa. Un botón totalmente redondeado en
   cada acción de la página es de los tells más reconocibles de una interfaz
   generada, y aquí además arrastraba el aire del WordPress anterior.
   ===================================================================== */
.btn {
  --btn-fondo: var(--oliva-boton);
  --btn-texto: var(--blanco);
  --btn-borde: transparent;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--r2);
  min-height: 48px;                 /* objetivo táctil cómodo en móvil */
  padding: 0 var(--r5);
  border: 1px solid var(--btn-borde);
  border-radius: var(--radio-btn);
  background: var(--btn-fondo);
  color: var(--btn-texto);
  font-size: var(--t-menor); font-weight: 600; letter-spacing: .01em;
  cursor: pointer; text-align: center;
  /* Solo color y transform: son las dos propiedades que el navegador
     compone sin recalcular la página. */
  transition: background var(--transicion), border-color var(--transicion),
              transform 90ms cubic-bezier(.4,0,.2,1);
}
.btn:hover  { --btn-fondo: var(--oliva-boton-hover); }

/* La respuesta va en el hundido, no en el color: se siente inmediata porque
   ocurre al APRETAR, no al soltar. */
.btn:active { transform: translateY(1px) scale(.985); }
.btn[disabled], .btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; }

.btn.contorno { --btn-fondo: transparent; --btn-texto: var(--tinta); --btn-borde: rgba(0,0,0,.22); }
.btn.contorno:hover { --btn-fondo: rgba(0,0,0,.04); --btn-borde: rgba(0,0,0,.4); }
.oscuro .btn.contorno,
.navy .btn.contorno {
  --btn-texto: var(--blanco);
  --btn-borde: rgba(255,255,255,.28);
}
.oscuro .btn.contorno:hover,
.navy .btn.contorno:hover { --btn-fondo: rgba(255,255,255,.08); }

.btn.tinta { --btn-fondo: var(--navy); --btn-texto: var(--blanco); }
.btn.tinta:hover { --btn-fondo: var(--negro); box-shadow: 0 0 0 3px var(--perla); }

.btn.ancho  { width: 100%; }
.btn.chico  { min-height: 38px; padding: 0 var(--r4); font-size: var(--t-micro); }
.btn.grande { min-height: 56px; padding: 0 var(--r6); font-size: 1rem; }

.enlace {
  color: var(--verde-hondo); font-weight: 500; text-decoration: underline;
  text-underline-offset: 3px; text-decoration-thickness: 1px;
}
.enlace:hover { color: var(--tinta); }
.oscuro .enlace, .navy .enlace { color: var(--verde); }

/* =====================================================================
   Tarjetas
   ===================================================================== */
.tarjeta {
  background: var(--blanco);
  border: 1px solid rgba(0,0,0,.10);
  border-radius: var(--curva);
  padding: var(--r5);
  transition: border-color var(--transicion), box-shadow var(--transicion), transform var(--transicion);
}
.tarjeta.enlazable:hover { border-color: rgba(0,0,0,.28); box-shadow: var(--sombra); }
.tarjeta.destacada { border-color: var(--verde); box-shadow: 0 0 0 1px var(--verde); }

.oscuro .tarjeta { background: var(--navy-80); border-color: var(--navy-60); }
.oscuro .tarjeta.enlazable:hover { border-color: var(--navy-40); box-shadow: none; }

/* Tarjetas editoriales de programas, consultas y productos. */
.tarjeta-producto {
  display: grid; grid-template-rows: auto 1fr;
  padding: 0; overflow: hidden; min-height: 100%;
  border-radius: 24px; box-shadow: var(--sombra);
}
.tarjeta-producto:hover { transform: translateY(-2px); }
.producto-imagen {
  display: grid; place-items: center; aspect-ratio: 1 / 1;
  overflow: hidden; background: linear-gradient(145deg, var(--blanco), var(--crema));
  border-bottom: 1px solid rgba(0,0,0,.08);
}
.producto-imagen img { width: 100%; height: 100%; object-fit: contain; }
.producto-imagen.recorte-anualidad img { object-fit: cover; object-position: 40% center; }
.producto-sin-imagen {
  max-width: 16ch; padding: var(--r6); text-align: center;
  font-family: var(--tit); font-size: clamp(1.5rem, 1rem + 2vw, 2.5rem);
  font-weight: 700; line-height: 1.05;
}
.producto-contenido { padding: clamp(var(--r5), 3vw, var(--r6)); }
.producto-contenido h3 {
  font-size: clamp(1.25rem, 1.08rem + .55vw, 1.65rem);
  overflow-wrap: normal;
  word-break: normal;
  hyphens: none;
}
.producto-ficha-imagen {
  display: grid; place-items: center; overflow: hidden;
  aspect-ratio: 1 / 1; max-width: 620px;
  background: var(--crema); border-radius: 24px;
}
.producto-ficha-imagen img { width: 100%; height: 100%; object-fit: contain; }

.beneficio { padding: clamp(var(--r5), 3vw, var(--r6)); }
.numero-beneficio {
  color: var(--verde-hondo); font-family: var(--tit); font-size: var(--t-menor);
  font-weight: 700; letter-spacing: .12em;
}
.llamada-programas {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--r7); padding: clamp(var(--r6), 5vw, var(--r8));
  background: var(--menta); border-color: rgba(141,139,85,.20);
}
.acceso-existente {
  padding: var(--r5); overflow: hidden;
  background-color: var(--crema);
  background-image: radial-gradient(rgba(141,139,85,.16) .8px, transparent .8px);
  background-size: 20px 20px;
  border-color: rgba(141,139,85,.20);
}
.acceso-existente .btn { align-self: flex-start; }
@media (max-width: 760px) {
  .llamada-programas { align-items: flex-start; flex-direction: column; }
}

/* Marcador de estado */
.marca {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px var(--r3); border-radius: var(--pildora);
  font-size: var(--t-micro); font-weight: 600; letter-spacing: .02em;
  background: rgba(0,0,0,.06); color: var(--tinta-suave);
  white-space: nowrap;
}
.marca.vigente { background: var(--perla); color: var(--negro); }
.marca.espera  { background: var(--rosa); color: var(--negro); }
.marca.vencida { background: var(--rosa); color: var(--negro); }
.oscuro .marca { background: rgba(255,255,255,.07); color: var(--hielo-suave); }
.oscuro .marca.vigente { background: var(--oliva); color: var(--negro); }

/* Portada con relación de aspecto fija: evita el salto al cargar */
.portada {
  aspect-ratio: 16 / 9;
  background: linear-gradient(140deg, var(--perla), var(--oliva));
  border-radius: calc(var(--curva) - 4px);
  position: relative; overflow: hidden;
}
.portada img { width: 100%; height: 100%; object-fit: cover; }
.portada .play {
  position: absolute; right: 12px; bottom: 12px;
  display: grid; place-items: center;
}
.portada .play span {
  width: 42px; height: 42px; border-radius: 50%;
  background: var(--oliva-boton); color: var(--blanco); display: grid; place-items: center;
  box-shadow: 0 4px 14px rgba(0,0,0,.24);
}
.barra-avance {
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 4px; background: rgba(0,0,0,.35);
}
.barra-avance i { display: block; height: 100%; background: var(--verde); }

/* =====================================================================
   Formularios
   ===================================================================== */
.campo { display: flex; flex-direction: column; gap: 6px; margin-bottom: var(--r4); }
.campo label { font-size: var(--t-menor); font-weight: 500; }
.campo .ayuda { font-size: var(--t-micro); color: var(--tinta-tenue); }
.oscuro .campo .ayuda { color: var(--hielo-apaga); }

.campo input, .campo select, .campo textarea {
  min-height: 48px; padding: 0 var(--r4);
  background: var(--blanco);
  border: 1px solid rgba(0,0,0,.22);
  border-radius: var(--curva);
  width: 100%;
  transition: border-color var(--transicion), box-shadow var(--transicion);
}
.campo textarea { min-height: 120px; padding: var(--r3) var(--r4); resize: vertical; line-height: 1.5; }
.campo input:focus, .campo select:focus, .campo textarea:focus {
  outline: none; border-color: var(--verde);
  box-shadow: 0 0 0 3px rgba(141,139,85,.28);
}
.control-contrasena { position: relative; }
.control-contrasena > input { padding-right: 56px; }
/* Edge pinta su propio ojo dentro del campo: junto al nuestro saldrían dos. */
.control-contrasena > input::-ms-reveal,
.control-contrasena > input::-ms-clear { display: none; }
.alternar-contrasena {
  position: absolute; top: 50%; right: 6px; transform: translateY(-50%);
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; padding: 0;
  border: 0; border-radius: 50%;
  background: transparent; color: var(--tinta-tenue); cursor: pointer;
  transition: color var(--transicion), background-color var(--transicion);
}
.alternar-contrasena:hover { color: var(--tinta); background: rgba(141,139,85,.12); }
.alternar-contrasena:focus-visible {
  outline: 2px solid var(--verde); outline-offset: 1px;
}
.icono-contrasena {
  width: 22px; height: 22px; fill: none; stroke: currentColor;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}
.icono-contrasena-ocultar { display: none; }
.alternar-contrasena[aria-pressed="true"] .icono-contrasena-mostrar { display: none; }
.alternar-contrasena[aria-pressed="true"] .icono-contrasena-ocultar { display: block; }
.oscuro .campo input, .oscuro .campo select, .oscuro .campo textarea {
  background: var(--navy); border-color: var(--navy-40); color: var(--hielo);
}
.campo.malo input, .campo.malo select, .campo.malo textarea { border-color: var(--error); }
.campo .error { font-size: var(--t-micro); color: var(--error); font-weight: 500; }

/* La entradilla biográfica es deliberadamente más grande que la historia:
   el peso deja claro que es una presentación, no un error de dimensiones. */
.acerca-intro { font-weight: 600; }

/* Aviso general de formulario */
.aviso {
  display: flex; gap: var(--r3); align-items: flex-start;
  padding: var(--r3) var(--r4); border-radius: var(--curva);
  font-size: var(--t-menor); margin-bottom: var(--r4);
  border: 1px solid transparent;
}
.aviso.malo   { background: var(--rosa); border-color: var(--negro); color: var(--negro); }
.aviso.bien   { background: var(--perla); border-color: var(--oliva); color: var(--negro); }
.aviso.neutro { background: rgba(0,0,0,.04);      border-color: rgba(0,0,0,.12);     color: var(--tinta-suave); }
.oscuro .aviso.neutro { background: rgba(255,255,255,.05); border-color: var(--navy-60); color: var(--hielo-suave); }
.oscuro .aviso.malo   { color: var(--negro); }

/* =====================================================================
   Tablas — en móvil se convierten en fichas apiladas
   ===================================================================== */
.tabla { width: 100%; border-collapse: collapse; font-size: var(--t-menor); }
.tabla th {
  text-align: left; font-size: var(--t-micro); text-transform: uppercase;
  letter-spacing: .12em; color: var(--tinta-tenue); font-weight: 600;
  padding: var(--r3) var(--r4); border-bottom: 1px solid rgba(0,0,0,.12);
}
.tabla td { padding: var(--r4); border-bottom: 1px solid rgba(0,0,0,.08); vertical-align: middle; }
.oscuro .tabla th { color: var(--hielo-apaga); border-bottom-color: var(--navy-60); }
.oscuro .tabla td { border-bottom-color: var(--navy-60); }
.tabla .num { text-align: right; font-variant-numeric: tabular-nums; }

.tabla-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

@media (max-width: 640px) {
  .tabla.apila thead { display: none; }
  .tabla.apila tr {
    display: block; padding: var(--r4) 0;
    border-bottom: 1px solid rgba(0,0,0,.10);
  }
  .oscuro .tabla.apila tr { border-bottom-color: var(--navy-60); }
  .tabla.apila td {
    display: grid; grid-template-columns: 40% 1fr; gap: var(--r3);
    padding: 4px 0; border: 0;
  }
  .tabla.apila td::before {
    content: attr(data-rotulo);
    font-size: var(--t-micro); text-transform: uppercase; letter-spacing: .1em;
    color: var(--tinta-tenue); font-weight: 600;
  }
  .oscuro .tabla.apila td::before { color: var(--hielo-apaga); }
  .tabla.apila .num { text-align: left; }
}

/* =====================================================================
   Precio
   ===================================================================== */
.precio { display: flex; align-items: baseline; gap: 6px; }
.precio .cifra {
  font-family: var(--tit); font-weight: 700;
  font-size: clamp(1.9rem, 1.5rem + 1.6vw, 2.6rem); letter-spacing: -.02em;
}
.precio .moneda { font-size: var(--t-menor); color: var(--tinta-tenue); font-weight: 600; }
.oscuro .precio .moneda { color: var(--hielo-apaga); }

/* =====================================================================
   htmx — retroalimentación mientras vuela la petición
   ===================================================================== */
.htmx-indicator { opacity: 0; transition: opacity var(--transicion); }
.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator { opacity: 1; }
.htmx-request .oculta-al-cargar { opacity: .4; pointer-events: none; }

.girador {
  width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid rgba(0,0,0,.18); border-top-color: var(--verde);
  animation: gira .7s linear infinite;
}
.oscuro .girador { border-color: rgba(255,255,255,.2); border-top-color: var(--verde); }
@keyframes gira { to { transform: rotate(360deg); } }

/* Cuando no hay nada que mostrar, decirlo bien */
.vacio { text-align: center; padding: var(--r8) var(--r5); color: var(--tinta-tenue); }
.oscuro .vacio { color: var(--hielo-apaga); }
.vacio h3 { color: var(--tinta); margin-bottom: var(--r2); }
.oscuro .vacio h3 { color: var(--hielo); }

.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;
}

/* =====================================================================
   CUESTIONARIO DE CONSULTA
   Hasta 29 preguntas en una pantalla. Lo que las hace legibles es el aire
   entre ellas y que cada bloque de opciones se lea como una unidad.
   ===================================================================== */

.seccion-cuestionario { margin-top: var(--r8); }

.cuestionario {
  background: var(--blanco);
  border: 1px solid rgba(0,0,0,.10);
  border-radius: var(--r5);
  padding: clamp(var(--r5), 3vw, var(--r7));
  margin-bottom: var(--r5);
}

.cuestionario .campo { margin-bottom: 0; }

.cuestionario .titulo-bloque {
  font-size: var(--t-h3);
  margin-top: var(--r4);
  padding-bottom: var(--r3);
  border-bottom: 1px solid rgba(0,0,0,.10);
}

.separador-campo {
  border: 0; border-top: 1px solid rgba(0,0,0,.08); margin: var(--r3) 0;
}

.obligatorio { color: var(--error); font-weight: 700; margin-left: 2px; }

/* Grupos de opciones: fieldset sin el marco feo del navegador */
.grupo-opciones { border: 0; padding: 0; margin: 0; }

.grupo-opciones legend {
  font-size: var(--t-menor); font-weight: 500;
  padding: 0; margin-bottom: var(--r3);
}

/* Las opciones se acomodan en rejilla: en escritorio caben dos o tres por
   fila, y una lista de siete enfermedades deja de ser una columna infinita. */
.grupo-opciones .opciones {
  display: grid; gap: var(--r2);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 230px), 1fr));
}

.grupo-opciones .opcion {
  display: flex; align-items: center; gap: var(--r3);
  padding: var(--r3) var(--r4);
  border: 1px solid rgba(0,0,0,.16);
  border-radius: var(--r3);
  cursor: pointer;
  font-size: var(--t-menor); font-weight: 400; line-height: 1.35;
  transition: border-color var(--transicion), background var(--transicion);
}

.grupo-opciones .opcion:hover { border-color: rgba(0,0,0,.34); background: rgba(0,0,0,.02); }

/* :has da el resaltado de lo elegido sin JavaScript. Donde no exista,
   el control marcado se ve igual: solo se pierde el fondo. */
.grupo-opciones .opcion:has(input:checked) {
  border-color: var(--verde);
  background: var(--perla);
  font-weight: 500;
}

.grupo-opciones .opcion:has(input:focus-visible) {
  outline: 2px solid var(--verde); outline-offset: 2px;
}

/* IMPRESCINDIBLE. Arriba, `.campo input` da min-height:48px, width:100% y
   borde redondeado a TODO input dentro de un .campo. Un fieldset de opciones
   también es .campo, así que sin este reinicio cada radio se dibuja como un
   campo de texto gigante con el círculo al centro y la etiqueta expulsada
   fuera de la caja. Se restaura el control nativo. */
.grupo-opciones .opcion input[type="radio"],
.grupo-opciones .opcion input[type="checkbox"] {
  flex: none;
  width: 19px; height: 19px; min-height: 0;
  margin: 0; padding: 0;
  border: 0; border-radius: 0;
  background: none;
  box-shadow: none;
  appearance: auto; -webkit-appearance: auto;
  accent-color: var(--oliva);
  cursor: pointer;
}

.grupo-opciones .opcion span { flex: 1; }

/* Subida de foto. El ejemplo va al lado del control, no debajo: se mira la
   postura y se elige el archivo en el mismo golpe de vista. */
.campo-archivo {
  padding: var(--r4);
  border: 1px dashed rgba(0,0,0,.22);
  border-radius: var(--r3);
  background: rgba(0,0,0,.02);
}

.archivo-fila {
  display: flex; gap: var(--r4); align-items: flex-start; flex-wrap: wrap;
}

.archivo-ejemplo { margin: 0; flex: none; width: 150px; }

.archivo-ejemplo img {
  width: 100%; height: auto;
  border-radius: var(--r2);
  border: 1px solid rgba(0,0,0,.12);
}

.archivo-ejemplo figcaption { margin-top: var(--r1); text-align: center; }

.archivo-control { flex: 1 1 240px; min-width: 0; }

/* El input de archivo también hereda el min-height:48px de .campo input.
   Aquí estorba: el botón nativo queda flotando en una caja vacía. */
.campo-archivo input[type="file"] {
  min-height: 0; width: 100%;
  padding: var(--r3);
  background: var(--blanco);
  border: 1px solid rgba(0,0,0,.22);
  border-radius: var(--r3);
  font-size: var(--t-menor);
  cursor: pointer;
}

.campo-archivo input[type="file"]::file-selector-button {
  margin-right: var(--r3);
  padding: 6px var(--r4);
  border: 0; border-radius: var(--radio-btn);
  background: var(--oliva-boton); color: var(--blanco);
  font-size: var(--t-micro); font-weight: 600;
  cursor: pointer;
}

.campo-archivo input[type="file"]::file-selector-button:hover { background: var(--oliva-boton-hover); }

/* Foto ya guardada, en el expediente. Miniatura de tamaño fijo y recortada
   al centro: las fotos de frente y de lado llegan del teléfono en todas las
   proporciones, y a su tamaño natural una vertical ocupaba media pantalla. Al
   pulsarla se abre entera. */
.adjunto-foto {
  position: relative; display: inline-block;
  width: 180px; max-width: 100%;
  border-radius: var(--r3); overflow: hidden;
  text-decoration: none;
}
.adjunto-foto img {
  display: block;
  width: 100%; aspect-ratio: 3 / 4; object-fit: cover;
  border: 1px solid rgba(0,0,0,.14);
  border-radius: var(--r3);
  background: var(--perla);
}
.adjunto-foto:hover img,
.adjunto-foto:focus-visible img { border-color: var(--oliva-boton); }
.adjunto-foto-accion {
  position: absolute; left: 8px; bottom: 8px;
  padding: 3px 8px; border-radius: 999px;
  background: rgba(0,0,0,.62); color: #fff;
  font-size: .78rem; line-height: 1.4;
}

/* Un documento del expediente (PDF de laboratorio, foto HEIC): tarjeta que
   se abre, no una imagen rota. */
.adjunto-documento {
  display: inline-flex; align-items: center; gap: 12px;
  padding: 12px 16px;
  border: 1px solid rgba(0,0,0,.14); border-radius: var(--r3);
  background: #fff; color: var(--tinta); text-decoration: none;
}
.adjunto-documento:hover,
.adjunto-documento:focus-visible { border-color: var(--oliva-boton); }
.adjunto-documento svg {
  width: 30px; height: 30px; flex: none;
  fill: none; stroke: var(--oliva-boton); stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}

.aviso-previo {
  align-items: flex-start;
  padding: var(--r3) var(--r4);
  border-radius: var(--r3);
  background: var(--perla);
  border: 1px solid var(--oliva);
  color: var(--negro);
}

.aviso-previo svg { flex: none; margin-top: 2px; }

.error-formulario {
  padding: var(--r3) var(--r4);
  border-radius: var(--r3);
  background: var(--rosa);
  border: 1px solid var(--negro);
  color: var(--negro);
  font-size: var(--t-menor);
  margin-bottom: var(--r4);
}

.nota-privacidad { display: flex; align-items: center; gap: var(--r2); }

/* =====================================================================
   EXPEDIENTE — el cuestionario ya contestado, en solo lectura
   ===================================================================== */

.lista-datos { display: grid; gap: var(--r3); margin: 0; }

.lista-datos dt {
  font-size: var(--t-micro); color: var(--tinta-tenue);
  text-transform: none; letter-spacing: 0;
}

.lista-datos dd { margin: 2px 0 0; font-size: var(--t-menor); font-weight: 500; }

.lista-datos.compacta { gap: var(--r2); }

.valores-varios { margin: 0; padding-left: var(--r4); font-weight: 400; }

.expediente-encabezado { align-items: flex-start; }

.tarjeta-enlace { text-decoration: none; color: inherit; transition: border-color .15s ease; }
.tarjeta-enlace:hover { border-color: rgba(0,0,0,.28); box-shadow: var(--sombra); }

/* =====================================================================
   REDES SOCIALES
   ===================================================================== */

/* Los glifos de marca ya tienen forma propia y reconocible. Meterlos en un
   círculo con contorno los encoge y los aplana a todos por igual: se leen
   como una fila de botones grises, no como Instagram, Facebook y TikTok.
   Van sueltos, más grandes, y cada uno toma su color de marca al pasar. */
.redes { display: flex; gap: var(--r4); flex-wrap: wrap; align-items: center; }

.redes a {
  display: inline-flex;
  color: var(--tinta-suave);
  opacity: .75;
  transition: opacity var(--transicion), color var(--transicion), transform var(--transicion);
}

.redes a svg { display: block; width: 21px; height: 21px; }

.redes a:hover { opacity: 1; transform: translateY(-2px); }

/* Colores oficiales de cada marca */
.redes a.red-ig:hover { color: #FF0069; }
.redes a.red-fb:hover { color: #0866FF; }
.redes a.red-tiktok:hover { color: #000000; }
.redes a.red-wa:hover { color: #25D366; }

/* El pie es de superficie clara (--crema), así que hereda el tono del pie.
   La superficie oscura del área de miembros sí necesita el suyo. */
.oscuro .redes a, .navy .redes a { color: var(--hielo-suave); }

/* El pie pone display:block y padding a todos sus enlaces; en la fila de
   iconos eso desalinea los glifos con el texto de la arroba. */
.pie .redes a { padding-block: 0; }

/* =====================================================================
   WHATSAPP FLOTANTE
   Solo lo ve quien no tiene sesión. Abre con una casilla, sin JavaScript.
   ===================================================================== */

.wa-flotante {
  position: fixed; right: var(--r5); bottom: var(--r5);
  z-index: 60;
  display: flex; flex-direction: column; align-items: flex-end; gap: var(--r3);
}

.wa-burbuja {
  display: flex; align-items: center; justify-content: center;
  width: 56px; height: 56px; border-radius: 50%;
  border: 0; padding: 0;
  background: #25D366; color: #fff;
  box-shadow: var(--sombra-alta);
  cursor: pointer;
  transition: transform .15s ease;
}

.wa-burbuja:hover { transform: scale(1.06); }

/* Presentación oficial de WhatsApp: verde de marca con glifo blanco. */
.wa-burbuja svg { width: 30px; height: 30px; }

.wa-tarjeta {
  position: relative;
  display: flex; flex-direction: column; gap: var(--r3);
  width: min(300px, calc(100vw - var(--r6)));
  padding: var(--r5);
  background: var(--blanco);
  border: 1px solid rgba(0,0,0,.10);
  border-radius: var(--r5);
  box-shadow: var(--sombra-alta);

  opacity: 0; visibility: hidden; transform: translateY(8px);
  transition: opacity .2s ease, transform .2s ease, visibility .2s;
}

.wa-flotante.wa-abierta .wa-tarjeta {
  opacity: 1; visibility: visible; transform: none;
}

/* Quien pidió menos movimiento no recibe la apertura automática. */
@media (prefers-reduced-motion: reduce) {
  .wa-tarjeta { transition: none; }
}

.wa-cerrar {
  position: absolute; top: var(--r3); right: var(--r3);
  display: flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 50%;
  border: 0; padding: 0; background: transparent;
  color: var(--tinta-tenue); cursor: pointer;
}

.wa-cerrar:hover { background: rgba(0,0,0,.06); color: var(--tinta); }

.wa-boton {
  background: #25D366; border-color: #25D366; color: #fff;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--r2);
}

.wa-boton svg { width: 17px; height: 17px; flex: none; }

.wa-boton:hover { background: #1FB855; border-color: #1FB855; }

@media (max-width: 480px) {
  .wa-flotante { right: var(--r4); bottom: var(--r4); }
}

/* Referencia histórica cuyo archivo ya no existía al hacer el corte. No es un
   enlace: se conserva el nombre sin prometer una descarga inexistente. */
.adjunto {
  display: inline-flex; align-items: center; gap: var(--r2);
  padding: 4px var(--r3);
  border: 1px dashed rgba(0,0,0,.22);
  border-radius: var(--r2);
  font-size: var(--t-menor);
  color: var(--tinta-suave);
  word-break: break-all;
}

.adjunto svg { flex: none; }
.adjunto em { font-style: normal; }

/* Barra de moneda de la ficha. Va sobre las dos columnas y fuera del
   formulario de compra: un <form> dentro de otro es HTML inválido. */
.barra-moneda {
  justify-content: flex-end;
  margin-bottom: var(--r5);
}

/* Marca de precio convertido. Discreta pero visible: la cifra es una
   referencia del día, no un precio de lista. */
.precio .aprox {
  font-size: .55em; color: var(--tinta-tenue); font-weight: 500;
  margin-right: 2px; vertical-align: middle;
}
.oscuro .precio .aprox { color: var(--hielo-apaga); }

/* Precio tachado de una oferta. Va antes del precio de ahora, que es el orden
   en que se lee, y en tinta tenue: lo que importa es lo que se cobra. */
.precio .precio-antes {
  font-size: .5em; color: var(--tinta-tenue); font-weight: 500;
  text-decoration: line-through; margin-right: var(--r2);
}
.oscuro .precio .precio-antes { color: var(--hielo-apaga); }

/* =====================================================================
   Acción destructiva

   La usan el panel —borrar a una persona— y el perfil —pedir la baja—, así
   que vive aquí y no en `ns-panel.css`, que no se carga en el área de
   miembros. Estuvo un rato en rosa pálido con borde negro y en una fila de
   acciones se leía como una opción más; va en rojo sólido porque el color es
   la última advertencia antes de escribir el correo completo.
   Blanco sobre `--error` (#A3301F) son 7.00:1.
   ===================================================================== */
.btn.peligro {
  --btn-fondo: var(--error);
  --btn-texto: var(--blanco);
  --btn-borde: transparent;
  min-height: 42px;
}
.btn.peligro:hover { --btn-fondo: #8A281A; }

/* =====================================================================
   Foto de perfil
   ===================================================================== */
.foto-perfil {
  display: flex; flex-wrap: wrap; gap: var(--r6);
  align-items: flex-start;
}
.foto-perfil-muestra {
  width: 120px; height: 120px; border-radius: 50%;
  overflow: hidden; flex-shrink: 0;
  background: var(--oliva-boton); color: var(--blanco);
  display: grid; place-items: center;
  font-family: var(--tit); font-size: 2rem; font-weight: 600;
  letter-spacing: .02em;
}
.foto-perfil-muestra img { width: 100%; height: 100%; object-fit: cover; display: block; }
.foto-perfil-acciones { flex: 1 1 260px; min-width: 0; }

/* La zona de baja no grita: no es un error ni una alerta, es una opción
   legítima. Se separa con un filete y el peso lo lleva el botón. */
.zona-baja { border-color: rgba(163,48,31,.30); }
.zona-baja h2 { color: var(--error); }

/* =====================================================================
   Campos de tarjeta de PayPal dentro del carrito.

   Cada campo es un IFRAME de PayPal, así que no se le puede dar estilo al
   input: se estiliza el marco que lo contiene y el iframe se estira dentro.
   Por eso `.marco-tarjeta` lleva la altura y el borde que en el resto del
   sitio llevaría el propio input.
   ===================================================================== */
.tarjeta-campos {
  margin-top: var(--r5);
  padding: var(--r5);
  border: 1px solid var(--navy-60);
  border-radius: var(--curva);
  background: var(--blanco);
}
.tarjeta-titulo { font-size: var(--t-h3); margin: 0; }

/* Número y titular ocupan la fila entera; vencimiento y CVV la comparten.
   Es una rejilla y no una fila de flex porque así el salto a una columna en
   el móvil lo hace el propio grid, sin una segunda regla que mantener. */
.tarjeta-rejilla {
  display: grid; gap: var(--r4);
  grid-template-columns: 1fr 1fr;
}
.tarjeta-rejilla > .ancho-total { grid-column: 1 / -1; }

.campo-tarjeta { display: block; margin: 0; min-width: 0; }
.campo-tarjeta > span {
  display: block; margin-bottom: 6px;
  font-size: var(--t-menor); color: var(--tinta-suave);
}

/* =====================================================================
   El marco NO lleva borde propio, y es a propósito.

   Dentro de cada `.marco-tarjeta` hay un iframe de PayPal que pinta su
   campo con su propia caja. Dibujando además la nuestra se veían DOS
   rectángulos redondeados concéntricos por campo, con el texto flotando
   dentro del interior: exactamente lo que se veía en la pantalla de pago.

   No se puede quitar la de dentro desde aquí —el CSS no cruza la frontera
   del iframe—, así que se quita la de fuera, que es la que sí controlamos.
   El aspecto lo pide el JS por la API de estilo del SDK.
   ===================================================================== */
.marco-tarjeta { min-height: 46px; }
.marco-tarjeta iframe { display: block; width: 100%; height: 46px; border: 0; }

@media (max-width: 520px) {
  .tarjeta-rejilla { grid-template-columns: 1fr; }
  .tarjeta-campos { padding: var(--r4); }
}

/* =====================================================================
   Pantalla de pago
   ===================================================================== */

/* Los pasos. Numerados por CSS para que el marcado siga siendo una lista
   ordenada: quien navega con lector de pantalla oye «1 de 3». */
.pasos-compra {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--r3);
  list-style: none; margin: 0 0 var(--r5); padding: 0;
  font-size: var(--t-menor); counter-reset: paso;
}
.pasos-compra li {
  display: flex; align-items: center; gap: var(--r2);
  color: var(--tinta-suave); counter-increment: paso;
}
.pasos-compra li::before {
  content: counter(paso);
  display: grid; place-items: center;
  width: 22px; height: 22px; border-radius: 50%;
  border: 1px solid var(--navy-60);
  font-size: 12px; line-height: 1;
}
/* La separación entre pasos es decorativa: no debe leerse en voz alta. */
.pasos-compra li + li::after { content: none; }
.pasos-compra li:not(:last-child) { padding-right: var(--r3); }
.pasos-compra .hecho::before,
.pasos-compra .actual::before {
  background: var(--oliva-boton); border-color: var(--oliva-boton);
  color: var(--blanco);
}
.pasos-compra .actual { color: var(--tinta); font-weight: 600; }
.pasos-compra a { color: inherit; text-decoration: underline; }

/* La columna del cobro. `min-width:0` evita que los iframes de PayPal,
   que traen ancho mínimo propio, desborden la rejilla. */
.pago-principal { min-width: 0; }

/* Si la forma elegida saca del sitio o no. Es lo único que no se podía
   deducir mirando la pantalla, y decidía si alguien abandonaba la compra.

   ⚠️ Se llamaron `.marca-sitio` y `.marca-salida` y fue un error caro:
   `marca-sitio` YA era la clase del enlace del logotipo, en las tres
   plantillas —pública, miembros y panel—. La regla le puso fondo verde y
   `border-radius: var(--pildora)`, así que el logotipo apareció dentro de
   una píldora verde clara EN TODO EL SITIO. Un nombre de clase nuevo se
   busca antes en `templates/` que en el CSS: aquí no existía y allí sí. */
.cobro-aqui, .cobro-fuera {
  display: inline-block; margin-top: 6px;
  padding: 2px 10px; border-radius: var(--pildora);
  font-size: 12px;
}
.cobro-aqui  { background: rgba(74,107,42,.12);  color: var(--ok); }
.cobro-fuera { background: rgba(0,0,0,.06);      color: var(--tinta-suave); }

/* =====================================================================
   Datos de quien compra, en la pantalla de pago.

   Estaban sueltos entre el selector de forma de cobro y el botón, con el
   estilo de un formulario cualquiera, y se leían como un apéndice. Son el
   otro bloque de la pantalla y pesan lo mismo que la tarjeta: misma caja,
   mismo aire.
   ===================================================================== */
.datos-comprador {
  padding: var(--r5);
  border: 1px solid var(--navy-60);
  border-radius: var(--curva);
  background: var(--blanco);
}

/* Nombre y correo caben en dos columnas en escritorio; en el móvil se
   apilan solos. */
.campos-comprador {
  display: grid; gap: var(--r4);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
}
.campos-comprador > label {
  display: flex; flex-direction: column; gap: 6px; min-width: 0;
  font-size: var(--t-menor); color: var(--tinta-suave); font-weight: 500;
}
.campos-comprador input {
  width: 100%; min-height: 48px; padding: 12px 14px;
  border: 1px solid rgba(0,0,0,.22); border-radius: var(--radio-btn);
  background: var(--blanco); color: var(--tinta);
  font: inherit; font-size: 16px;   /* por debajo de 16 iOS hace zoom */
  transition: border-color var(--transicion), box-shadow var(--transicion);
}
.campos-comprador input::placeholder { color: rgba(0,0,0,.38); }
.campos-comprador input:focus {
  outline: none;
  border-color: var(--oliva-boton);
  box-shadow: 0 0 0 3px rgba(122,120,73,.18);
}

/* Bloqueado no es error: se ve tranquilo y se explica al lado. */
.campos-comprador input[readonly] {
  background: var(--perla); color: var(--tinta-suave);
  border-color: transparent; cursor: default;
}
.campos-comprador input[readonly]:focus { box-shadow: none; }

/* El autorrelleno de Chrome pinta el campo de azul lavanda y se salta el
   fondo declarado: no hay forma de cambiarlo salvo con una sombra interior
   del grosor del campo. Sin esto, los datos recordados salían en un color
   que no es de la marca. */
.campos-comprador input:-webkit-autofill,
.campos-comprador input:-webkit-autofill:hover,
.campos-comprador input:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 1000px var(--blanco) inset;
  -webkit-text-fill-color: var(--tinta);
  caret-color: var(--tinta);
}

/* =====================================================================
   Cuestionario: dónde faltó contestar.

   El aviso enumera las preguntas en blanco y enlaza a cada una. Un «falta
   algo» genérico obliga a recorrer 29 preguntas a ojo buscando el hueco,
   que es justo cuando se abandona la compra.
   ===================================================================== */
.resumen-faltantes { flex-direction: column; align-items: stretch; }
.lista-faltantes { margin: 0; padding-left: 1.2em; }
.lista-faltantes li { margin-bottom: 2px; }

/* La pregunta que falta se señala en el sitio, no solo en el resumen de
   arriba: quien llega por el enlace tiene que reconocerla al aterrizar. */
.campo-falta {
  border-left: 3px solid var(--error);
  padding-left: var(--r4);
  margin-left: calc(var(--r4) * -1);
}
.campo-falta > label > span:first-child,
.campo-falta > legend { color: var(--error); font-weight: 600; }
.campo-falta input, .campo-falta textarea, .campo-falta select {
  border-color: var(--error);
}

/* El país y el número son UN campo, no dos: se pegan en una sola caja para
   que se lean como el teléfono completo que son. El selector se queda con lo
   que necesita y el número toma el resto. */
.campo-telefono { display: flex; gap: 0; }
.campo-telefono select {
  flex: 0 0 auto; max-width: 46%;
  min-height: 48px; padding: 12px 10px;
  border: 1px solid rgba(0,0,0,.22); border-right: 0;
  border-radius: var(--radio-btn) 0 0 var(--radio-btn);
  background: var(--perla); color: var(--tinta);
  font: inherit; font-size: var(--t-menor);
}
.campo-telefono input {
  flex: 1 1 auto; min-width: 0;
  border-radius: 0 var(--radio-btn) var(--radio-btn) 0;
}
/* El foco tiene que verse por encima del vecino, o el halo queda cortado. */
.campo-telefono select:focus,
.campo-telefono input:focus { position: relative; z-index: 1; }
.campo-telefono select:focus {
  outline: none; border-color: var(--oliva-boton);
  box-shadow: 0 0 0 3px rgba(122,120,73,.18);
}

/* =====================================================================
   La descripción del producto, ya con formato.

   Antes era un `<p>` con texto plano: los saltos de línea que se escribían
   en el panel los colapsaba HTML y todo salía como un ladrillo. Ahora llega
   como HTML saneado y necesita estilo propio para sus párrafos y listas.
   ===================================================================== */
/* Un párrafo de prosa pide aire; una lista de características, no. El
   margen global de `p` es 1em y con `.entrada` la letra va a 1.2rem, así que
   doce líneas cortas quedaban desparramadas por media pantalla. */
.descripcion-producto p { margin-bottom: .55em; }
.descripcion-producto > p:last-child { margin-bottom: 0; }
.descripcion-producto h3, .descripcion-producto h4 {
  font-size: var(--t-menor); text-transform: uppercase; letter-spacing: .06em;
  color: var(--tinta-suave); margin: 1.4em 0 .5em;
}
.descripcion-producto ul, .descripcion-producto ol {
  margin: 0 0 1em; padding-left: 1.3em;
}
.descripcion-producto li { margin-bottom: .3em; }
.descripcion-producto a {
  color: var(--oliva-boton); text-decoration: underline;
  text-underline-offset: 2px;
}
.descripcion-producto blockquote {
  margin: 1em 0; padding-left: var(--r4);
  border-left: 3px solid var(--oliva-boton); color: var(--tinta-suave);
}

/* =====================================================================
   Expediente: la pregunta se lee antes que la respuesta.

   Las etiquetas iban en micro y gris tenue —el tamaño más pequeño de la
   escala—, así que en un cuestionario de 29 preguntas costaba distinguir
   qué se preguntó de qué se contestó. La pregunta manda: es lo que da
   sentido al dato.
   ===================================================================== */
.expediente .lista-datos dt {
  font-size: var(--t-menor); font-weight: 600; color: var(--tinta);
}
.expediente .lista-datos dd {
  margin: 2px 0 0; font-size: var(--t-cuerpo); font-weight: 400;
  color: var(--tinta-suave);
}

/* En pantalla ancha, pregunta y respuesta en dos columnas: se recorre con
   la vista sin saltar de renglón. En móvil se apilan, que es lo único
   legible con preguntas largas. */
@media (min-width: 720px) {
  .expediente .lista-datos {
    grid-template-columns: minmax(200px, 38%) 1fr;
    align-items: baseline; gap: var(--r3) var(--r5);
  }
  .expediente .lista-datos dt { grid-column: 1; text-align: right; }
  .expediente .lista-datos dd { grid-column: 2; margin: 0; }
  /* Un filete por fila ayuda a seguir la línea en listas largas. */
  .expediente .lista-datos dd { border-bottom: 1px solid rgba(0,0,0,.06);
                                padding-bottom: var(--r2); }
}

/* =====================================================================
   Lo calculado a partir del expediente.

   Caja aparte y al final: una cosa es lo que contestó la persona y otra la
   cuenta hecha sobre ello. Mezclarlas haría parecer que el IMC lo escribió
   quien llenó el cuestionario.
   ===================================================================== */
.expediente-calculo {
  margin-top: var(--r5); padding: var(--r5);
  border: 1px solid var(--navy-60); border-radius: var(--curva);
  background: var(--perla);
}

.rejilla-calculo {
  display: grid; gap: var(--r4);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr));
}

.dato-calculo {
  display: flex; flex-direction: column; gap: 2px;
  padding: var(--r4); border-radius: var(--radio-btn);
  background: var(--blanco);
}
.dato-calculo-clave {
  font-size: var(--t-micro); text-transform: uppercase; letter-spacing: .06em;
  color: var(--tinta-tenue);
}
.dato-calculo-valor { font-size: var(--t-h3); line-height: 1.1; color: var(--tinta); }
.dato-calculo-nota  { font-size: var(--t-menor); color: var(--tinta-suave); }

/* Solo marca lo que merece una segunda mirada. En ámbar y no en rojo: es
   una señal para quien atiende, no una alarma clínica. */
.dato-calculo.atencion { box-shadow: inset 3px 0 0 var(--aviso); }
.dato-calculo.atencion .dato-calculo-nota { color: var(--aviso); font-weight: 600; }

@media (max-width: 520px) {
  .expediente-calculo { padding: var(--r4); }
  .dato-calculo { padding: var(--r3); }
}
