/* ===========================================================
   Estilos compartidos por todas las paginas del prototipo.
   Un solo lugar: lo que se cambie aca aplica a index y a
   contacto sin tener que tocar las dos.
   =========================================================== */
/* ============================================================
   ESCALA TIPOGRAFICA  (K7)  — nombrada por rol, no por tamaño
   Ritmo vertical basado en el cuerpo de lectura (K12): u = 28px
   Una sola familia (K9). Tres pesos (K8).
   ============================================================ */
:root{
  --font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

  /* Escala fluida en DOS dimensiones (K7).
     El termino lleva vw + vh a proposito: una laptop tiene ancho de
     sobra pero poca altura, asi que escalar solo con vw dejaba el
     texto demasiado grande ahi. Con vh en la formula, el contenido
     se encoge cuando la pantalla es baja y mantiene la proporcion. */
  --display:   clamp(1.7rem,  calc(-0.68rem + 1.6vw + 3.6vh), 3.5rem);  --display-lh: 1.14;
  --title-lg:  clamp(1.4rem,  calc(0.15rem + 0.8vw + 1.5vh), 2.25rem);  --title-lg-lh: 1.25;
  --title-md:  clamp(1.12rem, calc(0.7rem + 0.35vw + 0.6vh), 1.45rem);  --title-md-lh: 1.35;
  --subtitle:  clamp(1rem,    calc(0.6rem + 0.3vw + 0.7vh), 1.35rem);   --subtitle-lh: 1.45;

  /* el cuerpo apenas se mueve: por debajo de 16px deja de leerse bien (K1) */
  --body-read: clamp(1rem, calc(0.92rem + 0.28vh), 1.125rem); --body-read-lh: 1.6;
  --body-ui:   clamp(.9375rem, calc(0.88rem + 0.18vh), 1rem); --body-ui-lh: 1.5;
  --label:     0.8125rem;--label-lh: 1.6;
  --caption:   clamp(.8125rem, calc(0.78rem + 0.12vh), .875rem); --caption-lh: 1.6;

  /* ritmo vertical tambien proporcional a la altura (K12) */
  --u: clamp(19px, calc(9px + 1.6vh), 30px);
  --lectura: 68ch;      /* ancho de lectura (K3) */

  /* Alto real de la isla superior: las dos barras sumadas, con las
     mismas formulas que usan .aviso y .barra. Sirve para que el
     contenido de una pagina se separe de la isla y no de la pantalla:
     las barras tienen minimo fijo, asi que en pantallas bajas un
     respiro medido en vh se encoge cuando la isla no lo hace. */
  --isla: calc(clamp(34px, calc(26px + 1.1vh), 42px) + clamp(58px, calc(42px + 2.4vh), 78px));
  --zoom: 1.14;         /* acercamiento de la imagen del hero */

  /* color deliberadamente sobrio: la variable de este prototipo es
     la ESTRUCTURA, no el color */
  --bg:      #111821;
  --bg-alt:  #171f2a;
  --bg-card: #1c2531;
  --line:    #2b3644;
  --tx:      #e6ebf2;
  --tx-mid:  #9aa7b8;
  --tx-dim:  #6b7889;
  --acc:     #4da3ff;
  --ok:      #3fb984;
}

/* ============================================================
   TRANSICION ENTRE PAGINAS
   Se usa la View Transitions API: el navegador toma una foto de
   la pagina que sale y de la que entra, y las funde. No hace
   falta framework ni recargar de forma especial.
   La ISLA SUPERIOR se declara aparte y NO se anima: queda fija
   mientras el contenido se cruza. Ese es el detalle que hace que
   se sienta una sola aplicacion y no tres paginas sueltas.
   ============================================================ */
@view-transition{ navigation: auto }

::view-transition-old(root){
  animation:230ms cubic-bezier(.4,0,.2,1) both vt-sale;
}
::view-transition-new(root){
  animation:320ms cubic-bezier(.16,.84,.44,1) both vt-entra;
}
@keyframes vt-sale { to  {opacity:0; transform:translateY(-10px)} }
@keyframes vt-entra{ from{opacity:0; transform:translateY(14px)} }

/* la isla no se mueve: se mantiene anclada durante el cruce */
body > header{ view-transition-name: isla }
::view-transition-old(isla),
::view-transition-new(isla){ animation:none; mix-blend-mode:normal }

/* respaldo para navegadores sin la API (Firefox, Safari viejos):
   la clase la pone app.js solo si hace falta */
.sin-vt body{
  opacity:0; transform:translateY(12px);
  transition:opacity .30s ease, transform .30s cubic-bezier(.16,.84,.44,1);
}
.sin-vt body.vt-listo{opacity:1; transform:none}

@media(prefers-reduced-motion:reduce){
  ::view-transition-old(root),
  ::view-transition-new(root){animation:none}
  .sin-vt body{opacity:1;transform:none;transition:none}
}

*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
body{
  font-family:var(--font);
  font-size:var(--body-ui); line-height:var(--body-ui-lh);
  background:var(--bg); color:var(--tx);
  -webkit-font-smoothing:antialiased;
}

/* ---------- utilidades de estructura ----------
   Ancho completo de pantalla con un respiro lateral que crece con el
   viewport. Nada de columna fija centrada.                          */
:root{ --aire: clamp(16px, 2.2vw, 44px); }    /* respiro a los lados */

.wrap{width:100%;max-width:100%;margin:0;padding:0 var(--aire)}
.lectura{max-width:var(--lectura)}            /* K3 */

/* El ancho de LECTURA se conserva aunque el layout sea full-width:
   una linea de 2000px es ilegible por mas espacio que haya (K3).    */
p{max-width:var(--lectura)}
section{padding:calc(var(--u)*4) 0}           /* K12: 4u entre secciones */
.alt{background:var(--bg-alt)}                /* D3: separar por fondo, no por lineas */

h1{font-size:var(--display);line-height:var(--display-lh);font-weight:700;letter-spacing:-.02em}
h2{font-size:var(--title-lg);line-height:var(--title-lg-lh);font-weight:600;letter-spacing:-.01em}
h3{font-size:var(--title-md);line-height:var(--title-md-lh);font-weight:600}
p{font-size:var(--body-read);line-height:var(--body-read-lh);color:var(--tx-mid)}
p+p{margin-top:16px}
strong{color:var(--tx);font-weight:600}       /* K4: negrita solo para el termino clave */

.label{                                        /* K6: mayusculas solo en etiquetas cortas */
  font-size:var(--label);line-height:var(--label-lh);font-weight:600;
  text-transform:uppercase;letter-spacing:.08em;color:var(--tx-dim);
}
.caption{font-size:var(--caption);line-height:var(--caption-lh);color:var(--tx-dim)}

.enc{margin-bottom:calc(var(--u)*2)}
.enc h2{margin-top:8px}
.enc p{margin-top:12px;max-width:var(--lectura)}

/* ---------- notas de patron (se pueden apagar) ---------- */
.pat{
  display:inline-block;font-size:11px;font-weight:600;letter-spacing:.06em;
  color:#7fd4ff;background:rgba(77,163,255,.1);border:1px solid rgba(77,163,255,.28);
  border-radius:4px;padding:2px 6px;margin-left:8px;vertical-align:middle;
}
/* Se conservan en el HTML como rastro de que patron aplica cada
   seccion, pero no se muestran. */
.pat{display:none}


/* ---------- header: aviso + barra (D1) ----------
   Estructura de la referencia: una barra de aviso arriba con mensaje
   rotativo y flechas, y debajo la barra principal en tres zonas
   (enlaces · marca centrada · acciones). Se oculta al bajar y
   reaparece al subir.                                              */
body > header{
  position:fixed; top:0; left:0; right:0; z-index:50;
  transform:translateY(0);
  transition:transform .58s cubic-bezier(.22,.61,.24,1);
  will-change:transform;
}
/* El conjunto sube, y ademas cada barra se desvanece con su propio
   tiempo: la de aviso primero, la principal un instante despues.
   Ese desfase hace que el movimiento se lea como dos piezas y no
   como un bloque plano.                                          */
body > header.oculto{transform:translateY(-100%);pointer-events:none}

.aviso,.barra{will-change:opacity,transform}
.aviso{transition:opacity .40s ease, transform .48s cubic-bezier(.22,.61,.24,1)}
.barra{transition:
  opacity .44s ease .06s,
  transform .50s cubic-bezier(.22,.61,.24,1) .06s,
  background .40s ease, height .40s cubic-bezier(.22,.61,.24,1);}

body > header.oculto .aviso{opacity:0;transform:translateY(-12px)}
body > header.oculto .barra{opacity:0;transform:translateY(-8px)}

@media(prefers-reduced-motion:reduce){
  body > header,.aviso,.barra{transition:none}
}

/* --- barra de aviso --- */
.aviso{
  display:flex;align-items:center;justify-content:center;
  height:clamp(34px, calc(26px + 1.1vh), 42px);
  padding:0 var(--aire);
  background:#0c1219;
  border-bottom:1px solid rgba(255,255,255,.06);
}
/* Caja centrada con las flechas en sus extremos y el texto en medio,
   como en la referencia: alli la caja ocupa el 46% del ancho de la
   barra y el hueco a cada lado equivale al ancho del propio texto. */
.aviso-caja{
  display:flex;align-items:center;justify-content:space-between;
  width:min(34%, 760px);
  min-width:min(100%, 320px);
}
.aviso-f{
  background:none;border:0;cursor:pointer;
  color:var(--tx-dim);font:inherit;font-size:20px;line-height:1;
  padding:2px 4px;border-radius:6px;transition:color .18s ease;
}
.aviso-f:hover{color:var(--tx)}
/* Grilla de una sola celda: los seis mensajes se apilan encima uno de
   otro, pero SIGUEN EN FLUJO, asi el contenedor toma el ancho del mas
   largo. Con position:absolute la caja se colapsaba a cero y no se
   veia nada. Ademas el ancho queda fijo y las flechas no bailan.   */
.aviso-vp{display:grid;flex:1 1 auto;min-width:0;height:1.5em;overflow:hidden}
.aviso-msg{
  grid-area:1/1;
  display:flex;align-items:center;justify-content:center;
  padding:0 10px;
  white-space:nowrap;
  font-size:clamp(12px,calc(11px + .18vh),13.5px);font-weight:600;
  letter-spacing:.04em;color:var(--tx);
  /* Tres estados: el que espera esta abajo, el activo en su sitio, y
     el que sale se va hacia ARRIBA. Antes el saliente volvia hacia
     abajo y el movimiento se leia al reves.                        */
  opacity:0;transform:translateY(110%);
  transition:opacity .3s ease, transform .42s cubic-bezier(.32,.72,0,1);
  pointer-events:none;
}
.aviso-msg.activo{opacity:1;transform:translateY(0)}
.aviso-msg.sale{opacity:0;transform:translateY(-110%)}

/* con la flecha izquierda el sentido se invierte: entra desde arriba
   y sale hacia abajo, para que el gesto coincida con la direccion */
.aviso.rev .aviso-msg{transform:translateY(-110%)}
.aviso.rev .aviso-msg.activo{transform:translateY(0)}
.aviso.rev .aviso-msg.sale{transform:translateY(110%)}


/* --- barra principal: enlaces · marca · acciones --- */
.barra{
  display:grid;
  grid-template-columns:1fr auto 1fr;   /* la marca queda centrada de verdad */
  align-items:center;gap:16px;
  height:clamp(58px, calc(42px + 2.4vh), 78px);
  padding:0 var(--aire);
  background:rgba(19,26,35,.74);
  backdrop-filter:blur(18px) saturate(150%);
  -webkit-backdrop-filter:blur(18px) saturate(150%);
  border-bottom:1px solid rgba(255,255,255,.09);
  box-shadow:0 10px 34px rgba(0,0,0,.30);
}
body > header.scrolled .barra{
  height:clamp(52px, calc(38px + 2vh), 68px);
  background:rgba(11,15,21,.9);
}

.hnav{display:flex;align-items:center;gap:clamp(14px,1.8vw,30px);justify-self:start}
.hnav a{
  color:var(--tx);text-decoration:none;
  /* Toda la barra va en caja alta. Las versales piden menos cuerpo
     y mas interletrado, si no se apelmazan (K6).                  */
  text-transform:uppercase;
  font-size:clamp(12.5px,calc(11.8px + .18vh),13.8px);
  font-weight:600;
  letter-spacing:.08em;
  text-shadow:0 1px 2px rgba(0,0,0,.45);
  transition:color .18s ease;white-space:nowrap;
}
/* separa la navegacion del sitio de la ficha tecnica */
.sep{
  width:1px;height:15px;flex:0 0 1px;
  background:rgba(255,255,255,.20);
  margin:0 clamp(2px,.5vw,8px);
}
.hnav a:hover{color:var(--acc)}

/* ============================================================
   MEGA-MENU DE SERVICIOS
   Patron tomado de andersenlab.com: se abre al pasar el mouse,
   categorias en columna a la izquierda y el detalle a la derecha.
   Aca va con la paleta del sitio: fondo oscuro con desenfoque,
   el resalte es un velo blanco muy bajo y el acento es --acc.
   Por ahora solo las categorias; el detalle se llena despues.
   ============================================================ */
.mserv-btn{display:inline-flex;align-items:center;gap:5px}
.mserv-cv{
  width:13px;height:13px;flex:0 0 13px;
  fill:none;stroke:currentColor;stroke-width:2.4;
  stroke-linecap:round;stroke-linejoin:round;
  transition:transform .22s cubic-bezier(.4,0,.2,1);
}
.mserv-btn[aria-expanded="true"]{color:var(--acc)}
.mserv-btn[aria-expanded="true"] .mserv-cv{transform:rotate(180deg)}
/* subrayado que marca el menu abierto, como la linea amarilla de
   la referencia pero con el acento del sitio */
.mserv-btn::after{
  content:'';position:absolute;left:0;right:0;bottom:-19px;height:2px;
  background:var(--acc);border-radius:2px;
  transform:scaleX(0);transform-origin:center;
  transition:transform .24s cubic-bezier(.4,0,.2,1);
}
.mserv-btn{position:relative}
.mserv-btn[aria-expanded="true"]::after{transform:scaleX(1)}

.mserv{
  /* fondo solido: nada de transparencia ni desenfoque. El menu tapa
     por completo lo que hay detras, como en la referencia.        */
  background:var(--bg);
  border-bottom:1px solid var(--line);
  box-shadow:0 26px 60px rgba(0,0,0,.5);
  overflow:hidden;
}
/* [hidden] lo saca del flujo; la animacion la maneja la clase */
.mserv[hidden]{display:none}
.mserv{
  opacity:0;transform:translateY(-10px);
  transition:opacity .22s ease, transform .26s cubic-bezier(.16,.84,.44,1);
}
.mserv.abierto{opacity:1;transform:none}

.mserv-caja{
  display:grid;
  grid-template-columns:minmax(280px,26%) 1fr;
  gap:clamp(24px,3vw,56px);
  padding:clamp(20px,2.4vh,34px) var(--aire) clamp(26px,3.4vh,46px);
  /* ocupa TODA la pantalla que queda debajo de las dos barras.
     --alto-barras lo mide app.js y lo actualiza al redimensionar,
     porque las barras usan clamp() y su alto cambia con el viewport. */
  height:calc(100vh - var(--alto-barras, 116px));
  height:calc(100svh - var(--alto-barras, 116px));
  align-items:stretch;   /* las dos columnas ocupan todo el alto */
  overflow:hidden;       /* el reparto es exacto: no debe haber scroll */
}

/* ---------- columna de categorias ----------
   Las 9 se reparten el alto disponible en partes iguales: cada fila
   crece o se encoge con la pantalla, sin numeros fijos. En un
   monitor alto quedan holgadas; en una laptop se comprimen solas. */
.mserv-lista{display:flex;min-height:0}
.mserv-lista ul{
  list-style:none;
  display:flex;flex-direction:column;
  width:100%;height:100%;
}
.mserv-lista li{display:flex;flex:1 1 0;min-height:0}

/* El desplegable de Servicios lleva once categorias; el de Ficha
   tecnica, cuatro. Con el mismo tamano, once no entran en una pantalla
   de portatil y la lista se corta. Se aprieta solo esta:
     - menos relleno vertical y menos tipografia
     - un alto minimo por fila, para que apretar no las deje ilegibles
   El otro desplegable no cambia. */
/* Los grupos llenan su columna y aun asi no cambian de tamano al
   cambiar de grupo.
   ------------------------------------------------------------------
   Las dos cosas se peleaban. Las filas de la izquierda se reparten el
   alto de la caja -`ul{height:100%}` y `li{flex:1 1 0}`-, y la caja
   medía lo que midiera el panel de la derecha: con trece subgrupos
   -Codigo, Laboratorio- se estiraba, y con tres -Tableros- se
   encogia. Las filas daban saltos. Medido: forzando el panel a 760px,
   cada fila pasaba de 80px a 190px.

   Antes esto se resolvio soltando la lista, que dejo de llenar la
   columna. La causa real era otra: que la caja cambiara de alto. Asi
   que ahora los cinco paneles de Ficha tecnica ocupan la MISMA celda y
   el que no toca se queda ahi, apagado pero midiendo. La celda vale
   siempre lo que vale el mas alto, sea cual sea el grupo, y encima de
   una caja quieta la lista puede llenar su columna tranquila.

   El precio, y es real: con un grupo de pocos subgrupos -Tableros- la
   derecha queda con aire de sobra, porque reserva el alto del grupo
   mas grande.

   Servicios no necesita nada de esto: su caja ya tiene alto fijo
   -toda la pantalla menos las barras-, el mismo para los once. */
#panel-ficha .mserv-detalle{display:grid}
#panel-ficha .mserv-panel-cat,
#panel-ficha .mserv-vacio{grid-area:1 / 1;align-self:start}
/* apagado a la vista, pero sigue ocupando su sitio y midiendo */
#panel-ficha .mserv-panel-cat[hidden]{display:block;visibility:hidden}

/* Ficha tecnica lleva cinco grupos y Servicios once. Con el mismo
   tamano, cinco nombres en una columna pensada para once se quedan
   chicos para lo que son: son el indice de la seccion. Se agrandan
   solo estos.
   ------------------------------------------------------------------
   Crecer aqui no mueve nada de la derecha, y no es casualidad:
     - el ancho de la columna es una pista de la rejilla
       -minmax(280px,26%)-, no depende del contenido, asi que la letra
       mas grande no empuja al panel;
     - las filas ya miden lo que mide su contenido y se quedan arriba
       -flex:0 0 auto-, asi que tampoco arrastran el alto.
   Medido antes y despues: el panel de subgrupos no cambia ni un pixel. */
/* El tamano de letra de los grupos es el MISMO en los dos
   desplegables. La formula vive aqui, una sola vez: si se cambia, se
   cambia en los dos y no se pueden separar sin querer. */
#panel-ficha .mserv-cat,
#panel-serv .mserv-cat{
  font-size:clamp(16.5px,calc(14.4px + .58vh),22px);
}

#panel-ficha .mserv-cat{
  padding:clamp(11px,1.35vh,19px) 18px;
  gap:16px;
  border-radius:12px;
}
#panel-ficha .mserv-lista ul{gap:4px}
#panel-ficha .mserv-ch{width:19px;height:19px;flex-basis:19px;stroke-width:2.4}

/* Servicios crece igual que Ficha tecnica, pero aqui el tamano no es
   libre: son once categorias y su desplegable ocupa toda la pantalla
   -.mserv-caja tiene alto fijo y overflow:hidden-, asi que pasarse
   significa que las ultimas filas se cortan.
   Por eso la letra y el relleno van atados a la altura de la ventana
   con clamp: en un monitor alto quedan como las de Ficha tecnica, y en
   una pantalla baja se aprietan solas hasta el minimo legible.
   Medido de 560 a 1080 px de alto: las once entran siempre.
   Y por si algun dia no entraran -una categoria mas, un zoom alto-,
   la lista se desplaza en vez de perder filas sin avisar. */
#panel-serv .mserv-cat{
  /* la letra la pone la regla compartida de arriba; aqui solo el
     relleno, que sigue siendo mas corto: once filas contra cinco */
  padding:clamp(7px,1.05vh,13px) 18px;
  gap:16px;
  border-radius:12px;
  min-height:30px;
}
/* Las once filas se reparten el alto de la columna, pero se repartian
   tambien lo que no habia: con `flex:1 1 0` y `min-height:0` una fila
   podia quedar mas baja que su propio texto. Un nombre de dos lineas
   -"ERP, CRM y facturacion electronica"- medido 45px vivia en una fila
   de 31 y se salia por arriba y por abajo, encima del nombre siguiente.
   Y no habia aviso: la lista nunca desbordaba, porque encoger las filas
   la hacia caber siempre.

   Ahora crecen pero no se encogen por debajo de su texto. Cuando las
   once ya no entran -pantalla baja, zoom alto- la lista se desplaza,
   que era lo que esta linea decia hacer desde el principio. */
#panel-serv .mserv-lista li{flex:1 0 auto}
#panel-serv .mserv-lista{overflow-y:auto;min-height:0}
#panel-serv .mserv-lista ul{gap:3px}
#panel-serv .mserv-ch{width:19px;height:19px;flex-basis:19px;stroke-width:2.4}
/* la caja deja de exigir el alto pensado para pocas filas */
#panel-serv .mserv-detalle{min-height:clamp(240px,30vh,380px)}
.mserv-cat{
  flex:1;
  display:flex;align-items:center;justify-content:space-between;gap:14px;
  padding:clamp(8px,1vh,16px) 16px;
  border-radius:10px;
  color:var(--tx);text-decoration:none;
  font-size:clamp(14px,calc(12.4px + .42vh),18px);
  font-weight:600;line-height:1.25;
  letter-spacing:-.005em;
  transition:background .18s ease, color .18s ease;
}
.mserv-cat span{min-width:0}
.mserv-ch{
  width:16px;height:16px;flex:0 0 16px;
  fill:none;stroke:currentColor;stroke-width:2.2;
  stroke-linecap:round;stroke-linejoin:round;
  opacity:0;transform:translateX(-4px);
  transition:opacity .18s ease, transform .18s ease;
}
.mserv-cat:hover,
.mserv-cat:focus-visible,
.mserv-cat.activa{
  background:rgba(255,255,255,.055);
  color:var(--acc);
  outline:none;
}
.mserv-cat:hover .mserv-ch,
.mserv-cat:focus-visible .mserv-ch,
.mserv-cat.activa .mserv-ch{opacity:1;transform:none}

/* ---------- panel derecho (vacio por ahora) ---------- */
.mserv-detalle{
  border-left:1px solid var(--line);
  padding-left:clamp(24px,3vw,56px);
  min-height:clamp(260px,34vh,420px);
}

@media(max-width:1000px){
  .mserv{display:none !important}   /* en movil manda otro patron */
}
@media(prefers-reduced-motion:reduce){
  .mserv,.mserv-cv,.mserv-ch,.mserv-btn::after{transition:none}
}
/* pagina actual: mismo azul que el hover, pero fijo. Se marca con
   aria-current="page" en el enlace, asi que cualquier pagina nueva
   lo hereda sin tocar el CSS. Sirve ademas para lectores de
   pantalla, no solo para el color. */
.hnav a[aria-current="page"]{color:var(--acc)}

.marca{
  justify-self:center;text-decoration:none;
  /* En caja alta el interletrado va positivo y el cuerpo baja:
     las mayusculas ocupan mas ancho visual al mismo tamaño.     */
  text-transform:uppercase;
  font-size:clamp(15px,calc(13.5px + .42vh),19px);font-weight:700;
  letter-spacing:.10em;color:var(--tx);
  text-shadow:0 1px 2px rgba(0,0,0,.45);white-space:nowrap;
}
.marca span{color:var(--acc);font-weight:700}

.acciones{display:flex;align-items:center;gap:clamp(8px,1vw,16px);justify-self:end}
/* ---------- switch de idioma ----------
   Segmentado con indicador deslizante. Usa la misma paleta que el
   resto: borde --line, acento --acc a baja opacidad. Deliberadamente
   mas discreto que el boton "Hablemos": es control, no llamada a la
   accion, y no debe competir con el CTA. */
.idioma{
  position:relative; display:inline-flex; align-items:center;
  background:rgba(255,255,255,.05);
  border:1px solid var(--line);
  border-radius:999px;
  padding:2px; cursor:pointer;
  font:inherit; line-height:1; white-space:nowrap;
  transition:border-color .18s ease, background .18s ease;
}
.idioma:hover{border-color:#31404f;background:rgba(255,255,255,.08)}
.idioma:focus-visible{outline:2px solid var(--acc);outline-offset:2px}

/* la pista mide exactamente medio interior; al pasar a EN se
   desplaza el 100% de SU ancho, que es justo el segundo segmento */
.idioma__pista{
  position:absolute; top:2px; left:2px;
  width:calc(50% - 2px); height:calc(100% - 4px);
  border-radius:999px;
  background:rgba(77,163,255,.16);
  border:1px solid rgba(77,163,255,.42);
  transition:transform .26s cubic-bezier(.4,0,.2,1);
  pointer-events:none;
}
.idioma[data-idioma="en"] .idioma__pista{transform:translateX(100%)}

.idioma__op{
  position:relative; z-index:1;
  min-width:31px; text-align:center;
  padding:5px 7px;
  font-size:11.5px; font-weight:600;
  letter-spacing:.09em; text-transform:uppercase;
  color:var(--tx-dim);
  transition:color .2s ease;
}
.idioma[data-idioma="es"] .idioma__op:nth-of-type(2),
.idioma[data-idioma="en"] .idioma__op:nth-of-type(3){color:var(--tx)}

@media (prefers-reduced-motion: reduce){
  .idioma__pista{transition:none}
}
.icono{
  color:var(--tx-mid);text-decoration:none;font-size:19px;line-height:1;
  padding:6px 8px;border-radius:8px;transition:color .18s ease, background .18s ease;
}
.icono:hover{color:var(--tx);background:rgba(255,255,255,.07)}

.btn{
  display:inline-block;background:var(--acc);color:#04121f;text-decoration:none;
  font-weight:600;font-size:15px;padding:10px 18px;
  border-radius:8px;border:0;cursor:pointer;
}
.btn:hover{filter:brightness(1.08)}
/* solo el boton de la barra: los del hero y los casos siguen igual */
body > header .btn{
  text-transform:uppercase;letter-spacing:.08em;
  font-size:12.5px;font-weight:700;padding:10px 16px;
}
.btn.sec{background:transparent;color:var(--tx);border:1px solid var(--line)}
.btn.sec:hover{border-color:var(--acc)}

@media(max-width:860px){
  .hnav{display:none}
  .barra{grid-template-columns:1fr auto}
  .idioma,.icono{display:none}
}

/* ---------- hero (H1,H2) ----------
   Ocupa EXACTAMENTE una pantalla, en cualquier monitor:
   - min-height 100svh  -> alto real del viewport (svh evita el salto
     que provocan las barras del navegador en movil)
   - el contenido se centra en el espacio libre
   - la tira queda anclada al borde inferior de esa pantalla
   Asi el carrusel se ve al fondo tanto en la laptop como en el monitor. */
.hero{
  min-height:100vh;            /* respaldo para navegadores sin svh */
  min-height:100svh;
  display:flex; flex-direction:column;
  /* el aire de arriba escala con la altura: deja pasar la isla flotante */
  padding:clamp(124px, 16vh, 210px) 0 0;
  position:relative; isolation:isolate; overflow:hidden;
}

/* ---- imagen de fondo del hero ----
   Ahora la imagen ES el titular, asi que se encuadra centrada y
   completa. El velo baja al minimo: solo lo necesario para que los
   botones se lean y para fundir el borde inferior con la tira.     */
.hero::before{
  content:'';position:absolute;inset:0;z-index:-2;
  background-image:url('img/hero.webp');
  background-size:cover;
  background-position:center center;
  background-repeat:no-repeat;
  /* acerca el encuadre. Un solo numero para ajustarlo: --zoom */
  transform:scale(var(--zoom));
  transform-origin:center center;
}
/* Velo: oscurece de izquierda a derecha para que el texto se lea
   sobre la foto, y funde el borde inferior con el fondo del sitio. */
.hero::after{
  content:'';position:absolute;inset:0;z-index:-1;
  background:
    linear-gradient(90deg,
      rgba(8,12,20,.55) 0%,      /* refuerza la zona de texto */
      rgba(8,12,20,.18) 34%,
      rgba(8,12,20,0)   52%),
    linear-gradient(180deg,
      rgba(11,15,20,.45) 0%,     /* para que la barra se lea */
      rgba(11,15,20,0)   20%,
      rgba(11,15,20,0)   68%,
      rgba(11,15,20,.80) 100%);  /* funde con la tira de abajo */
}
.hero .wrap{
  flex:1 1 auto;
  display:flex; flex-direction:column; justify-content:center;
}
/* La imagen deja limpia su mitad izquierda hasta el 45% del ancho:
   ahi va todo el texto. Mas alla empieza la foto del escritorio.  */
.hero-txt{max-width:min(46%, 720px)}
.hero h1{max-width:19ch}
.hero .sub{
  margin-top:clamp(12px, 2.2vh, 22px);
  max-width:58ch;font-size:var(--subtitle);line-height:var(--subtitle-lh);color:var(--tx-mid);
}
.hero .ctas{display:flex;gap:12px;margin-top:clamp(18px, 3.4vh, 36px);flex-wrap:wrap}

/* La imagen mide 2.11:1. Cuando la pantalla es mas "cuadrada" o
   vertical que eso, `cover` recortaria los lados y se comeria el
   texto impreso. Ahi se pasa a `contain`: la imagen entra entera,
   sin recorte, apoyada arriba, y los botones quedan debajo.        */
/* Cuando falta ancho, el bloque de texto no cabe en el 43%: crece,
   y el encuadre se corre a la IZQUIERDA para conservar debajo la
   zona oscura de la imagen. El velo compensa lo que reste.        */
/* Entre 1180 y 1600 el ancho ya no sobra: el zoom se quita (achica la
   zona oscura) y el bloque de texto se angosta para no invadir la foto. */
@media(max-width:1600px){
  :root{--zoom:1}
  .hero-txt{max-width:min(41%, 560px)}
  .hero::after{
    background:
      linear-gradient(90deg, rgba(8,12,20,.62) 0%, rgba(8,12,20,.24) 40%, rgba(8,12,20,0) 56%),
      linear-gradient(180deg, rgba(11,15,20,.45) 0%, rgba(11,15,20,0) 20%,
                              rgba(11,15,20,0) 68%, rgba(11,15,20,.80) 100%);
  }
}
@media(max-width:1180px){
  .hero-txt{max-width:min(62%, 640px)}
  .hero::before{background-position:22% center}
  .hero::after{
    background:
      linear-gradient(90deg, rgba(8,12,20,.72) 0%, rgba(8,12,20,.34) 46%, rgba(8,12,20,0) 66%),
      linear-gradient(180deg, rgba(11,15,20,.45) 0%, rgba(11,15,20,0) 20%,
                              rgba(11,15,20,0) 68%, rgba(11,15,20,.80) 100%);
  }
}
/* Pantallas altas o verticales: el texto ocupa todo el ancho y el
   velo se vuelve un fundido vertical, con la foto de telon.       */
@media(max-aspect-ratio:5/4){
  .hero-txt{max-width:none}
  .hero::before{background-position:38% center}
  .hero::after{
    background:linear-gradient(180deg,
      rgba(8,12,20,.62) 0%, rgba(8,12,20,.70) 45%,
      rgba(8,12,20,.86) 76%, var(--bg) 100%);
  }
}
/* La tira queda como banda solida sobre la foto: mismo recurso que
   usa histrips con su franja de avales encima de la imagen. */
.tira{position:relative;z-index:1}

/* ---------- titular del hero: composicion del banner ----------
   Proporciones medidas sobre la referencia (1822x863):
     "TU PROCESO DIGITALIZADO"  alto de caja ~38px  -> .25em
     "TE LLEVA"                              ~50px  -> .33em
     "MAS"                                  ~150px  -> 1em  (base)
     "LEJOS"                                 ~52px  -> .35em
   Todo se deriva de --tit, asi la composicion se mantiene identica
   en cualquier pantalla.                                          */
.titular{
  --tit: clamp(58px, calc(1.4vw + 20vh), 230px);
  font-family:'Anton', 'Inter', sans-serif;
  font-size:var(--tit);
  font-weight:400;              /* Anton solo tiene un peso, ya es pesada */
  line-height:.93;              /* pegadas, con un respiro minimo */
  text-transform:uppercase;
  letter-spacing:.005em;
  color:#fff;                   /* blanco puro: el titular manda */
  margin:0;
}
.titular span{display:block}
.t1{font-size:.25em;letter-spacing:.012em}
.t2{font-size:.30em;color:var(--acc);letter-spacing:.008em;margin-top:.14em}
/* MAS crece a 1.25em. No es solo tamaño: al ensancharse la M, la A
   con tilde se desplaza a la derecha y su acento cae DESPUES de donde
   termina "TE LLEVA". Por eso las lineas pueden ir pegadas sin que
   el acento se monte encima. Es como esta resuelto en la referencia. */
.t3{font-size:1.25em;letter-spacing:-.008em;margin-top:.05em}
/* LEJOS se apoya en la linea base de MAS, como en la referencia */
.t3 em{
  font-style:normal;font-size:.35em;color:var(--acc);
  letter-spacing:.01em;margin-left:.12em;
}

/* La palabra inglesa es más larga; mantiene la jerarquía sin recortarse,
   incluso mientras se carga Anton o cuando se usa la fuente de respaldo. */
html[lang="en"] .titular .t1{font-size:.21em}
html[lang="en"] .titular .t3{font-size:.63em}
html[lang="en"] .titular .t3 em{display:block;font-size:.5em;margin:.12em 0 0}

/* regla azul corta, entre el titular y la bajada */
.regla{
  display:block;width:clamp(38px,4.4vw,72px);height:3px;
  background:var(--acc);border-radius:2px;
  margin:clamp(14px,2.4vh,26px) 0 clamp(10px,1.6vh,18px);
}

/* bajada, con las palabras destacadas en azul */
.hero-txt .sub{
  margin-top:0;max-width:none;
  font-size:clamp(14px, calc(12px + .55vh), 19px);
  line-height:1.5;color:var(--tx-mid);
}
.hero-txt .sub strong{
  display:inline-block;margin-bottom:.25em;
  color:var(--tx);font-weight:700;
  font-size:1.06em;
}
.hero-txt .sub b{color:var(--acc);font-weight:700}

/* ---------- pantallas de poca altura (laptops) ----------
   Estos son EXACTAMENTE los valores que ya funcionaban bien en la
   laptop; la unica diferencia es que ahora viven dentro del media
   query, asi el monitor grande conserva su escala original.       */
@media(max-height:780px){
  .titular{--tit: clamp(52px, calc(1.2vw + 18vh), 224px)}
  .hero-txt .sub{font-size:clamp(13px, calc(11.2px + .5vh), 18px);line-height:1.48}
  .regla{margin:clamp(11px,2vh,24px) 0 clamp(8px,1.4vh,16px)}
  .hero .ctas{gap:10px;margin-top:clamp(14px, 2.8vh, 34px)}
  .hero .btn{
    font-size:clamp(13px, calc(11.4px + .28vh), 15px);
    padding:clamp(8px,1.15vh,11px) clamp(14px,1.5vw,20px);
  }
}

/* ---------- tira de lenguajes (marquesina) ----------
   Mismo patron que la tira de avales de histrips: ficha compacta
   (marca circular + nombre + rol), desplazamiento continuo, a sangre.
   Se sale del --aire a proposito: cruza toda la pantalla.          */
.tira{
  position:relative;
  margin-top:clamp(16px, 3.6vh, 52px);
  padding:clamp(12px, 1.9vh, 20px) 0;
  border-top:1px solid var(--line);
  border-bottom:1px solid var(--line);
  background:var(--bg-alt);
  overflow:hidden;
  /* difumina los extremos para que entre y salga sin cortar seco */
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 5%,#000 95%,transparent 100%);
  mask-image:linear-gradient(90deg,transparent 0,#000 5%,#000 95%,transparent 100%);
}
.tira-pista{
  display:flex;align-items:center;gap:0;
  width:max-content;
  animation:desliza 140s linear infinite;
}
.tira:hover .tira-pista{animation-play-state:paused}
@keyframes desliza{
  from{transform:translateX(0)}
  to{transform:translateX(-50%)}   /* la pista esta duplicada: -50% = un ciclo */
}
@media(prefers-reduced-motion:reduce){
  .tira-pista{animation:none}
  .tira{overflow-x:auto}
}

.lang{
  display:flex;flex-direction:row;align-items:center;   /* icono a la izquierda */
  gap:12px;
  /* Ancho FIJO para todas, calculado sobre la ficha mas larga
     ("Sistema · Linux en Windows"): 30 icono + 12 gap + 176 texto
     + 44 relleno = 262. Kotlin ocupa lo mismo que WSL.          */
  width:268px;
  padding:0 22px;
  border-right:1px solid var(--line);
  white-space:nowrap;
}
/* Logos originales a color. Cuatro de ellos (.NET, Gradle, NestJS,
   Express) son casi negros y desaparecerian sobre el fondo oscuro,
   asi que el circulo va en claro: ademas de resolverlo, es el mismo
   recurso de la franja de avales de la referencia.               */
.lang-ico{
  width:30px;height:30px;flex:0 0 auto;
  /* Sin contenedor: el SVG entra como MASCARA y se pinta con un color
     de la paleta. Asi los 21 pesan igual y ninguno trae su propio
     color a competir con la identidad del sitio.                   */
  background:var(--tx-mid);
  -webkit-mask-image:var(--i);      mask-image:var(--i);
  -webkit-mask-repeat:no-repeat;    mask-repeat:no-repeat;
  -webkit-mask-position:center;     mask-position:center;
  -webkit-mask-size:contain;        mask-size:contain;
  transition:background .2s ease;
}
.lang:hover .lang-ico{background:var(--acc)}

.lang b{display:block;font-size:var(--body-ui);font-weight:600;line-height:1.3}
.lang span{display:block;font-size:var(--caption);color:var(--acc);line-height:1.4;margin-top:1px}

/* ---------- dos caminos ---------- */
.caminos{display:grid;grid-template-columns:repeat(auto-fit,minmax(340px,1fr));gap:16px}
/* Ficha compacta, mismo lenguaje que la tira de lenguajes:
   marca circular + titulo en negrita + linea de rol en acento.
   Dos lineas en vez de cuatro bloques: la altura baja de ~200px a ~78px. */
.camino{
  background:var(--bg-card);border:1px solid var(--line);border-radius:12px;
  padding:16px 18px;text-decoration:none;color:inherit;
  display:flex;align-items:center;gap:14px;
  transition:border-color .2s ease, background .2s ease;
}
.camino:hover{border-color:var(--acc);background:#1e2733}
.camino .marca{
  width:42px;height:42px;flex:0 0 42px;border-radius:50%;
  display:grid;place-items:center;font-size:18px;font-weight:600;
  background:var(--bg);border:1px solid var(--line);color:var(--acc);
}
.camino .txt{min-width:0;flex:1}
.camino b{display:block;font-size:var(--body-read);font-weight:600;line-height:1.3;color:var(--tx)}
.camino .rol{
  display:block;margin-top:3px;font-size:var(--caption);line-height:1.45;
  color:var(--tx-dim);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.camino .rol em{color:var(--acc);font-style:normal;font-weight:500}
.camino .flecha{
  color:var(--tx-dim);font-size:20px;line-height:1;flex:0 0 auto;
  transition:transform .2s ease, color .2s ease;
}
.camino:hover .flecha{color:var(--acc);transform:translateX(3px)}

/* ---------- casos (E1,E2,E3,B1) ---------- */
.caso{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(300px,420px);gap:clamp(24px,3vw,64px);
  padding:calc(var(--u)*1.5) 0;border-top:1px solid var(--line);align-items:start;
}
.caso:first-of-type{border-top:0}
.caso h3{margin:10px 0 12px;font-size:1.5rem;line-height:1.3}
.caso .cuerpo p{font-size:var(--body-read)}
.caja{background:var(--bg-card);border:1px solid var(--line);border-radius:12px;padding:22px}
.caja dl{display:grid;grid-template-columns:auto 1fr;gap:10px 16px;margin:14px 0 18px}
.caja dt{font-size:var(--caption);color:var(--tx-dim);white-space:nowrap}
.caja dd{font-size:var(--caption);color:var(--tx)}
.pill{
  display:inline-block;font-size:11px;font-weight:600;letter-spacing:.07em;text-transform:uppercase;
  padding:3px 9px;border-radius:999px;border:1px solid var(--line);color:var(--tx-mid);
}
.pill.prod{color:var(--ok);border-color:rgba(63,185,132,.4);background:rgba(63,185,132,.08)}
.caja .btn{width:100%;text-align:center;margin-top:6px}
.caja .btn.sec{margin-top:8px}

/* ---------- comparativa (B6) ---------- */
table{width:100%;border-collapse:collapse;margin-top:var(--u)}
th,td{text-align:left;padding:14px 16px;border-bottom:1px solid var(--line);font-size:var(--body-ui)}
thead th{font-size:var(--caption);color:var(--tx-dim);font-weight:600;text-transform:uppercase;letter-spacing:.06em}
tbody td:first-child{color:var(--tx-mid)}
td.si{color:var(--ok)}
td.no{color:#e07a7a}

/* ---------- como trabajo (F1,F2) ---------- */
.num{font-size:var(--label);font-weight:700;color:var(--acc)}

/* ---------- sectores (E4) ---------- */
.sectores{display:flex;flex-wrap:wrap;gap:10px}
.sector{border:1px solid var(--line);border-radius:999px;padding:10px 18px;font-size:var(--body-ui);color:var(--tx-mid)}
.sector b{color:var(--tx);font-weight:600}

/* ---------- laboratorio: acordeon (B3) ---------- */
details{border:1px solid var(--line);border-radius:10px;margin-bottom:10px;background:var(--bg-card)}
summary{
  cursor:pointer;padding:18px 22px;display:flex;align-items:center;gap:14px;
  font-size:var(--body-read);font-weight:600;list-style:none;
}
summary::-webkit-details-marker{display:none}
summary::after{content:'+';margin-left:auto;color:var(--tx-dim);font-weight:400;font-size:20px}
details[open] summary::after{content:'–'}
summary .cnt{font-size:var(--caption);color:var(--tx-dim);font-weight:400}
.grid-apps{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:12px;padding:0 22px 22px}
.app{border:1px solid var(--line);border-radius:8px;padding:16px;background:var(--bg)}
.app b{display:block;font-size:var(--body-ui);margin-bottom:6px}
.app span{display:block;font-size:var(--caption);color:var(--tx-dim);line-height:1.5}
.app .tags{margin-top:10px;display:flex;gap:6px;flex-wrap:wrap}

/* ---------- tableros (G1,G2) ---------- */
.tablero{border:1px solid var(--line);border-radius:12px;overflow:hidden;background:var(--bg-card)}
.tablero .visual{
  aspect-ratio:16/7;background:
    repeating-linear-gradient(90deg,transparent 0 38px,rgba(255,255,255,.03) 38px 39px),
    repeating-linear-gradient(0deg,transparent 0 38px,rgba(255,255,255,.03) 38px 39px),
    var(--bg);
  display:flex;align-items:center;justify-content:center;color:var(--tx-dim);font-size:var(--caption);
  border-bottom:1px solid var(--line);
}
.tablero .txt{padding:24px}
.tablero .txt p{max-width:var(--lectura)}

/* ---------- servicios (J1,J2,J5) ---------- */
.servicios{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:16px}
.serv{background:var(--bg-card);border:1px solid var(--line);border-radius:12px;padding:24px;display:flex;flex-direction:column}
.serv h3{font-size:1.125rem;margin:10px 0 10px}
.serv .para{font-size:var(--caption);color:var(--acc);font-weight:500}
.serv ul{list-style:none;margin:14px 0 0}
.serv li{font-size:var(--body-ui);color:var(--tx-mid);padding:7px 0 7px 20px;position:relative;line-height:1.5}
.serv li::before{content:'—';position:absolute;left:0;color:var(--tx-dim)}
.serv .precio{margin-top:auto;padding-top:18px;font-size:var(--caption);color:var(--tx-dim)}

/* ---------- trayectoria ---------- */
.tl{border-left:1px solid var(--line);padding-left:28px;margin-left:6px}
.item{position:relative;padding-bottom:calc(var(--u))}
.item::before{content:'';position:absolute;left:-33px;top:7px;width:9px;height:9px;border-radius:50%;background:var(--acc)}
.item .fecha{font-size:var(--caption);color:var(--tx-dim)}
.item b{display:block;font-size:var(--body-read);margin:4px 0 4px}
.item span{font-size:var(--body-ui);color:var(--tx-mid)}

/* ---------- articulos (A5,A6) ---------- */
.art{display:grid;grid-template-columns:clamp(96px,9vw,150px) 1fr;gap:clamp(16px,2vw,28px);padding:22px 0;border-top:1px solid var(--line);align-items:start}
.art .mini{aspect-ratio:1;background:var(--bg-card);border:1px solid var(--line);border-radius:8px}
.art b{display:block;font-size:var(--title-md);font-weight:600;margin:6px 0 6px;line-height:1.35}
.art p{font-size:var(--body-ui);margin:0}
.art .meta{font-size:var(--caption);color:var(--tx-dim)}

/* ---------- indice compacto (I5) ---------- */
.indice{columns:auto 220px;column-gap:32px}
.indice a{display:block;color:var(--tx-mid);text-decoration:none;font-size:var(--body-ui);padding:5px 0}
.indice a:hover{color:var(--acc)}

/* ---------- cierre ---------- */
.cierre{text-align:center;padding:calc(var(--u)*5) 0}
.cierre h2{max-width:22ch;margin:0 auto}
.cierre p{margin:16px auto 0;max-width:52ch}
.cierre .ctas{display:flex;gap:12px;justify-content:center;margin-top:32px;flex-wrap:wrap}
footer{border-top:1px solid var(--line);padding:calc(var(--u)*1.5) 0;color:var(--tx-dim);font-size:var(--caption)}
footer .wrap{display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap}

/* ---------- responsive ---------- */
@media(max-width:900px){
  body > header .wrap{height:58px}
  body > header.scrolled .wrap{height:52px}
  .caso{grid-template-columns:1fr}
  .hnav a{display:none}
  .art{grid-template-columns:72px 1fr}
}


/* ============================================================
   FORMULARIO DE CONTACTO
   Vivia en el <style> de contacto.html. Se mudo aca porque el
   mismo bloque se usa ahora al final de la pagina de inicio.
   Un solo lugar para las dos.
   ============================================================ */
/* ============================================================
   PAGINA DE CONTACTO
   Estructura de la referencia: panel a la izquierda con el
   mensaje y la persona, formulario a la derecha. Todo con la
   escala, la paleta y el ritmo del resto del sitio.
   ============================================================ */
.contacto{
  min-height:100vh; min-height:100svh;
  padding-top:clamp(104px, 13vh, 150px);
  display:grid;
  /* la columna del formulario manda: nunca baja de 480px */
  grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);
}
.panel{
  /* Mas adentro: el contenido no se pega al filo de la pantalla.
     El respiro exterior crece con el ancho; el interior, hacia la
     linea divisoria, se mantiene mas contenido.                */
  padding:0 clamp(28px,4.2vw,80px) calc(var(--u)*2) clamp(28px,6.5vw,128px);
  display:flex;flex-direction:column;
  justify-content:center;          /* centrado vertical */
}
.formulario{
  /* La columna ya no lleva color propio: el formulario vive en una
     tarjeta. Asi no queda un rectangulo a sangre que el header
     recorta por arriba.                                         */
  padding:0 clamp(24px,5.5vw,110px) calc(var(--u)*2) clamp(20px,3vw,56px);
  display:flex;flex-direction:column;
}
.tarjeta{
  margin-block:auto;      /* centra sin cortar cuando no cabe */
  background:var(--bg-alt);
  border:1px solid var(--line);
  border-radius:16px;
  padding:clamp(24px,2.6vw,44px);
  box-shadow:
    0 28px 64px rgba(0,0,0,.38),
    inset 0 1px 0 rgba(255,255,255,.045);
}

/* ---------- panel izquierdo ---------- */
.panel h1{
  font-size:clamp(1.9rem, calc(0.85rem + 1.5vw + 1.8vh), 3.2rem);
  line-height:1.1;font-weight:700;letter-spacing:-.025em;color:#fff;
  max-width:15ch;margin-top:12px;
}
.panel .bajada{
  margin-top:clamp(16px,2.8vh,28px);max-width:42ch;
  font-size:var(--body-read);line-height:1.6;color:var(--tx-mid);
}
.panel .bajada a{color:var(--tx);text-decoration:none;border-bottom:1px solid var(--acc);padding-bottom:1px}
.panel .bajada a:hover{color:var(--acc)}

/* persona */
.persona{
  display:flex;align-items:center;gap:15px;
  margin-top:clamp(28px,5vh,56px);
  padding-top:clamp(22px,4vh,40px);
  border-top:1px solid var(--line);   /* separa sin encerrar */
  max-width:42ch;
}
.persona .foto{
  width:56px;height:56px;flex:0 0 56px;border-radius:10px;
  background:linear-gradient(180deg,#222c38,#1a222d);
  border:1px solid var(--line);
  display:grid;place-items:center;
  font-size:17px;font-weight:700;letter-spacing:.04em;color:var(--tx-mid);
}
.persona b{display:block;font-size:var(--body-read);font-weight:600;line-height:1.3}
.persona span{display:block;margin-top:2px;font-size:var(--caption);color:var(--tx-dim)}


/* ---------- formulario ---------- */
.formulario .enc-form{margin-bottom:calc(var(--u))}
.campos{display:grid;grid-template-columns:1fr 1fr;gap:clamp(14px,1.4vw,22px)}
.campo{display:flex;flex-direction:column;min-width:0}
.campo.ancho{grid-column:1 / -1}
.campo label{
  font-size:var(--caption);font-weight:600;color:var(--tx);
  margin-bottom:7px;
}
.campo label i{font-style:normal;color:var(--acc);margin-left:2px}
.campo input,.campo select,.campo textarea{
  font:inherit;font-size:var(--body-ui);color:var(--tx);
  background:var(--bg-card);
  border:1px solid var(--line);border-radius:8px;
  padding:12px 14px;width:100%;
  transition:border-color .18s ease, background .18s ease;
}
.campo textarea{min-height:clamp(110px,16vh,168px);resize:vertical;line-height:1.55}
.campo input::placeholder,.campo textarea::placeholder{color:var(--tx-dim)}
.campo input:focus,.campo select:focus,.campo textarea:focus{
  outline:none;border-color:var(--acc);background:#1f2834;
}
.campo select{appearance:none;cursor:pointer;
  background-image:linear-gradient(45deg,transparent 50%,var(--tx-dim) 50%),
                   linear-gradient(135deg,var(--tx-dim) 50%,transparent 50%);
  background-position:calc(100% - 20px) 52%, calc(100% - 14px) 52%;
  background-size:6px 6px, 6px 6px;background-repeat:no-repeat;
}

/* casillas */
.casilla{display:flex;align-items:flex-start;gap:11px;margin-top:clamp(16px,2.4vh,24px)}
.casilla input{
  appearance:none;width:19px;height:19px;flex:0 0 19px;margin-top:1px;
  border:1px solid var(--line);border-radius:5px;background:var(--bg-card);
  cursor:pointer;transition:all .18s ease;position:relative;
}
.casilla input:checked{background:var(--acc);border-color:var(--acc)}
.casilla input:checked::after{
  content:'';position:absolute;left:6px;top:2px;width:5px;height:10px;
  border:solid #04121f;border-width:0 2px 2px 0;transform:rotate(45deg);
}
.casilla label{font-size:var(--caption);color:var(--tx-mid);line-height:1.5;cursor:pointer}

/* envio */
.envio{
  display:flex;align-items:center;gap:clamp(14px,1.6vw,22px);
  flex-wrap:wrap;margin-top:clamp(20px,3.2vh,34px);
}
.envio .btn{font-size:var(--body-ui);padding:13px 26px}
.privacidad{display:flex;align-items:center;gap:8px;font-size:var(--caption);color:var(--tx-dim)}
.privacidad svg{width:16px;height:16px;flex:0 0 16px;fill:var(--ok)}

.aviso-envio{
  margin-top:16px;font-size:var(--caption);color:var(--acc);
  display:none;
}
.aviso-envio.visible{display:block}

/* ---------- pantallas de poca altura ----------
   El formulario es alto por naturaleza. En una laptop desbordaba
   137px, asi que aca se comprime todo el conjunto.            */
@media(max-height:780px){
  /* SOLO el formulario. El panel de la izquierda conserva su escala.

     Aca NO se busca que todo entre sin scroll: forzarlo obligaba a
     apretar los espacios hasta que el conjunto se veia denso. Se
     reduce lo que es puro tamaño (tipografia y alto de campos) y se
     CONSERVA el aire entre bloques, que es lo que sostiene la
     estetica. Si sobra, la pagina se desplaza y no pasa nada.    */
  .contacto{padding-top:clamp(126px,17vh,168px);align-items:start}
  /* No se centra lo que no cabe: se apoya arriba y la pagina se
     desplaza. Centrar algo mas alto que la pantalla deja la parte
     de arriba a medio ver y se siente desordenado.              */
  .tarjeta{margin-block:0}
  .panel{justify-content:flex-start;padding-top:10px}
  .tarjeta{padding:26px 26px;border-radius:14px}

  .campos{gap:17px}
  .campo label{margin-bottom:7px;font-size:12.5px}
  .campo input,.campo select,.campo textarea{
    padding:10px 13px;font-size:14px;
  }
  .campo textarea{min-height:96px;line-height:1.5}

  .casilla{margin-top:16px;gap:11px}
  .casilla label{font-size:12.5px;line-height:1.5}
  .casilla input{width:18px;height:18px;flex:0 0 18px}
  .casilla input:checked::after{left:5px;top:2px;width:4px;height:9px}

  .envio{margin-top:22px;gap:16px}
  .envio .btn{padding:11px 24px;font-size:14px}
  .privacidad{font-size:12.5px}
}

/* ---------- responsive ---------- */
@media(max-width:1000px){
  .contacto{grid-template-columns:1fr;padding-top:clamp(96px,12vh,132px)}
  .panel{padding:calc(var(--u)) clamp(24px,5vw,64px) calc(var(--u)*2)}
  .formulario{
    padding:calc(var(--u)) clamp(24px,5vw,64px) calc(var(--u)*3);
  }
  .panel h1{max-width:18ch}
}
@media(max-width:620px){
  .tarjeta{padding:22px 18px;border-radius:14px}
  .campos{grid-template-columns:1fr}
  .envio{align-items:stretch;flex-direction:column}
  .envio .btn{text-align:center}
}

/* ---------- version incrustada al final del inicio ----------
   En su propia pagina el bloque ocupa la pantalla completa y deja
   sitio para la isla fija. Al final del inicio no hace falta ni lo
   uno ni lo otro: ya viene precedido de contenido.               */
.contacto.incrustada{
  min-height:auto;
  padding-top:0;
  padding-block:calc(var(--u)*2.6);
  border-top:1px solid var(--line);
}
.contacto.incrustada .panel{justify-content:center}

/* En pantalla baja, la version de pagina completa se apoya arriba y
   reduce el aire. La incrustada NO puede hacer eso: no lleva header
   encima sino una linea divisoria, y sin respiro el texto y la
   tarjeta quedan pegados a ella.                                  */
@media(max-height:780px){
  .contacto.incrustada{
    padding-top:calc(var(--u)*2);
    padding-bottom:calc(var(--u)*2);
    align-items:center;
  }
  /* estas dos vienen de la version de pagina completa, donde el
     contenido se apoya arriba. Aca se devuelven a su sitio. */
  .contacto.incrustada .panel{justify-content:center;padding-top:0}
  .contacto.incrustada .tarjeta{margin-block:auto}
}



/* ============================================================
   PIE — una sola linea
   Sin sello ni monograma: identidad a la izquierda, enlaces a la
   derecha, todo en una fila. Va deliberadamente apagado (opacidad
   baja) para que cierre la pagina sin competir con el formulario
   que tiene justo encima.
   ============================================================ */
footer{
  border-top:1px solid var(--line);
  padding:calc(var(--u)*0.95) 0;
  font-size:var(--caption);
  color:var(--tx-dim);
  opacity:.62;                       /* el pie no pide atencion */
  transition:opacity .25s ease;
}
footer:hover{opacity:1}              /* al acercarse, se recupera */

.pie{
  display:flex;align-items:center;justify-content:space-between;
  gap:16px;flex-wrap:wrap;
}
.pie-id{
  margin:0;max-width:none;
  font-size:var(--caption);line-height:1.4;color:var(--tx-dim);
}
.pie-id b{color:var(--tx-mid);font-weight:600}

.pie-enl{display:flex;align-items:center;gap:clamp(16px,1.8vw,28px);flex-wrap:wrap}
.pie-enl a{
  display:inline-flex;align-items:center;gap:7px;
  color:var(--tx-dim);text-decoration:none;
  transition:color .18s ease;
}
.pie-enl a:hover{color:var(--acc)}

/* mismo tratamiento monocromo que los iconos de la tira: el SVG se
   usa como mascara, asi el icono toma el color del texto y cambia
   con el hover sin necesidad de dos archivos. */
.pie-ico{
  width:15px;height:15px;flex:0 0 15px;
  background:currentColor;
  -webkit-mask:var(--i) center/contain no-repeat;
          mask:var(--i) center/contain no-repeat;
}
.pie-c{color:var(--tx-dim);opacity:.85}

@media(max-width:620px){
  .pie{flex-direction:column;align-items:flex-start;gap:10px}
}


/* ---------- foto de la tarjeta de persona ----------
   Antes era el monograma "PA" sobre un cuadrado redondeado. La
   imagen YA viene recortada en circulo y con fondo transparente,
   asi que el contenedor se desnuda por completo: sin fondo, sin
   borde y en circulo. Si no, el circulo queda flotando sobre un
   cuadrado y se ven las dos formas.                              */
.persona .foto{
  padding:0;
  background:none;
  border:0;
  border-radius:50%;
  overflow:hidden;
}
.persona .foto img{
  width:100%;height:100%;object-fit:cover;display:block;
  border-radius:50%;
}

.persona .foto picture{display:block;width:100%;height:100%}


/* ============================================================
   SECCION EN TONO MEDIO
   El sitio va sobre el fondo base. Para cortar el
   bloque no hace falta irse al blanco: basta subir un escalon de
   luminosidad. Un claro sobre un fondo tan oscuro se lee como un
   parche; un tono medio se lee como profundidad.

   El texto NO se invierte: sigue siendo claro, como en el resto
   del sitio. Solo cambian los fondos y las lineas.

   Escala, por si hay que moverlo:
   El valor es el MISMO que --bg-alt, que es el fondo de la tarjeta
   que encierra el formulario. Reusar un tono que ya existe en el
   sitio es lo que hace que la seccion se lea como parte del mismo
   sistema y no como un color inventado para ella.

   Si hiciera falta separarla mas, la escala sigue asi:
     #171f2a  <- el actual: igual que la tarjeta del formulario
     #1e2733  un paso
     #283442  marcado
     #303e4e  fuerte
   ============================================================ */
.tono{
  --bg:      #171f2a;   /* = --bg-alt: el fondo de la tarjeta */
  --bg-alt:  #111821;
  --bg-card: #1f2834;   /* las fases suben un escalon sobre el fondo */
  --line:    #2b3644;

  background:var(--bg);
  border-top:1px solid var(--line);
  border-bottom:1px solid var(--line);
}

/* sin sombra: la separacion la da el escalon de tono y el borde */
.tono .fase,
.tono .pr{
  background:var(--bg-card);
  border-color:var(--line);
  box-shadow:none;
}


/* ============================================================
   FICHA TECNICA
   Mismo lenguaje que la tarjeta del formulario, que es el que
   mejor funciona en este sitio:
     - tarjeta de 16px sobre --bg-alt, con sombra profunda y una
       linea interior de luz arriba (el borde superior claro es lo
       que da la sensacion de material, no la sombra sola)
     - campos y piezas internas a 8px sobre --bg-card
     - el azul --acc como acento puntual, no como decoracion
   ============================================================ */
.ficha{
  min-height:100vh; min-height:100svh;
  /* la isla, mas un aire. En pantalla grande da los mismos ~140px de
     antes; en una chica ya no se come el respiro. */
  padding-top:calc(var(--isla) + clamp(28px, 3.2vh, 35px));
  padding-bottom:calc(var(--u)*4);
}
/* El encabezado necesita respirar: es lo primero que se lee al
   entrar y estaba apretado contra la isla y contra el bloque de
   Estudios. Se separa arriba, se agranda el titulo y se cierra con
   una linea que marca donde termina la introduccion.            */
.ficha-enc{
  max-width:var(--lectura);
  margin-bottom:calc(var(--u)*3.2);
  padding-bottom:calc(var(--u)*1.6);
  border-bottom:1px solid var(--line);
}
.ficha-enc .label{
  display:block;                    /* era inline: no separaba */
  margin-bottom:clamp(10px,1.4vh,16px);
  color:var(--acc);
}
.ficha-enc h1{
  margin:0;
  font-size:clamp(1.75rem, calc(0.9rem + 1.1vw + 1.5vh), 2.9rem);
  line-height:1.14;
  font-weight:700;
  letter-spacing:-.022em;
  color:var(--tx);
}
.ficha-enc p{
  margin-top:clamp(14px,2vh,22px);
  font-size:var(--body-read);
  color:var(--tx-mid);
  max-width:60ch;
}
/* Navegacion entre las cinco secciones.
   Va debajo del encabezado de cada pagina, porque ya no hay una ficha
   completa desde donde elegir: se salta de una seccion a otra directo.
   La actual se marca con aria-current, no con una clase: el atributo ya
   dice la verdad para quien navega con lector de pantalla y de paso
   sirve de selector. */
.ficha-nav{
  display:flex;flex-wrap:wrap;gap:4px;
  margin-top:calc(var(--u)*1.1);
  padding-bottom:calc(var(--u)*.5);
  border-bottom:1px solid var(--line);
}
.ficha-nav a{
  font-size:var(--caption);font-weight:600;
  color:var(--tx-dim);
  padding:8px 14px;border-radius:8px;
  transition:color .18s ease, background .18s ease;
}
.ficha-nav a:hover{color:var(--tx);background:var(--bg-alt)}
.ficha-nav a[aria-current="page"]{
  color:var(--acc);
  background:rgba(77,163,255,.1);
}

/* El conteo del bloque cuando la seccion va sola: antes vivia junto al
   <h2> del bloque, que en esa ruta ya no se dibuja. */
.ficha-enc-n{
  display:block;
  margin-top:clamp(8px,1vh,12px);
  font-size:var(--caption);
  color:var(--tx-dim);
  font-variant-numeric:tabular-nums;
}

/* La separacion entre bloques era de 2.6u, calibrada para cuando la
   ficha apilaba los cinco seguidos y cada uno necesitaba leerse como
   una parada distinta. Hoy solo Formacion lleva dos bloques -Estudios
   y Certificaciones-, y ahi ese hueco se sumaba al relleno inferior de
   la ultima etapa: quedaban casi cien pixeles de nada. */
.ficha-bloque{padding:0;margin-top:calc(var(--u)*1.5)}
.bloque-cab{
  display:flex;align-items:baseline;justify-content:space-between;
  gap:16px;flex-wrap:wrap;margin-bottom:calc(var(--u)*1.1);
}
.bloque-cab h2{font-size:var(--title-md);font-weight:600;color:var(--tx)}
.bloque-n{
  font-size:var(--caption);color:var(--tx-dim);
  font-variant-numeric:tabular-nums;
}

/* ---------- estudios: tuberia ----------
   Cada programa es una etapa colgada de un riel vertical: nodo con su
   numero, periodo, y a la derecha lo que es.

   El riel se dibuja en .tuberia y no en cada etapa, para que arranque en
   el centro del primer nodo y termine en el del ultimo: si fuera un
   borde de cada fila, sobresaldria por arriba y por abajo.

   Sin punta de flecha: las etapas no van en orden cronologico -Hong Kong
   primero, por estar completado, como manda master/perfil.md-, asi que
   marcar una direccion sugeriria una secuencia que no es. */
.tuberia{
  list-style:none;
  position:relative;
  /* alto del nodo y de donde queda su centro: el riel se cuelga de ahi */
  --nodo:46px;
  --centro:calc(var(--u)*.9 + var(--nodo) / 2);
}
.tuberia::before{
  content:"";
  position:absolute;
  left:calc(var(--nodo) / 2 - 1px);
  top:var(--centro);
  bottom:var(--centro);
  width:2px;
  background:var(--line);
}
.etapa{
  position:relative;
  display:grid;
  grid-template-columns:var(--nodo) 7.5rem 1fr;
  gap:clamp(14px,2vw,30px);
  align-items:start;
  padding:calc(var(--u)*.9) 0;
}
.etapa-nodo{
  position:relative;z-index:1;     /* por encima del riel */
  width:var(--nodo);height:var(--nodo);
  display:grid;place-items:center;
  border-radius:50%;
  background:var(--bg-card);
  border:2px solid var(--line);
  font-size:12px;font-weight:700;
  color:var(--tx-dim);
  font-variant-numeric:tabular-nums;
  transition:border-color .2s ease, color .2s ease;
}
.etapa--ok .etapa-nodo{border-color:var(--ok);color:var(--ok)}
.etapa:hover .etapa-nodo{border-color:var(--acc);color:var(--acc)}

.etapa-per{
  display:flex;align-items:center;gap:10px;
  padding-top:calc(var(--nodo) / 2 - .6em);   /* a la altura del nodo */
  font-size:var(--caption);
  color:var(--tx-dim);
  font-variant-numeric:tabular-nums;
  letter-spacing:.04em;
}
.etapa-per i{width:18px;height:1px;background:currentColor;opacity:.55;display:block}

.etapa-cuerpo{padding-top:calc(var(--nodo) / 2 - .72em)}
.etapa h3{
  font-size:var(--body-read);
  font-weight:600;line-height:1.3;
  letter-spacing:-.01em;color:var(--tx);
}
.etapa p{margin-top:5px;font-size:var(--caption);color:var(--tx-mid);max-width:56ch}
.etapa-estado{
  display:inline-flex;align-items:center;gap:8px;
  margin-top:12px;
  font-size:var(--caption);font-weight:500;
  color:var(--tx-dim);
}
.etapa-estado::before{
  content:"";flex:none;
  width:6px;height:6px;border-radius:50%;
  background:currentColor;
}
/* el verde solo para lo que si esta completado: "8 semestres cursados"
   no es un estado de exito y pintarlo de verde afirmaba algo falso */
.etapa--ok .etapa-estado{color:var(--ok)}

@media (max-width:760px){
  .etapa{grid-template-columns:var(--nodo) 1fr;gap:14px}
  .etapa-nodo{grid-row:1 / span 2}
  .etapa-per{grid-column:2;padding-top:calc(var(--nodo) / 2 - .6em)}
  .etapa-cuerpo{grid-column:2;padding-top:6px}
}

/* ---------- filtros ---------- */
.chips{display:flex;flex-wrap:wrap;gap:9px;margin-bottom:calc(var(--u)*1.2)}
.chip{
  display:inline-flex;align-items:center;gap:8px;
  font:inherit;font-size:var(--caption);font-weight:600;
  color:var(--tx-mid);
  background:var(--bg-card);
  border:1px solid var(--line);
  border-radius:8px;
  padding:9px 15px;cursor:pointer;
  transition:color .18s ease, background .18s ease, border-color .18s ease;
}
.chip span{
  font-size:11px;font-weight:700;color:var(--tx-dim);
  font-variant-numeric:tabular-nums;
}
.chip:hover{color:var(--tx);border-color:#3f5064}
.chip.activo{
  color:#04121f;
  background:var(--acc);
  border-color:var(--acc);
}
.chip.activo span{color:rgba(4,18,31,.62)}

/* ---------- certificaciones ---------- */
.certs{
  display:grid;gap:16px;
  grid-template-columns:repeat(auto-fill,minmax(276px,1fr));
  /* Todas las filas del mismo alto, no solo las tarjetas de una misma
     fila. Sin esto una fila con un titulo de tres lineas queda mas alta
     que la de al lado y la reticula se ve dispareja. */
  grid-auto-rows:1fr;
}
.cert[hidden]{display:none}
.cert{display:flex}
.cert-btn{
  width:100%;text-align:left;cursor:pointer;
  font:inherit;color:inherit;
  background:var(--bg-alt);
  border:1px solid var(--line);
  border-radius:16px;
  padding:0;overflow:hidden;
  display:flex;flex-direction:column;
  box-shadow:
    0 18px 44px rgba(0,0,0,.26),
    inset 0 1px 0 rgba(255,255,255,.045);
  transition:border-color .2s ease, transform .2s ease, box-shadow .2s ease;
}
.cert-btn:hover,
.cert-btn:focus-visible{
  border-color:var(--acc);
  transform:translateY(-3px);
  box-shadow:
    0 26px 56px rgba(0,0,0,.34),
    inset 0 1px 0 rgba(255,255,255,.06);
  outline:none;
}

.cert-vista{
  display:block;position:relative;
  aspect-ratio:16/10;
  /* flex:none para que la caja conserve su proporcion aunque la
     tarjeta se estire para igualar el alto de su fila */
  flex:none;
  background:var(--bg-card);
  border-bottom:1px solid var(--line);
  overflow:hidden;
}
.cert-vista img{
  width:100%;height:100%;display:block;
  /* contain, no cover.
     Los diplomas no vienen todos de la misma forma: los de Udemy son
     1200x893 (1.34) y la caja es 16:10 (1.60), asi que con cover se les
     recortaba el 16% del alto -el borde y el pie del diploma, que es
     justo lo que se quiere ver-. Con contain entra completo y las cajas
     siguen midiendo todas igual; lo que cambia es el aire a los lados,
     y el fondo lo absorbe. */
  object-fit:contain;
  padding:10px;
  /* el certificado es blanco puro: atenuado no quema la reticula,
     y recupera color al pasar el mouse */
  opacity:.84;
  transition:opacity .22s ease, transform .32s ease;
}
.cert-btn:hover .cert-vista img{opacity:1;transform:scale(1.03)}
.cert-marca{
  position:absolute;inset:0;display:grid;place-items:center;
  font-size:var(--caption);font-weight:600;letter-spacing:.14em;
  text-transform:uppercase;color:var(--tx-dim);
}

/* El texto ocupa lo que sobra de la tarjeta, y el codigo se va hasta
   abajo. Asi los codigos quedan alineados entre tarjetas en vez de
   flotar a distinta altura segun cuanto ocupe el titulo. */
.cert-txt{
  display:flex;flex-direction:column;
  flex:1;
  padding:16px 18px 18px;
}
.cert-emisor{
  display:block;font-size:var(--caption);font-weight:600;
  color:var(--acc);margin-bottom:8px;
}
.cert-txt b{
  display:block;font-size:var(--body-ui);font-weight:600;
  color:var(--tx);line-height:1.4;
  /* dos lineas reservadas: un titulo corto no encoge su tarjeta.
     No se recorta el que ocupa tres -el nombre completo de la
     credencial importa mas que la simetria-; de igualar el alto se
     encarga grid-auto-rows. */
  min-height:2.8em;
}
.cert-id{
  display:block;margin-top:auto;padding-top:12px;
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:11px;color:var(--tx-dim);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}

/* ============================================================
   MODAL DE CERTIFICADO — misma tarjeta, mas grande
   ============================================================ */
.modal[hidden]{display:none}
.modal{position:fixed;inset:0;z-index:120;display:grid;place-items:center;padding:var(--aire)}
.modal-fondo{
  position:absolute;inset:0;
  background:rgba(6,9,13,.8);
  backdrop-filter:blur(4px);
  opacity:0;transition:opacity .2s ease;
}
.modal.abierto .modal-fondo{opacity:1}
.modal-caja{
  position:relative;
  width:min(900px,100%);max-height:min(88vh,920px);
  display:flex;flex-direction:column;
  background:var(--bg-alt);
  border:1px solid var(--line);
  border-radius:16px;
  box-shadow:
    0 40px 100px rgba(0,0,0,.55),
    inset 0 1px 0 rgba(255,255,255,.05);
  opacity:0;transform:translateY(12px) scale(.985);
  transition:opacity .22s ease, transform .28s cubic-bezier(.16,.84,.44,1);
  overflow:hidden;
}
.modal.abierto .modal-caja{opacity:1;transform:none}

.modal-cab{
  display:flex;align-items:flex-start;justify-content:space-between;gap:18px;
  padding:20px 22px;border-bottom:1px solid var(--line);
}
.modal-emisor{
  display:block;font-size:var(--caption);font-weight:600;
  color:var(--acc);margin-bottom:6px;
}
.modal-cab h3{font-size:var(--body-read);font-weight:600;color:var(--tx);line-height:1.35}
.modal-x{
  font:inherit;font-size:28px;line-height:1;
  background:none;border:0;cursor:pointer;color:var(--tx-dim);
  padding:0 4px;transition:color .16s ease;
}
.modal-x:hover{color:var(--tx)}

.modal-cuerpo{
  flex:1;min-height:0;overflow:auto;
  padding:22px;background:var(--bg);
  display:grid;place-items:center;
}
.modal-cuerpo img{
  max-width:100%;height:auto;display:block;
  border:1px solid var(--line);border-radius:8px;
}
.modal-aviso{text-align:center;color:var(--tx-mid);max-width:44ch}
.modal-aviso b{display:block;color:var(--tx);margin-bottom:8px}

.modal-pie{
  display:flex;align-items:center;justify-content:space-between;
  gap:16px;flex-wrap:wrap;
  padding:16px 22px;border-top:1px solid var(--line);
}
.modal-id{
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:11.5px;color:var(--tx-dim);
}

/* Al bloquear el scroll desaparece la barra de desplazamiento y la
   pagina se ensancha esos pocos pixeles: con un fondo opaco no se
   notaba, pero detras del cristal del visor el salto se ve. El hueco
   se reserva siempre, asi no hay nada que reacomodar. */
html{scrollbar-gutter:stable}
body.sin-scroll{overflow:hidden}

@media(max-width:620px){
  .certs{grid-template-columns:1fr}
}
@media(prefers-reduced-motion:reduce){
  .modal-fondo,.modal-caja,.cert-btn,.cert-vista img,.est{transition:none}
  .cert-btn:hover{transform:none}
}

/* visor de PDF dentro del modal */
.modal-cuerpo:has(.modal-pdf){display:block;padding:0}

/* Un README se estira; no se centra.
   .modal-cuerpo trae place-items:center, que sirve para la imagen de un
   certificado -una pieza suelta en medio de la caja-. Con un documento
   hace dano: justify-items:center encoge cada hijo a su contenido en
   vez de estirarlo, y si un hijo sale mas ancho que la caja, centrado
   se desborda por los DOS lados. Como solo se puede desplazar hacia la
   derecha, la mitad izquierda queda inalcanzable: eso era lo que se
   veia "corrido a la izquierda".

   Medido en el navegador sobre el README de Reserva CQRS:
     tal cual                 hijo de prueba   8px   desborda 248px
     forzando display:block   hijo de prueba   8px   desborda 248px
     place-items:stretch      hijo de prueba 946px   desborda   0px

   Por eso se corrige place-items y no display: cambiar display no hacia
   nada. Y se toca solo el contenedor del README: la imagen del
   certificado sigue centrada. */
.readme{place-items:stretch}

/* GitHub envuelve cada tabla en este elemento propio. El navegador no
   lo conoce, asi que por defecto lo trata como display:inline, y una
   tabla en bloque dentro de un padre en linea rompe el contenedor.
   Veinte de los veintitres README traen tablas asi. */
.readme markdown-accessiblity-table{
  display:block;
  max-width:100%;
  overflow-x:auto;
}

/* Nada dentro del README puede ser mas ancho que el README. Las lineas
   largas de consola -hay una de 164 caracteres- se desplazan dentro de
   su bloque, no empujan la pagina. */
.readme{max-width:100%;min-width:0;overflow-wrap:break-word}
.readme pre,
.readme table,
.readme img{max-width:100%}

/* El codigo suelto dentro de un parrafo puede ser un identificador
   larguisimo sin espacios: que parta donde sea antes que empujar la
   caja. El de dentro de <pre> NO parte: ahi se desplaza, que es como
   se lee el codigo. */
.readme :not(pre) > code{overflow-wrap:anywhere}
.readme pre{white-space:pre}
.readme pre code{overflow-wrap:normal;white-space:pre}
.modal-pdf{
  width:100%;
  height:min(70vh, 760px);
  border:0;display:block;background:var(--bg);
}
.modal-respaldo{
  padding:12px 22px 18px;font-size:var(--caption);
  text-align:center;max-width:none;
}
.modal-respaldo a{color:var(--acc)}

/* El primer bloque no lleva el margen grande de los demas -la linea del
   encabezado ya separo-, pero tampoco cero: esta regla se escribio
   cuando debajo del encabezado venia el contenido directo, y ahora en
   medio esta la barra de secciones. Con margin-top:0 el bloque quedaba
   pegado a esa barra. */
.ficha-bloque:first-of-type{margin-top:calc(var(--u)*1.5)}


/* ============================================================
   REPOSITORIOS
   Misma tarjeta que las certificaciones: 16px, sombra profunda y
   linea de luz arriba. No se trajo el diseno del portafolio
   anterior, solo la mecanica (tarjeta -> modal con README).
   ============================================================ */
/* La linea que explica el bloque -"Cada proyecto es publico y
   auditable..."- no tenia regla propia, asi que las tarjetas le
   quedaban pegadas debajo. La misma clase la usa el bloque de
   Tableros. */
.ficha-nota{
  font-size:var(--body-ui);
  color:var(--tx-mid);
  line-height:1.6;
  max-width:var(--lectura);
  margin-bottom:calc(var(--u)*1.4);
}

.repos{
  display:grid;gap:16px;
  grid-template-columns:repeat(auto-fill,minmax(320px,1fr));
}

/* La tarjeta que se eligio en el menu, en Codigo y en Laboratorio.
   Se detiene debajo de la isla al desplazarse, y parpadea tres veces
   con el azul del sitio: suficiente para encontrarla entre trece
   iguales, poco para molestar.

   El resplandor se pinta en el <article> que envuelve, pero la tarjeta
   que se ve es el boton de adentro, con esquinas de 16px. Sin este
   radio el halo salia cuadrado alrededor de una tarjeta redondeada. Es
   el mismo valor a proposito: si cambia uno, tiene que cambiar el otro. */
.repo,
.lab{
  scroll-margin-top:calc(var(--isla) + 28px);
  border-radius:16px;
}
.repo--resaltado,
.lab--resaltado{animation:repo-marca 2.4s ease both}
/* Los cuatro pasos declaran DOS sombras, siempre.
   Si un paso trae una y el siguiente dos, el navegador tiene que
   rellenar la que falta para interpolar, y la transicion sale a
   saltos. Con la misma cantidad en todos, solo cambian los valores. */
@keyframes repo-marca{
  0%,100%{
    box-shadow:0 0 0 0 rgba(77,163,255,0), 0 0 0 rgba(77,163,255,0);
  }
  8%,58%{
    box-shadow:0 0 0 3px rgba(77,163,255,.55), 0 0 34px rgba(77,163,255,.28);
  }
  28%,78%{
    box-shadow:0 0 0 3px rgba(77,163,255,.12), 0 0 12px rgba(77,163,255,.08);
  }
}
/* quien pidio menos movimiento recibe la marca sin parpadeo */
@media (prefers-reduced-motion:reduce){
  .repo--resaltado,
  .lab--resaltado{animation:none;box-shadow:0 0 0 3px rgba(77,163,255,.55)}
}
.repo-btn{
  width:100%;height:100%;text-align:left;cursor:pointer;
  font:inherit;color:inherit;
  background:var(--bg-alt);
  border:1px solid var(--line);
  border-radius:16px;
  padding:clamp(20px,2.1vw,26px);
  display:flex;flex-direction:column;gap:12px;
  box-shadow:
    0 18px 44px rgba(0,0,0,.26),
    inset 0 1px 0 rgba(255,255,255,.045);
  transition:border-color .2s ease, transform .2s ease, box-shadow .2s ease;
}
.repo-btn:hover,
.repo-btn:focus-visible{
  border-color:var(--acc);
  transform:translateY(-3px);
  box-shadow:
    0 26px 56px rgba(0,0,0,.34),
    inset 0 1px 0 rgba(255,255,255,.06);
  outline:none;
}
.repo-cab{
  display:flex;align-items:baseline;justify-content:space-between;
  gap:14px;
}
.repo-cab b{
  font-size:var(--body-read);font-weight:600;color:var(--tx);
  line-height:1.3;letter-spacing:-.01em;
}
.repo-n{
  font-size:11.5px;color:var(--tx-dim);white-space:nowrap;
  font-variant-numeric:tabular-nums;
}
.repo-desc{
  font-size:var(--caption);color:var(--tx-mid);line-height:1.55;
}
.repo-stack{
  list-style:none;display:flex;flex-wrap:wrap;gap:6px;margin-top:auto;
}
.repo-stack li{
  font-size:11px;font-weight:600;letter-spacing:.02em;
  color:var(--acc);
  background:rgba(77,163,255,.09);
  border:1px solid rgba(77,163,255,.22);
  border-radius:6px;padding:3px 9px;
}

/* ---------- modal ancho para el README ---------- */
.modal-ancha{width:min(1040px,100%)}

.repo-tabs{
  display:flex;gap:8px;flex-wrap:wrap;
  padding:14px 22px;border-bottom:1px solid var(--line);
  background:var(--bg-alt);
}
.repo-tab{
  font:inherit;font-size:var(--caption);font-weight:600;
  color:var(--tx-mid);
  background:var(--bg-card);
  border:1px solid var(--line);
  border-radius:8px;padding:8px 14px;cursor:pointer;
  transition:color .18s ease, background .18s ease, border-color .18s ease;
}
.repo-tab:hover{color:var(--tx);border-color:#3f5064}
.repo-tab.activa{
  color:#04121f;background:var(--acc);border-color:var(--acc);
}
.repo-tabs:empty{display:none}

/* ---------- README renderizado por GitHub ----------
   Llega como HTML ya armado. Se le impone la tipografia del sitio
   para que no traiga la de GitHub, que rompe la coherencia.     */
.readme{
  display:block;
  padding:clamp(20px,2.4vw,34px);
  text-align:left;
  line-height:1.65;color:var(--tx-mid);
}
.readme > *:first-child{margin-top:0}
.readme h1,.readme h2,.readme h3,
.readme h4,.readme h5,.readme h6{
  color:var(--tx);font-weight:600;line-height:1.3;
  margin:1.7em 0 .6em;letter-spacing:-.01em;
}
.readme h1{font-size:var(--title-md);padding-bottom:.4em;border-bottom:1px solid var(--line)}
.readme h2{font-size:var(--body-read);padding-bottom:.35em;border-bottom:1px solid var(--line)}
.readme h3{font-size:var(--body-ui)}
.readme h4,.readme h5,.readme h6{font-size:var(--caption);color:var(--tx-mid)}
.readme p{margin:.9em 0;max-width:none;font-size:var(--caption)}
.readme a{color:var(--acc);text-decoration:none}
.readme a:hover{text-decoration:underline}
.readme ul,.readme ol{margin:.9em 0 .9em 1.3em;font-size:var(--caption)}
.readme li{margin:.35em 0}
.readme strong{color:var(--tx)}
.readme hr{border:0;border-top:1px solid var(--line);margin:1.8em 0}
.readme blockquote{
  margin:1.1em 0;padding:.2em 0 .2em 1em;
  border-left:2px solid var(--acc);color:var(--tx-dim);
}
.readme code{
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:.86em;
  background:var(--bg-card);border:1px solid var(--line);
  border-radius:4px;padding:.12em .4em;
  color:var(--tx);
}
.readme pre{
  margin:1.1em 0;padding:14px 16px;overflow-x:auto;
  background:var(--bg);border:1px solid var(--line);border-radius:10px;
}
.readme pre code{background:none;border:0;padding:0;font-size:12.5px;line-height:1.6}
.readme table{
  width:100%;border-collapse:collapse;margin:1.2em 0;
  font-size:var(--caption);display:block;overflow-x:auto;
}
.readme th,.readme td{
  border:1px solid var(--line);padding:8px 12px;text-align:left;
}
.readme th{background:var(--bg-card);color:var(--tx);font-weight:600}
.readme img{max-width:100%;height:auto;border-radius:8px}
.readme .anchor,.readme .octicon{display:none}   /* anclas de GitHub */

@media(max-width:620px){
  .repos{grid-template-columns:1fr}
}
@media(prefers-reduced-motion:reduce){
  .repo-btn{transition:none}
  .repo-btn:hover{transform:none}
}


/* ---------- panel derecho del mega-menu ----------
   Muestra los proyectos de la categoria sobre la que esta el
   cursor. Mismo patron de la referencia: la izquierda orienta, la
   derecha detalla. Con el diseno de este sitio, no el de ella.  */
/* Sin esta linea el placeholder no se va nunca: `display:grid` de la regla
   de abajo le gana al atributo hidden del HTML, asi que el JS lo ocultaba
   "en papel" y seguia ocupando su height:100%. El panel de detalle real
   quedaba empujado hacia abajo, fuera de la caja. Es el mismo patron que
   ya tenia .mserv-panel-cat, que si lo declara. */
.mserv-vacio[hidden]{display:none}
.mserv-vacio{
  height:100%;display:grid;place-items:center;
  color:var(--tx-dim);font-size:var(--caption);
}
.mserv-panel-cat[hidden]{display:none}
.mserv-panel-cat{
  animation:mserv-entra .22s cubic-bezier(.16,.84,.44,1) both;
}
@keyframes mserv-entra{
  from{opacity:0;transform:translateY(6px)}
  to{opacity:1;transform:none}
}

.mserv-panel-cab{
  display:flex;align-items:baseline;justify-content:space-between;
  gap:16px;padding-bottom:12px;margin-bottom:16px;
  border-bottom:1px solid var(--line);
}
.mserv-panel-et{
  font-size:var(--caption);font-weight:600;
  text-transform:uppercase;letter-spacing:.09em;color:var(--acc);
}
.mserv-panel-n{
  font-size:var(--caption);color:var(--tx-dim);
  font-variant-numeric:tabular-nums;
}

.mserv-proys{
  list-style:none;
  display:grid;gap:8px;
  grid-template-columns:repeat(auto-fill,minmax(230px,1fr));
  align-content:start;
}
.mserv-proy{
  display:flex;align-items:center;gap:13px;
  padding:12px 14px;border-radius:10px;
  text-decoration:none;color:inherit;
  border:1px solid transparent;
  /* Filo del acento a la izquierda.
     Va en el borde y no en un pseudoelemento para que ocupe sitio: asi
     el texto no se corre cuando el borde de alrededor aparece al pasar
     el cursor. Por eso el borde base ya existia en transparente. */
  border-left:2px solid var(--acc);
  transition:background .18s ease, border-color .18s ease;
}
.mserv-proy:hover{
  background:var(--bg-alt);
  border-color:var(--line);
  /* border-color de arriba pisaria tambien el filo: se repite para que
     el izquierdo siga siendo del acento */
  border-left-color:var(--acc);
}
.mserv-num{
  flex:0 0 auto;
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:12px;font-weight:600;color:var(--tx-dim);
  font-variant-numeric:tabular-nums;
}
.mserv-proy:hover .mserv-num{color:var(--acc)}
.mserv-info{min-width:0}
.mserv-info b{
  display:block;font-size:var(--body-ui);font-weight:600;
  color:var(--tx);line-height:1.3;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.mserv-info span{
  display:block;margin-top:3px;font-size:11.5px;color:var(--tx-dim);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}


/* ---------- laboratorio: demos navegables ----------
   Misma tarjeta del resto de la ficha. Abre en pestana nueva porque
   el demo es otra aplicacion: no conviene sacar al visitante de la
   ficha sin dejarle donde volver.                                 */
.labs{
  display:grid;gap:16px;
  grid-template-columns:repeat(auto-fill,minmax(300px,1fr));
}
.lab-btn{
  display:flex;flex-direction:column;gap:11px;height:100%;
  text-decoration:none;color:inherit;
  background:var(--bg-alt);
  border:1px solid var(--line);
  border-radius:16px;
  padding:clamp(20px,2.1vw,26px);
  box-shadow:
    0 18px 44px rgba(0,0,0,.26),
    inset 0 1px 0 rgba(255,255,255,.045);
  transition:border-color .2s ease, transform .2s ease, box-shadow .2s ease;
}
.lab-btn:hover,
.lab-btn:focus-visible{
  border-color:var(--acc);
  transform:translateY(-3px);
  box-shadow:
    0 26px 56px rgba(0,0,0,.34),
    inset 0 1px 0 rgba(255,255,255,.06);
  outline:none;
}
.lab-cab{display:flex;align-items:baseline;gap:11px}
.lab-num{
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:12px;font-weight:600;color:var(--tx-dim);
  font-variant-numeric:tabular-nums;
}
.lab-btn:hover .lab-num{color:var(--acc)}
.lab-cab b{
  font-size:var(--body-read);font-weight:600;color:var(--tx);
  line-height:1.3;letter-spacing:-.01em;
}
.lab-desc{font-size:var(--caption);color:var(--tx-mid);line-height:1.55}
.lab-stack{list-style:none;display:flex;flex-wrap:wrap;gap:6px}
.lab-stack li{
  font-size:11px;font-weight:600;
  color:var(--tx-mid);
  background:var(--bg-card);
  border:1px solid var(--line);
  border-radius:6px;padding:3px 9px;
}
.lab-ir{
  display:inline-flex;align-items:center;gap:7px;margin-top:auto;
  font-size:var(--caption);font-weight:600;color:var(--acc);
}
.lab-ir svg{
  width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:2.2;
  stroke-linecap:round;stroke-linejoin:round;
  transition:transform .2s ease;
}
.lab-btn:hover .lab-ir svg{transform:translate(2px,-2px)}

@media(max-width:620px){ .labs{grid-template-columns:1fr} }
@media(prefers-reduced-motion:reduce){
  .lab-btn{transition:none}
  .lab-btn:hover{transform:none}
  .lab-btn:hover .lab-ir svg{transform:none}
}


/* ---------- tableros en vivo ----------
   El tablero se incrusta tal cual. Es claro y el sitio es oscuro:
   el marco lleva su propio fondo claro para que no se vea un
   parpadeo oscuro mientras carga.                                */
.tabs-vivo{display:grid;gap:clamp(20px,2.4vw,32px)}
.tab{
  background:var(--bg-alt);
  border:1px solid var(--line);
  border-radius:16px;
  padding:clamp(20px,2.2vw,30px);
  box-shadow:
    0 18px 44px rgba(0,0,0,.26),
    inset 0 1px 0 rgba(255,255,255,.045);
}
.tab-cab{
  display:flex;align-items:flex-start;justify-content:space-between;
  gap:20px;flex-wrap:wrap;margin-bottom:18px;
}
.tab-id h3{
  font-size:var(--body-read);font-weight:600;color:var(--tx);
  line-height:1.3;letter-spacing:-.01em;
}
.tab-id p{
  margin-top:8px;font-size:var(--caption);color:var(--tx-mid);
  max-width:66ch;line-height:1.55;
}
.tab-acc{display:flex;gap:9px;flex-wrap:wrap;flex-shrink:0}
.tab-enl{
  display:inline-flex;align-items:center;gap:7px;
  font-size:var(--caption);font-weight:600;text-decoration:none;
  color:var(--tx-mid);
  background:var(--bg-card);
  border:1px solid var(--line);
  border-radius:8px;padding:9px 14px;
  transition:color .18s ease, border-color .18s ease, background .18s ease;
}
.tab-enl:hover{color:var(--tx);border-color:#3f5064}
.tab-enl--acc{
  color:var(--acc);
  background:rgba(77,163,255,.10);
  border-color:rgba(77,163,255,.34);
}
.tab-enl--acc:hover{color:#04121f;background:var(--acc);border-color:var(--acc)}
.tab-enl svg{
  width:13px;height:13px;fill:none;stroke:currentColor;stroke-width:2.2;
  stroke-linecap:round;stroke-linejoin:round;
}
.tab-ico{
  width:14px;height:14px;flex:0 0 14px;background:currentColor;
  -webkit-mask:var(--i) center/contain no-repeat;
          mask:var(--i) center/contain no-repeat;
}

.tab-cifras{
  list-style:none;display:flex;flex-wrap:wrap;
  gap:clamp(20px,3vw,44px);
  padding:16px 0;margin-bottom:18px;
  border-top:1px solid var(--line);
  border-bottom:1px solid var(--line);
}
.tab-cifras b{
  display:block;font-size:clamp(1.2rem,1.6vw,1.55rem);font-weight:700;
  color:var(--tx);letter-spacing:-.02em;
  font-variant-numeric:tabular-nums;line-height:1.1;
}
.tab-cifras span{
  display:block;margin-top:4px;font-size:11.5px;font-weight:600;
  text-transform:uppercase;letter-spacing:.08em;color:var(--tx-dim);
}

.tab-marco{
  border-radius:12px;overflow:hidden;
  border:1px solid var(--line);
  background:#f8f9fa;                 /* el tablero es claro */
  height:clamp(460px, 68vh, 760px);
}
.tab-marco iframe{width:100%;height:100%;border:0;display:block}

.tab-stack{
  list-style:none;display:flex;flex-wrap:wrap;gap:7px;margin-top:16px;
}
.tab-stack li{
  font-size:11px;font-weight:600;color:var(--tx-mid);
  background:var(--bg-card);
  border:1px solid var(--line);
  border-radius:6px;padding:4px 10px;
}

@media(max-width:620px){
  .tab-cab{flex-direction:column}
  .tab-cifras{gap:22px}
}

/* ---------- mega-menu de Ficha tecnica ----------
   Mismo layout que Servicios: categorias en columna a la izquierda,
   detalle a la derecha. La unica diferencia es la altura: con cuatro
   secciones no tiene sentido ocupar la pantalla entera, asi que la
   caja mide lo justo para que las filas respiren.               */
.mfic-btn{display:inline-flex;align-items:center;gap:5px;position:relative}
.mfic-btn[aria-expanded="true"]{color:var(--acc)}
.mfic-btn[aria-expanded="true"] .mserv-cv{transform:rotate(180deg)}
.mfic-btn::after{
  content:'';position:absolute;left:0;right:0;bottom:-19px;height:2px;
  background:var(--acc);border-radius:2px;
  transform:scaleX(0);transform-origin:center;
  transition:transform .24s cubic-bezier(.4,0,.2,1);
}
.mfic-btn[aria-expanded="true"]::after{transform:scaleX(1)}

/* pisa la altura de pantalla completa que hereda de .mserv-caja */
.mfic-caja{
  height:auto;
  min-height:clamp(240px, 34vh, 360px);
  max-height:none;
  padding-top:clamp(18px,2.2vh,30px);
  padding-bottom:clamp(22px,2.8vh,38px);
}

@media(max-width:1000px){ .mfic{display:none !important} }


/* ---------- metodologias, dentro de 'Como trabajo' ----------
   Por ahora es solo texto. Cuando se decida como presentarlas de
   forma formal, este bloque cambia sin tocar nada mas.          */
/* "Como trabajo" arranca mas arriba que las demas secciones.
   El relleno general de section es calc(var(--u)*4) -unos 105px-, y
   estaba calibrado para cuando esta seccion llevaba las cinco fases y
   los seis principios. Ahora que solo lleva el encabezado y las
   metodologias, ese hueco quedaba desproporcionado respecto a lo que
   hay debajo. Se toca solo aqui: las otras secciones conservan su
   ritmo. */
#trabajo{padding-top:calc(var(--u)*2.2)}

.metodologias{
  margin-top:calc(var(--u)*1.8);
  padding-top:calc(var(--u)*1.2);
  border-top:1px solid var(--line);
}
.metodologias .label{display:block;margin-bottom:10px}
.metodologias p{max-width:72ch}

/* ---------- tableros: etiqueta de estado y texto del desplegable ----------
   Un tablero que todavia corre solo en esta maquina se marca en su propia
   tarjeta. Si la pagina se publicara antes de desplegarlo, el marco saldria
   en blanco, y sin la etiqueta pareceria un error del sitio.               */
.tab-local{
  display:inline-block;vertical-align:middle;margin-left:10px;
  font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:#f0b429;background:rgba(240,180,41,.12);
  border:1px solid rgba(240,180,41,.35);border-radius:4px;
  padding:2px 8px;white-space:nowrap;
}
/* El marco de un tablero local se distingue del de uno publicado. */
.tab[data-local] .tab-marco{border-color:rgba(240,180,41,.3)}

/* Texto descriptivo dentro del panel derecho del desplegable. */
.mserv-panel-txt{
  margin:0;color:var(--tx-mid);font-size:13.5px;line-height:1.6;max-width:40ch;
}

/* Grupo creado pero todavia sin proyectos. Se marca para que se note
   que falta contenido y no parezca que el grupo esta vacio por diseno. */
.mserv-pendiente{
  color:var(--tx-dim);
  border-left:2px solid var(--line);
  padding-left:12px;
}

/* Servicio anunciado pero sin respaldo todavia en master/.
   El filo gris -no el azul de los demas- es la senal: se ve que esa
   entrada esta a la espera de evidencia y no se publica como si ya
   estuviera comprobada. */
.mserv-proy--pendiente{border-left-color:var(--line)}
.mserv-proy--pendiente .mserv-info b{color:var(--tx-mid)}
.mserv-proy--pendiente .mserv-num::after{
  content:"·";
  margin-left:4px;
  color:var(--tx-dim);
}


/* ============================================================
   METODOLOGIAS
   Lista a la izquierda, diagrama y descripcion a la derecha. Reusa
   .mserv-cat y .mserv-panel-cat para que la mueva el mismo conDetalle
   de app.js que ya mueve los dos desplegables del menu. Lo que cambia
   aqui es solo la presentacion: esto no flota sobre la pagina, vive
   dentro de ella.
   ============================================================ */
.met-caja{
  display:grid;
  grid-template-columns:minmax(160px, 210px) 1fr;
  gap:clamp(18px,2.6vw,42px);
  margin-top:calc(var(--u)*1.1);
  background:var(--bg-alt);
  border:1px solid var(--line);
  border-radius:16px;
  padding:clamp(18px,2vw,28px);
}

/* La lista NO se estira con la imagen.
   Antes este bloque reusaba la clase .mserv-lista del desplegable del
   menu, y con ella heredaba `ul{height:100%}` y `li{flex:1 1 0}`: reglas
   pensadas para un panel de altura fija, que aqui repartian el alto de
   la imagen entre las cinco opciones. Ahora la lista mide lo que miden
   sus opciones y se queda arriba. */
.met-lista{align-self:start}
.met-lista ul{list-style:none;display:grid;gap:2px}
.met-lista li{display:block}
.met-lista .mserv-cat{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:11px 13px;border-radius:9px;
  font-size:var(--body-ui);font-weight:600;
  color:var(--tx-mid);
  /* el filo de la izquierda marca la activa sin mover la fila */
  border-left:2px solid transparent;
  transition:color .18s ease, background .18s ease, border-color .18s ease;
}
.met-lista .mserv-cat:hover{color:var(--tx);background:var(--bg-card)}
.met-lista .mserv-cat.activa{
  color:var(--acc);
  background:var(--bg-card);
  border-left-color:var(--acc);
}
.met-lista .mserv-ch{width:16px;height:16px;flex:none;opacity:.5}
.met-lista .mserv-ch path{fill:none;stroke:currentColor;stroke-width:2}

.met-detalle{min-width:0}
.met-panel[hidden]{display:none}
/* Si alguien llega con el ancla en la URL -/#met-tdd compartido por
   ahi-, el navegador si desplaza. Que se detenga debajo de la isla y no
   por detras de ella. */
.met-caja,
.met-panel{scroll-margin-top:calc(var(--isla) + 24px)}
.met-panel .mserv-panel-cab{
  display:flex;align-items:baseline;justify-content:space-between;
  gap:14px;flex-wrap:wrap;
  padding-bottom:12px;margin-bottom:16px;
  border-bottom:1px solid var(--line);
}
.met-panel .mserv-panel-et{
  font-size:var(--title-md);font-weight:600;color:var(--tx);
}
.met-panel .mserv-panel-n{
  font-size:var(--caption);color:var(--tx-dim);
}

/* --- el diagrama ---
   Un SVG por metodologia, todos sobre la misma reticula de 340x120 para
   que al cambiar de una a otra el bloque no salte de alto. */
.met-diagrama svg{
  display:block;width:100%;height:auto;max-width:420px;
}
/* Una imagen generada viene con fondo blanco, y el sitio es oscuro.
   Mismo tratamiento que las miniaturas de certificados: enmarcada,
   atenuada para no quemar la retina, y a color pleno al pasar el
   cursor.

   Sin tope de alto. Lo hubo -420px- y era el error: con una infografia
   de 1672px de ancho, ese tope la encogia al 45% y las descripciones
   quedaban en 6px, ilegibles. Dejandola a lo ancho del panel se ve al
   54% y el texto chico llega a 11px, que si se lee. Lo que cuesta es
   alto de pagina, y eso se resuelve bajando. */
.met-diagrama img{
  display:block;width:100%;height:auto;
  border:1px solid var(--line);
  border-radius:12px;
  background:#fff;
  opacity:.88;
  transition:opacity .22s ease;
}
.met-diagrama img:hover{opacity:1}
.d-caja{fill:var(--bg-card);stroke:var(--line);stroke-width:1.5}
.d-caja.d-viva{stroke:var(--acc)}
.d-caja.d-roja{stroke:#d9534f}
.d-caja.d-verde{stroke:var(--ok)}
.d-col{fill:none;stroke:var(--line);stroke-width:1.5}
.d-col.d-viva{stroke:var(--acc)}
.d-ficha{fill:var(--bg-card);stroke:var(--line);stroke-width:1}
.d-ficha.d-viva{fill:rgba(77,163,255,.14);stroke:var(--acc)}
.d-anillo{fill:none;stroke:var(--line);stroke-width:1.5;stroke-dasharray:4 5}
.d-hito{stroke:var(--acc);stroke-width:1.5;stroke-dasharray:3 4}
.d-fl{
  fill:none;stroke:var(--tx-dim);stroke-width:1.5;
  marker-end:none;
}
.d-fl.d-vuelta{stroke-dasharray:4 4}
.d-tx{
  fill:var(--tx);font-size:11px;font-weight:600;
  text-anchor:middle;dominant-baseline:middle;
}
.d-tx.d-min{font-size:9.5px;font-weight:500;fill:var(--tx-mid)}
.d-et{
  fill:var(--tx-dim);font-size:9.5px;
  text-anchor:middle;letter-spacing:.04em;
}

/* Que es la metodologia: la linea que resume de que va. */
.met-resumen{
  margin-top:18px;
  font-size:var(--body-read);color:var(--tx);
  line-height:1.55;max-width:60ch;
}
/* Dos colores de resaltado, cada uno con un significado, para que
   marcar informe en vez de decorar:
     .k     azul  -el acento del sitio-  el MECANISMO
     .k-ok  verde -el mismo de "Completado" en Estudios-  el RESULTADO
   Como maximo dos marcas por frase: si se resalta media oracion, deja
   de haber jerarquia. */
.met-resumen .k{color:var(--acc);font-weight:600}
.met-resumen .k-ok{color:var(--ok);font-weight:600}
/* Como la usa Paulo. Va debajo, mas apagado, porque el resumen es la
   entrada y esto es el detalle. */
.met-aplico{
  margin-top:12px;
  font-size:var(--body-ui);color:var(--tx-mid);
  line-height:1.6;max-width:58ch;
}
.met-respaldo{
  display:block;margin-top:16px;
  font-size:var(--caption);color:var(--tx-dim);
}

@media (max-width:760px){
  .met-caja{grid-template-columns:1fr;gap:18px}
  .met-lista ul{
    display:flex;flex-wrap:wrap;gap:6px;
    padding-bottom:14px;border-bottom:1px solid var(--line);
  }
  .met-lista .mserv-cat{padding:8px 12px;border-left:0}
  .met-lista .mserv-cat.activa{border-left:0}
  .met-lista .mserv-ch{display:none}
}


/* ============================================================
   CASOS  —  anatomia del bloque destacado de histrips
   Tarjeta visual a la izquierda con su reticula de seis fichas;
   identidad, relato y UN solo boton a la derecha.
   El "un solo boton" es el patron E5: antes habia dos por caso y los
   seis apuntaban a "#".
   ============================================================ */
/* Encabezado y pestanas en la misma fila, como en la referencia: el
   titulo a la izquierda, la barra a la derecha. Debajo de 720px la
   barra baja y se puede arrastrar en horizontal. */
.casos-cab{
  display:flex;align-items:flex-end;justify-content:space-between;
  gap:24px;flex-wrap:wrap;
  margin-bottom:calc(var(--u)*1.2);
}
.casos-cab .enc{margin-bottom:0}
.casos-bajada{
  margin-top:12px;
  font-size:var(--body-read);
  color:var(--tx-mid);
  max-width:48ch;
}

.casos-tabs{
  display:flex;gap:2px;
  padding:4px;
  background:var(--bg-alt);
  border:1px solid var(--line);
  border-radius:999px;
}
.casos-tab{
  font:inherit;font-size:var(--caption);font-weight:600;
  color:var(--tx-mid);
  background:none;border:0;cursor:pointer;
  padding:9px 18px;border-radius:999px;
  white-space:nowrap;
  transition:color .18s ease, background .18s ease;
}
.casos-tab:hover{color:var(--tx)}
/* La activa lleva su propia pastilla, igual que la referencia: es lo
   que hace que se lea como un interruptor y no como cuatro enlaces. */
.casos-tab[aria-selected="true"]{
  color:var(--tx);
  background:var(--bg-card);
  box-shadow:0 1px 3px rgba(0,0,0,.28);
}
.casos-tab:focus-visible{outline:2px solid var(--acc);outline-offset:2px}

.caso2[hidden]{display:none}

@media (max-width:720px){
  .casos-cab{align-items:flex-start}
  .casos-tabs{
    width:100%;
    overflow-x:auto;
    border-radius:14px;
  }
  .casos-tab{flex:1 0 auto}
}

.caso2{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:clamp(16px,2vw,28px);
  align-items:stretch;
  margin-top:calc(var(--u)*1.6);
  padding:clamp(14px,1.4vw,20px);
  background:var(--bg-alt);
  border:1px solid var(--line);
  border-radius:22px;
}

/* ---- izquierda: la tarjeta visual ---- */
.caso2-vista{
  position:relative;
  display:flex;flex-direction:column;
  gap:clamp(14px,1.6vw,22px);
  padding:clamp(20px,2.2vw,32px);
  background:var(--bg-card);
  border-radius:16px;
}
.caso2-pill{
  position:absolute;top:clamp(14px,1.6vw,20px);left:clamp(14px,1.6vw,20px);
  font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ok);
  background:rgba(63,185,132,.12);
  border:1px solid rgba(63,185,132,.32);
  border-radius:999px;padding:5px 12px;
}
.caso2-cab{text-align:center;padding-top:clamp(18px,2vh,28px)}
.caso2-sistema{
  font-size:var(--title-md);font-weight:700;
  color:var(--tx-mid);letter-spacing:-.015em;
}
/* el nombre en el acento, el resto apagado: mismo recurso que usa la
   referencia para separar producto de familia */
.caso2-sistema span{color:var(--acc)}
.caso2-lema{
  margin-top:6px;
  font-size:var(--caption);color:var(--tx-dim);
}

/* Mientras no haya imagen, un hueco con la proporcion que tendra, para
   que el bloque no cambie de alto el dia que se agregue. */
.caso2-img,
.caso2-hueco{
  display:block;width:100%;
  aspect-ratio:16/10;
  border-radius:12px;
  object-fit:cover;
}
.caso2-hueco{
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(77,163,255,.10), transparent 70%),
    var(--bg);
  border:1px dashed var(--line);
}

/* la reticula de seis, 3x2 como en la referencia */
.caso2-fichas{
  list-style:none;
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:10px;
  margin-top:auto;
}
.caso2-fichas li{
  display:flex;align-items:center;
  min-height:64px;
  padding:11px 12px;
  font-size:var(--caption);line-height:1.35;
  color:var(--tx-mid);
  background:var(--bg-alt);
  border:1px solid var(--line);
  border-radius:10px;
  transition:color .18s ease, border-color .18s ease;
}
.caso2-fichas li:hover{color:var(--tx);border-color:#3f5064}

/* ---- derecha: el caso ---- */
.caso2-info{
  display:flex;flex-direction:column;
  padding:clamp(20px,2.4vw,38px) clamp(16px,2vw,28px);
}
.caso2-info .label{display:block;color:var(--acc);margin-bottom:14px}
.caso2-titular{
  font-size:var(--title-lg);
  line-height:1.18;font-weight:700;
  letter-spacing:-.02em;color:var(--tx);
  max-width:22ch;
}
.caso2-relato{margin-top:clamp(16px,2vh,24px)}
.caso2-relato p{
  font-size:var(--body-ui);color:var(--tx-mid);
  line-height:1.6;max-width:52ch;
}
.caso2-relato p + p{margin-top:12px}
.caso2-relato b{color:var(--tx);font-weight:600}

.caso2-ficha{
  display:grid;grid-template-columns:repeat(2,1fr);
  gap:12px 20px;
  margin-top:clamp(18px,2.2vh,26px);
  padding-top:clamp(16px,2vh,22px);
  border-top:1px solid var(--line);
}
.caso2-ficha dt{font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--tx-dim)}
.caso2-ficha dd{margin-top:3px;font-size:var(--caption);color:var(--tx)}

/* el boton, siempre al pie: asi queda a la misma altura en los tres
   casos aunque el relato mida distinto */
.caso2-cta{
  margin-top:auto;
  align-self:start;
  margin-top:clamp(22px,2.6vh,32px);
}

/* ---- la pagina de un caso ---- */
.caso-detalle{
  display:grid;
  grid-template-columns:minmax(0,1.35fr) minmax(0,1fr);
  gap:clamp(24px,3vw,56px);
  align-items:start;
}
.caso-relato h2{
  font-size:var(--title-md);font-weight:600;color:var(--tx);
  margin-bottom:10px;
}
.caso-relato h2 + p{margin-bottom:calc(var(--u)*1.2)}
.caso-relato p{
  font-size:var(--body-read);color:var(--tx-mid);
  line-height:1.65;max-width:var(--lectura);
}
.caso-lado{
  padding:clamp(18px,2vw,26px);
  background:var(--bg-alt);
  border:1px solid var(--line);
  border-radius:16px;
}
.caso-lado .caso2-ficha{margin-top:0;padding-top:0;border-top:0}
.caso-lado-t{
  font-size:var(--caption);font-weight:700;
  letter-spacing:.06em;text-transform:uppercase;
  color:var(--tx-dim);
  margin-top:calc(var(--u)*1.1);
  padding-top:calc(var(--u)*.8);
  border-top:1px solid var(--line);
}
.caso-lado-fichas{grid-template-columns:1fr;margin-top:14px}
.caso-lado-fichas li{min-height:0}

@media (max-width:900px){
  .caso2{grid-template-columns:1fr}
  .caso2-titular{max-width:none}
  .caso2-fichas{grid-template-columns:repeat(2,1fr)}
  .caso-detalle{grid-template-columns:1fr}
}
@media (max-width:520px){
  .caso2-fichas{grid-template-columns:1fr}
  .caso2-fichas li{min-height:0}
  .caso2-ficha{grid-template-columns:1fr}
}


/* ============================================================
   BARRAS DE DESPLAZAMIENTO
   Salian blancas, las del sistema, en medio de una pagina oscura.
   `color-scheme` es la forma estandar de pedirle al navegador que use
   sus controles oscuros; las reglas de abajo les dan ademas el color
   del sitio donde el navegador lo permite.
   ============================================================ */
:root{ color-scheme:dark; --barra:#3a4757; --barra-viva:#4f6178; }

*{ scrollbar-width:thin; scrollbar-color:var(--barra) transparent; }

::-webkit-scrollbar{width:12px;height:12px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{
  background:var(--barra);
  border-radius:999px;
  /* el borde transparente deja aire a los lados del pulgar: sin el,
     la barra se ve pegada al borde y mas gruesa de lo que es */
  border:3px solid transparent;
  background-clip:content-box;
}
::-webkit-scrollbar-thumb:hover{
  background:var(--barra-viva);
  background-clip:content-box;
}
::-webkit-scrollbar-corner{background:transparent}


/* ============================================================
   TABLEROS  —  tres tarjetas en fila, con vista previa en vivo
   La miniatura no es una captura: es el tablero dentro de un iframe
   renderizado a ancho de escritorio y encogido con transform. Asi
   refleja el estado real y no envejece.
   ============================================================ */
.tabm-fila{
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:clamp(14px,1.6vw,22px);
}

.tabm{
  display:flex;flex-direction:column;
  background:var(--bg-alt);
  border:1px solid var(--line);
  border-radius:16px;
  overflow:hidden;
  transition:border-color .2s ease, transform .2s ease;
}
.tabm:hover{border-color:var(--acc);transform:translateY(-3px)}

/* ---- la vista previa ---- */
.tabm-vista{
  --esc:.34;                 /* cuanto se encoge el tablero */
  position:relative;display:block;
  aspect-ratio:16/10;
  background:var(--bg);
  border-bottom:1px solid var(--line);
  overflow:hidden;
}
/* El iframe se dibuja a 1/esc del tamano de la caja -unos 1300px de
   ancho, medida de escritorio- y despues se encoge. Si se dibujara al
   tamano de la tarjeta, el tablero creeria estar en un movil y
   mostraria su version chica. */
.tabm-vista iframe{
  position:absolute;top:0;left:0;
  width:calc(100% / var(--esc));
  height:calc(100% / var(--esc));
  transform:scale(var(--esc));
  transform-origin:0 0;
  border:0;
  /* sin esto, la rueda del raton movería el tablero de adentro en vez
     de la pagina, y el clic no llegaria al enlace */
  pointer-events:none;
}

/* velo que se levanta al pasar el cursor */
.tabm-capa{
  position:absolute;inset:0;
  display:grid;place-items:center;
  background:linear-gradient(180deg, rgba(17,24,33,.30), rgba(17,24,33,.72));
  opacity:1;
  transition:opacity .22s ease, backdrop-filter .22s ease;
}
.tabm:hover .tabm-capa{background:linear-gradient(180deg, rgba(17,24,33,.10), rgba(17,24,33,.55))}
.tabm-ver{
  font-size:var(--caption);font-weight:700;
  letter-spacing:.04em;text-transform:uppercase;
  color:var(--tx);
  background:rgba(17,24,33,.72);
  border:1px solid var(--line);
  border-radius:999px;padding:8px 16px;
  transform:translateY(6px);opacity:0;
  transition:transform .22s ease, opacity .22s ease;
}
.tabm:hover .tabm-ver{transform:none;opacity:1}

/* Mensaje para cuando el tablero no contesta. Nace con el atributo
   hidden y lo descubre app.js; si el tablero responde, no se ve nunca. */
.tabm-caido[hidden]{display:none}
.tabm-caido{
  position:absolute;inset:0;
  display:flex;flex-direction:column;justify-content:center;
  gap:8px;padding:clamp(16px,2vw,26px);
  font-size:var(--caption);line-height:1.55;
  color:var(--tx-dim);
  background:
    repeating-linear-gradient(135deg,
      rgba(255,255,255,.012) 0 10px, transparent 10px 20px),
    var(--bg);
}
.tabm-caido b{
  display:block;font-size:var(--body-ui);font-weight:600;color:var(--tx-mid);
}
/* con el mensaje a la vista, el velo de "Ver el tablero" estorba */
.tabm--caido .tabm-capa{display:none}

.tabm-local{
  position:absolute;top:10px;left:10px;
  z-index:2;
  font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:#ffd479;
  background:rgba(255,212,121,.12);
  border:1px solid rgba(255,212,121,.34);
  border-radius:999px;padding:4px 10px;
}

/* ---- el cuerpo ---- */
.tabm-cuerpo{
  display:flex;flex-direction:column;
  gap:12px;
  padding:clamp(14px,1.4vw,20px);
  flex:1;
}
.tabm-cuerpo h3{
  font-size:var(--body-read);font-weight:600;
  line-height:1.3;letter-spacing:-.01em;
}
.tabm-cuerpo h3 a{color:var(--tx);transition:color .18s ease}
.tabm-cuerpo h3 a:hover{color:var(--acc)}

.tabm-cifras{
  list-style:none;display:flex;flex-wrap:wrap;gap:4px 16px;
}
.tabm-cifras li{display:flex;flex-direction:column}
.tabm-cifras b{
  font-size:var(--body-ui);font-weight:700;color:var(--acc);
  font-variant-numeric:tabular-nums;
}
.tabm-cifras span{font-size:11px;color:var(--tx-dim)}

.tabm-stack{
  list-style:none;display:flex;flex-wrap:wrap;gap:5px;
  margin-top:auto;
}
.tabm-stack li{
  font-size:10.5px;font-weight:600;
  color:var(--tx-mid);
  background:var(--bg-card);
  border:1px solid var(--line);
  border-radius:5px;padding:3px 7px;
}

.tabm-abrir{
  display:inline-flex;align-items:center;gap:7px;
  font-size:var(--caption);font-weight:600;
  color:var(--acc);
  padding-top:10px;border-top:1px solid var(--line);
}
.tabm-abrir svg{width:13px;height:13px;flex:none}
.tabm-abrir svg path{fill:none;stroke:currentColor;stroke-width:2}
.tabm-abrir:hover{color:var(--tx)}

/* ---- diseños ----
   Reusan la tarjeta de los tableros. Lo unico propio es que aqui no hay
   cifras ni stack: solo la portada, el nombre y "Echa un vistazo", asi
   que la tarjeta es mas baja y caben tres por fila con holgura.

   La portada no es un iframe encogido sino una imagen, asi que la caja
   pasa de 16/10 a 4/3: es la proporcion en que estan hechas las piezas
   y de ese modo la portada entra entera, sin recorte. */
.dis-cuerpo{gap:14px}
.dis-cuerpo h3{font-size:var(--title-md)}
.dis-vista{aspect-ratio:4/3}
.dis-vista img{
  position:absolute;inset:0;
  width:100%;height:100%;
  object-fit:cover;display:block;
  transition:transform .4s ease;
}
.tabm:hover .dis-vista img{transform:scale(1.03)}

/* cuantas piezas trae el proyecto, arriba de la portada */
.dis-n{
  position:absolute;top:10px;right:10px;z-index:2;
  font-size:10.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;
  color:var(--tx-mid);
  background:rgba(17,24,33,.74);
  border:1px solid var(--line);
  border-radius:999px;padding:4px 10px;
}

/* Hueco de la tarjeta que todavia no tiene diseno cargado. Se ve que
   falta, en vez de parecer una tarjeta rota. */
.dis-hueco{
  position:absolute;inset:0;
  display:grid;place-items:center;
  font-size:var(--caption);color:var(--tx-dim);
  background:
    repeating-linear-gradient(135deg,
      rgba(255,255,255,.014) 0 10px, transparent 10px 20px),
    var(--bg);
}
/* el "En preparacion" ocupa el lugar del enlace, pero no es un enlace */
.dis-sin{color:var(--tx-dim);cursor:default}
.dis-sin:hover{color:var(--tx-dim)}

@media (max-width:1100px){
  .tabm-fila{grid-template-columns:repeat(2,1fr)}
  /* menos ancho por tarjeta: se encoge un poco mas para que el tablero
     siga entrando entero */
  .tabm-vista{--esc:.30}
}
@media (max-width:680px){
  .tabm-fila{grid-template-columns:1fr}
  .tabm-vista{--esc:.42}
}


/* ============================================================
   UN TABLERO A PANTALLA COMPLETA
   La pagina es el tablero: ni titulo, ni descripcion, ni cifras. Eso
   ya se leyo en la tarjeta de la que se viene. Lo unico que se
   conserva es la barra del sitio, para no perder la navegacion.
   ============================================================ */
/* La pagina no se desplaza: el unico desplazamiento es el del tablero.
   Antes el pie quedaba debajo y al bajar aparecia, cortando el tablero
   a la altura de la ventana. Ahora esa pagina va sin pie -lo decide
   sinPie en el layout- y ocupa exactamente la ventana. */
.cuerpo-tablero{overflow:hidden}

.tabp{
  /* arranca justo debajo de la isla, sin el relleno de las demas
     paginas: aqui cada pixel es del tablero */
  padding-top:var(--isla);
  height:100svh;
  display:flex;flex-direction:column;
}

.tabp-barra{
  display:flex;align-items:center;gap:14px;
  padding:10px clamp(16px,2.2vw,44px);
  border-bottom:1px solid var(--line);
  background:var(--bg-alt);
}
.tabp-volver{
  display:inline-flex;align-items:center;gap:7px;
  font-size:var(--caption);font-weight:600;
  color:var(--tx-mid);
  transition:color .18s ease;
}
.tabp-volver:hover{color:var(--acc)}
.tabp-volver svg{width:14px;height:14px;flex:none}
.tabp-volver svg path{fill:none;stroke:currentColor;stroke-width:2}

/* Boton de verdad, no un enlace de texto.
   Es la accion principal de esta pagina -el tablero se ve mejor a
   pantalla completa- y antes competia de igual a igual con el "volver".
   Con el relleno del acento gana la jerarquia sin agrandar la barra. */
.tabp-abrir{
  margin-left:auto;
  display:inline-flex;align-items:center;gap:8px;
  font-size:var(--caption);font-weight:600;
  color:#04121f;
  background:var(--acc);
  border-radius:8px;
  padding:9px 16px;
  /* el sitio subraya los enlaces; dentro de un boton relleno ese
     subrayado lo hace ver a medio camino entre las dos cosas */
  text-decoration:none;
  transition:filter .18s ease, transform .18s ease, box-shadow .18s ease;
  box-shadow:0 6px 18px rgba(77,163,255,.20);
}
.tabp-abrir:hover{
  filter:brightness(1.08);
  transform:translateY(-1px);
  box-shadow:0 10px 26px rgba(77,163,255,.30);
}
.tabp-abrir svg{width:15px;height:15px;flex:none}
.tabp-abrir svg path{fill:none;stroke:currentColor;stroke-width:2.2}
/* la insignia aqui no va flotando en una esquina: va en la barra */
.tabp-local{position:static}

/* El marco se come todo lo que queda de alto. flex:1 en vez de una
   altura calculada: asi no hay que adivinar cuanto mide la barra. */
.tabp-marco{
  position:relative;
  flex:1;min-height:0;
  background:var(--bg);
}
/* Posicion absoluta y no height:100%.
   El alto del marco viene de flex:1, y un porcentaje contra una altura
   que nace de flexionar no siempre resuelve: el iframe se caia a los
   150px que trae por defecto. Con inset:0 se estira contra el marco sin
   depender de eso. */
.tabp-marco iframe{
  position:absolute;inset:0;
  display:block;width:100%;height:100%;border:0;
}
.tabp-marco iframe[hidden]{display:none}
/* el aviso, centrado y en grande: aqui hay sitio de sobra */
.tabp-caido{
  align-items:center;text-align:center;
  font-size:var(--body-ui);
  max-width:none;
}
.tabp-caido b{font-size:var(--title-md)}


/* ============================================================
   UN PROYECTO DE DISEÑO  —  las piezas, una pegada a la otra
   Estructura de galeria: una columna centrada y las piezas sin hueco
   entre ellas, como una tira. Nada de texto intercalado: un pie entre
   dos piezas rompe la continuidad, que es justamente lo que hace que
   se lea como un solo recorrido.

   El ancho -880- no es decorativo. Las piezas se sirven en dos
   tamanos y el navegador elige; a 1120 la version pequena se estiraba
   y la pieza se veia blanda. A 880 entra nitida en una pantalla
   normal, y en una de mucha densidad baja la grande.
   ============================================================ */
.dpro-enc{
  margin-left:auto;margin-right:auto;
  text-align:center;
}
.dpro-enc p{margin-left:auto;margin-right:auto}
.dpro-volver{
  display:inline-flex;align-items:center;gap:6px;
  margin-bottom:clamp(10px,1.4vh,16px);
  font-size:var(--caption);font-weight:600;
  color:var(--tx-dim);
  transition:color .18s ease;
}
.dpro-volver:hover{color:var(--acc)}
.dpro-volver svg{width:14px;height:14px;flex:none}
.dpro-volver svg path{fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round}

/* La tira. El borde y las esquinas son de la tira entera, no de cada
   pieza: por dentro no hay ninguna linea que las separe. */
.dpro-piezas{
  display:flex;flex-direction:column;
  gap:0;
  width:100%;max-width:880px;
  margin:calc(var(--u)*1.6) auto 0;
  border:1px solid var(--line);
  border-radius:14px;
  overflow:hidden;
  background:var(--bg-alt);
}

/* El disparador es un <button> y no un <div> con onclick: asi entra en
   el orden de tabulacion y responde a Enter sin escribir nada extra.
   Sin borde ni fondo propios -los pone la tira- y sin radio, o se
   verian seis cajas en vez de una. */
.dpro-abrir{
  display:block;position:relative;width:100%;
  padding:0;margin:0;border:0;border-radius:0;
  background:none;
  cursor:zoom-in;
}
/* display:block en la imagen: si fuera inline, la linea base dejaria
   unos pixeles de fondo entre pieza y pieza y ya no estarian pegadas */
.dpro-abrir img{display:block;width:100%;height:auto}

/* Lo unico que marca cual pieza se va a abrir es la lupa. Se probo
   apagar las demas al pasar el cursor y molestaba: al desplazarse con
   el raton encima, la tira entera parpadeaba. */
.dpro-abrir:focus-visible{outline:2px solid var(--acc);outline-offset:-2px}

/* la lupa aparece al pasar el cursor; no tapa la pieza */
.dpro-lupa{
  position:absolute;top:12px;right:12px;
  display:grid;place-items:center;
  width:36px;height:36px;border-radius:10px;
  background:rgba(17,24,33,.72);
  border:1px solid var(--line);
  opacity:0;transform:translateY(-4px);
  transition:opacity .2s ease, transform .2s ease;
}
.dpro-abrir:hover .dpro-lupa,
.dpro-abrir:focus-visible .dpro-lupa{opacity:1;transform:none}
.dpro-lupa svg{width:16px;height:16px}
.dpro-lupa svg path{fill:none;stroke:var(--tx);stroke-width:2;stroke-linecap:round}

.dpro-pie{
  max-width:880px;
  margin:calc(var(--u)*1.6) auto 0;
  padding-top:calc(var(--u)*1);
  border-top:1px solid var(--line);
  font-size:var(--caption);
  color:var(--tx-dim);
  text-align:center;
}


/* ============================================================
   LA VENTANA DE UN PROYECTO  —  el proyecto sobre la rejilla
   Mismo cristal que el visor y por la misma razon: el proyecto se abre
   encima de donde se estaba, no en otra pantalla. La rejilla se queda
   detras, borrosa, y al cerrar se sigue en la misma tarjeta.

   Lo que se desplaza es el panel, no la pagina: por eso el cristal de
   detras no se mueve.
   ============================================================ */
.dmod[hidden]{display:none}
.dmod{
  position:fixed;inset:0;z-index:110;
  display:grid;place-items:center;
  padding:clamp(18px,4vh,54px) clamp(12px,4vw,48px);
  background:rgba(10,14,20,.52);
  -webkit-backdrop-filter:blur(22px) saturate(130%);
  backdrop-filter:blur(22px) saturate(130%);
  opacity:0;transition:opacity .24s ease;
}
.dmod.abierto{opacity:1}

/* El panel entra creciendo, igual que la pieza en el visor: es lo que
   se lee como "se abrio algo encima" y no como "cargo otra pagina". */
.dmod-panel{
  width:100%;max-width:980px;max-height:100%;
  overflow-y:auto;overscroll-behavior:contain;
  padding:clamp(26px,3.4vw,48px) clamp(18px,2.6vw,42px) clamp(24px,3vw,40px);
  background:rgba(17,24,33,.72);
  -webkit-backdrop-filter:blur(14px);
  backdrop-filter:blur(14px);
  border:1px solid var(--line);
  border-radius:18px;
  box-shadow:0 30px 90px rgba(0,0,0,.55);
  transform:scale(.96);
  transition:transform .26s cubic-bezier(.2,.8,.3,1);
}
.dmod.abierto .dmod-panel{transform:none}

/* dentro del panel el encabezado ya no cierra con linea: el borde del
   propio panel hace ese trabajo y dos lineas seguidas sobran */
.dmod-panel .dpro-enc{
  border-bottom:0;
  padding-bottom:0;
  margin-bottom:calc(var(--u)*1.6);
}
.dmod-panel .dpro-piezas{margin-top:0}

.dmod-x{
  position:absolute;z-index:2;
  top:clamp(12px,2vh,22px);right:clamp(12px,2vw,26px);
  width:42px;height:42px;
  display:grid;place-items:center;
  border:1px solid var(--line);border-radius:999px;
  background:rgba(17,24,33,.6);
  -webkit-backdrop-filter:blur(10px);
  backdrop-filter:blur(10px);
  color:var(--tx);cursor:pointer;
  transition:background .18s ease, border-color .18s ease;
}
.dmod-x:hover{background:rgba(17,24,33,.88);border-color:var(--acc)}
.dmod-x svg{width:20px;height:20px}
.dmod-x svg path{fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round}

/* la barra del panel, del mismo color que el resto del sitio */
.dmod-panel::-webkit-scrollbar{width:10px}
.dmod-panel::-webkit-scrollbar-track{background:transparent}
.dmod-panel::-webkit-scrollbar-thumb{
  background:rgba(255,255,255,.16);
  border-radius:999px;
  border:3px solid transparent;
  background-clip:content-box;
}
.dmod-panel::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.28);background-clip:content-box}

@media (max-width:680px){
  .dmod{padding:10px}
  .dmod-panel{border-radius:14px}
  .dmod-x{top:6px;right:6px}
}


/* ============================================================
   EL VISOR  —  una pieza encima de la pagina
   No es otra pantalla: es una ventana que se abre sobre la que ya se
   estaba viendo, y por eso el fondo es cristal -translucido y
   desenfocado- en vez de opaco. La tira sigue ahi detras, borrosa; se
   entiende que no se fue a ningun lado y que basta cerrar para
   seguir donde estaba.
   Se sale con Escape, con la X o tocando el fondo, y se pasa de una
   pieza a otra con las flechas.
   ============================================================ */
.visor[hidden]{display:none}
/* place-items:stretch y no center: centrando, la caja se encoge al
   tamano de su contenido y la imagen, que mide su ancho contra la caja,
   se queda a medio tamano aunque sobre pantalla. Estirada, la caja mide
   todo el hueco y centra ella misma lo de adentro. */
.visor{
  position:fixed;inset:0;z-index:120;
  display:grid;place-items:stretch;
  padding:clamp(40px,5vh,64px) clamp(16px,6vw,88px);
  /* El cristal son las dos lineas juntas: el velo deja pasar la pagina
     y el desenfoque la vuelve textura, para que no compita con la
     pieza. Con el velo solo, el fondo distrae; con el desenfoque solo,
     no se lee que hay algo detras. */
  background:rgba(10,14,20,.52);
  -webkit-backdrop-filter:blur(22px) saturate(130%);
  backdrop-filter:blur(22px) saturate(130%);
  opacity:0;transition:opacity .24s ease;
}
.visor.abierto{opacity:1}

/* La pieza entra creciendo un poco desde el centro: es lo que hace que
   se lea como algo que se abre encima y no como una pagina que carga. */
.visor-caja{
  margin:0;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:14px;
  min-width:0;min-height:0;
  transform:scale(.94);
  transition:transform .26s cubic-bezier(.2,.8,.3,1);
}
.visor.abierto .visor-caja{transform:none}
.visor-caja img{
  display:block;
  max-width:100%;
  /* lo que queda de ventana despues del relleno y del pie */
  max-height:calc(100vh - clamp(130px,15vh,180px));
  width:auto;height:auto;
  object-fit:contain;
  border-radius:12px;
  background:var(--bg-alt);
  /* sobre un fondo translucido, una imagen sin sombra parece pegada al
     cristal; la sombra es lo que la despega */
  box-shadow:0 24px 70px rgba(0,0,0,.55), 0 2px 8px rgba(0,0,0,.35);
  transition:opacity .2s ease;
}
/* mientras llega la grande se ve la pequena, apenas atenuada */
.visor.cargando .visor-caja img{opacity:.75}

/* El pie tambien va en su propia pastilla de cristal: sobre un fondo
   que deja ver la pagina, un texto suelto se pierde contra lo que
   quede detras. */
.visor-caja figcaption{
  display:flex;align-items:baseline;gap:12px;
  font-size:var(--caption);color:var(--tx);
  padding:7px 16px;border-radius:999px;
  background:rgba(17,24,33,.6);
  border:1px solid var(--line);
  -webkit-backdrop-filter:blur(10px);
  backdrop-filter:blur(10px);
}
.visor-n{color:var(--tx-dim);font-variant-numeric:tabular-nums}

.visor-x,
.visor-nav{
  position:absolute;z-index:2;
  display:grid;place-items:center;
  border:1px solid var(--line);border-radius:999px;
  background:rgba(17,24,33,.6);
  -webkit-backdrop-filter:blur(10px);
  backdrop-filter:blur(10px);
  color:var(--tx);
  cursor:pointer;
  transition:background .18s ease, border-color .18s ease, transform .18s ease;
}
.visor-x:hover,
.visor-nav:hover{background:rgba(17,24,33,.88);border-color:var(--acc)}
.visor-x svg,
.visor-nav svg{width:20px;height:20px}
.visor-x svg path,
.visor-nav svg path{fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round}

.visor-x{top:clamp(12px,2vh,22px);right:clamp(12px,2vw,26px);width:42px;height:42px}
.visor-nav{top:50%;margin-top:-24px;width:48px;height:48px}
.visor-ant{left:clamp(8px,2vw,24px)}
.visor-sig{right:clamp(8px,2vw,24px)}
.visor-ant:hover{transform:translateX(-2px)}
.visor-sig:hover{transform:translateX(2px)}

@media (max-width:680px){
  .visor{padding:56px 10px 72px}
  .visor-nav{width:40px;height:40px;margin-top:-20px}
  .visor-caja img{max-height:calc(100vh - 190px)}
}

/* Servicio del grupo, todavia sin destino.
   Es un <span>, no un <a>: no navega, asi que tampoco pone el cursor de
   mano ni invita a pulsarlo. Cuando tenga a donde ir, pasa a <a> y esta
   regla sobra. */
/* El nombre de un proyecto cabe en una linea; el de un servicio, no.
   "Aplicaciones web progresivas (PWA)" salia como "Aplicaciones web
   pro...". Aqui se deja envolver a dos lineas en vez de recortar: el
   nombre completo vale mas que la altura pareja de las tarjetas. */
.mserv-serv .mserv-info b{
  white-space:normal;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
}
.mserv-serv{align-items:flex-start;cursor:default}
.mserv-serv .mserv-num{margin-top:1px}
.mserv-serv:hover{background:transparent;border-left-color:var(--line)}
.mserv-serv:hover .mserv-info b{color:var(--tx-mid)}
.mserv-serv:hover .mserv-num{color:var(--tx-dim)}

/* ── Servicios y Ficha técnica: un mismo diseño de desplegable ─────────
   Tres columnas, enlaces sin tarjeta, títulos completos y acento al
   pasar el cursor. Ficha conserva sus descripciones y enlaces. */
:is(#panel-serv, #panel-ficha) .mserv-proys{
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(18px,2.4vh,30px) clamp(24px,3vw,54px);
}

/* fuera la tarjeta: ni fondo, ni borde, ni filo, ni relleno */
:is(#panel-serv, #panel-ficha) .mserv-proy{
  display:block;
  padding:0;
  border:0;
  border-radius:0;
  background:none;
  align-items:flex-start;
}
:is(#panel-serv, #panel-ficha) .mserv-proy:hover{background:none;border:0}

/* La misma presentación sin numeración en ambos desplegables. */
:is(#panel-serv, #panel-ficha) .mserv-num{display:none}

:is(#panel-serv, #panel-ficha) .mserv-info{min-width:0}

/* el nombre, en dos lineas si hace falta */
:is(#panel-serv, #panel-ficha) .mserv-info b{
  display:block;
  font-size:var(--body-read);
  font-weight:600;
  line-height:1.35;
  color:var(--tx);
  white-space:normal;
  overflow:visible;
  margin-bottom:5px;
  transition:color .18s ease;
}

/* la descripcion entera, sin recortes */
:is(#panel-serv, #panel-ficha) .mserv-info span{
  display:block;
  margin-top:0;
  font-size:12.5px;
  line-height:1.55;
  color:var(--tx-dim);
  white-space:normal;
  overflow:visible;
  text-overflow:clip;
}

/* El acento y la flecha identifican los enlaces de ambos menús. */
:is(#panel-serv, #panel-ficha) a.mserv-proy .mserv-info b::after{
  content:'→';
  margin-left:7px;
  opacity:0;
  transform:translateX(-4px);
  display:inline-block;
  transition:opacity .18s ease, transform .18s ease;
}
:is(#panel-serv, #panel-ficha) a.mserv-proy:hover .mserv-info b{color:var(--acc)}
:is(#panel-serv, #panel-ficha) a.mserv-proy:hover .mserv-info b::after{opacity:1;transform:none}

/* el servicio pendiente: mismo sitio, un punto mas apagado */
#panel-serv .mserv-serv .mserv-info b{color:var(--tx-mid)}
#panel-serv .mserv-serv{cursor:default}

@media (max-width:1180px){
  :is(#panel-serv, #panel-ficha) .mserv-proys{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* Altura y espacios compartidos. Los paneles de cada menú ocupan la
   misma celda para que cambiar de categoría no mueva la lista. */
:is(#panel-serv, #panel-ficha) .mserv-caja{
  height:auto;
  /* 42vh dejaba 433px y se sentia apretado; 100vh era la pantalla
     entera, que es de donde veniamos. 58vh cae en medio: en una
     ventana de 945 da ~548 y todavia deja ver la pagina debajo. */
  /* Ni mas alto que la pantalla que queda bajo las barras: el panel
     flota, y lo que se sale por abajo no se alcanza con el scroll.
     El minimo se somete al mismo tope, porque en una ventana muy baja
     380px ya son mas de lo que hay. Pasado el tope manda el
     overflow-y de la lista. */
  min-height:min(clamp(380px,58vh,640px), calc(100vh - var(--alto-barras, 116px)));
  max-height:calc(100vh - var(--alto-barras, 116px));
  padding-top:clamp(18px,2.2vh,30px);
  padding-bottom:clamp(22px,2.8vh,38px);
}

#panel-serv .mserv-detalle{display:grid}
#panel-serv .mserv-panel-cat,
#panel-serv .mserv-vacio{grid-area:1 / 1;align-self:start}
/* apagado a la vista, pero sigue ocupando su sitio y midiendo */
#panel-serv .mserv-panel-cat[hidden]{display:block;visibility:hidden}

/* Ficha usa el mismo espaciado de categorías que Servicios. Sus listas
   de trece proyectos pueden desplazarse en ventanas de poca altura. */
#panel-ficha .mserv-cat{padding:clamp(7px,1.05vh,13px) 18px;min-height:30px}
#panel-ficha .mserv-lista li{flex:1 0 auto}
#panel-ficha .mserv-lista{overflow-y:auto}
#panel-ficha .mserv-lista ul{gap:3px}
#panel-ficha .mserv-detalle{min-height:0;overflow-y:auto;overscroll-behavior:contain}

/* ── Página de servicios ───────────────────────────────────────────────
   La misma lista del desplegable, pero aquí se lee en vez de mirarse de
   paso: cabe la descripción entera y el grupo se anuncia con su propio
   encabezado. Tres columnas, como en el desplegable, por coherencia.  */
.srv-indice{
  display:flex;flex-wrap:wrap;gap:6px;
  margin-top:calc(var(--u)*1.2);
  padding-bottom:calc(var(--u)*.6);
  border-bottom:1px solid var(--line);
}
.srv-indice a{
  font-size:var(--caption);font-weight:600;
  color:var(--tx-dim);
  padding:7px 13px;border-radius:8px;
  transition:color .18s ease, background .18s ease;
}
.srv-indice a:hover{color:var(--tx);background:var(--bg-alt)}
/* el grupo al que se acaba de saltar */
.srv-grupo:target .bloque-cab h2{color:var(--acc)}

.srv-grupo{
  padding-top:calc(var(--u)*2.2);
  /* el ancla no queda bajo la barra fija al saltar */
  scroll-margin-top:calc(var(--isla) + 24px);
}

.srv-rejilla{
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(16px,2vh,26px) clamp(24px,3vw,54px);
}

.srv-item{
  display:block;
  padding-left:14px;
  border-left:2px solid var(--line);
  /* el estilo base de <a> subraya; aqui el enlace es la tarjeta entera
     y el subrayado ensucia tres lineas seguidas */
  text-decoration:none;
  color:inherit;
}
.srv-indice a{text-decoration:none}
.srv-item b{
  display:block;
  font-size:var(--body-read);font-weight:600;
  line-height:1.35;color:var(--tx-mid);
  margin-bottom:5px;
  transition:color .18s ease;
}
.srv-item span{
  display:block;
  font-size:12.5px;line-height:1.55;color:var(--tx-dim);
}

/* Un grupo con proyecto detrás vale más que uno sin él: el que lleva a
   algo se ve, el que no, acompaña. */
.srv-item--proy{border-left-color:var(--acc)}
.srv-item--proy b{color:var(--tx)}
.srv-item--proy:hover b{color:var(--acc)}

.srv-ver{
  display:inline-flex !important;align-items:center;gap:5px;
  margin-top:7px;
  font-size:var(--caption);font-weight:600;
  color:var(--acc) !important;
  opacity:0;transform:translateX(-4px);
  transition:opacity .18s ease, transform .18s ease;
}
.srv-item--proy:hover .srv-ver,
.srv-item--proy:focus-visible .srv-ver{opacity:1;transform:none}
.srv-ver svg{width:13px;height:13px;flex:none}
.srv-ver svg path{fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round}

.srv-cierre{
  max-width:var(--lectura);
  margin-top:calc(var(--u)*3);
  padding-top:calc(var(--u)*1.2);
  border-top:1px solid var(--line);
  font-size:var(--body-read);color:var(--tx-mid);
}
.srv-cierre a{color:var(--acc);font-weight:600}
.srv-cierre a:hover{text-decoration:underline}

/* Los ultimos grupos no tenian pagina debajo para subir hasta arriba: al
   saltar a "IoT y telemetria" el navegador llegaba al final y el grupo
   se quedaba a media pantalla. El alto que falta se reserva aqui, bajo
   el cierre: puesto entre el ultimo grupo y el cierre se leia como un
   vacio, y abajo del todo se lee como el final de la pagina. */
.srv-cierre{
  padding-bottom:max(0px, calc(100vh - var(--isla) - 420px));
}

@media (max-width:1000px){
  .srv-rejilla{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:640px){
  .srv-rejilla{grid-template-columns:1fr}

  /* Once nombres largos en una fila que se parte quedan como un muro de
     texto gris de 291px antes de llegar al primer servicio: se lleva un
     tercio de la pantalla y no se lee, se salta. En una sola fila que se
     arrastra ocupa una linea y sigue sirviendo para lo unico que sirve,
     que es saltar de grupo. */
  .srv-indice{
    flex-wrap:nowrap;
    overflow-x:auto;
    scroll-snap-type:x proximity;
    scrollbar-width:none;
    padding-bottom:calc(var(--u)*.5);
  }
  .srv-indice::-webkit-scrollbar{display:none}
  .srv-indice a{
    flex:none;
    white-space:nowrap;
    scroll-snap-align:start;
    /* sin el borde la fila parece texto cortado, no una lista que corre */
    border:1px solid var(--line);
  }

  /* el titulo del grupo ya ocupa dos lineas; el contador al lado las
     estrecha mas todavia */
  .srv-grupo .bloque-cab{
    display:block;
  }
  .srv-grupo .bloque-n{
    display:block;
    margin-top:3px;
  }
}
