/* ═══════════════════════════════════════════════════════════════════════════
   Construempresas & Asesorías Pereira — sistema de marca compartido
   ═══════════════════════════════════════════════════════════════════════════

   DE DÓNDE SALE ESTO, y por qué ya no es una copia literal.

   Hasta septiembre de 2026 este archivo era `sitio/assets/css/sistema.css`
   copiado byte a byte por `npm run sincronizar-marca`. Ese sistema —hueso
   cálido, Instrument Serif, luego Fraunces— se canceló entero cuando se rehizo
   la web. La web nueva vive en `web/` (Astro) y NO tiene un `sistema.css`: su
   sistema está repartido en componentes, principalmente

       web/src/styles/inicio.css     tokens, tipografía, botones, curva --sal
       web/src/styles/tarjetas.css   el idioma de tarjeta: cristal, filo doble,
                                     sombra tintada de morado
       web/src/styles/vida.css       micro-interacción: entrar lento, salir rápido
       marca/tokens.css              morado y teal medidos del logo

   Copiar veinte hojas de una web de scroll cinematográfico dentro de una
   herramienta de trabajo no tendría sentido: la mitad son láminas plegadas,
   cortinas y fotogramas. Así que esto es una EXTRACCIÓN a mano de lo que las
   dos cosas comparten de verdad —color, tipografía, sombra, filo, radio,
   curva— escrita con los mismos nombres de token que ya usaba la aplicación,
   para que `app.css` siguiera funcionando sin reescribirse entero.

   LA REGLA QUE SE CONSERVA: la aplicación no inventa color ni tipografía. Todo
   sale de aquí. Si la web cambia un valor, se cambia aquí y cambian las dos.

   LO QUE NO SE TRAE DE LA WEB, a propósito: nada de animación de entrada, nada
   de revelado al desplazarse, nada de héroes ni de cortina. Aquello vende una
   vez; esto se usa ocho horas al día y a la tercera jornada cualquier gracia de
   entrada es un estorbo que se interpone entre la persona y su trabajo.
   ═══════════════════════════════════════════════════════════════════════════ */


/* ── 1 · Tokens ─────────────────────────────────────────────────────────────
   Los nombres son los de siempre —`--acento`, `--papel`, `--filete`, `--s3`—
   porque `app.css` y unas cuantas líneas de `src/index.js` los nombran. Lo que
   cambia son los valores. Renombrarlos habría obligado a tocar el marcado de
   treinta rutas para no ganar nada. */
:root{
  color-scheme:light;

  /* Superficie. Clara con sesgo lila, nunca crema cálido y nunca blanco puro
     de lienzo: el blanco se reserva para las TARJETAS, y es esa diferencia de
     dos puntos la que hace que una ficha se lea como un objeto apoyado encima
     y no como un rectángulo dibujado. */
  --fondo:#F6F4FC;          /* el lienzo de la aplicación */
  --fondo2:#EDE8F7;         /* hundido: fondo de código, celdas apagadas */
  --papel:#FBFAFE;          /* superficie intermedia */
  --papel2:#FFFFFF;         /* la tarjeta */
  --oscuro:#1B1420;         /* el fondo de escena de la web */
  --oscuro2:#241A38;

  /* Tinta. Los tres niveles están medidos sobre `--fondo`, que es el fondo más
     claro donde se apoyan, y pasan AA los tres: 14,6:1 · 6,16:1 · 5,54:1. Los
     grises del mockup original daban 3,48:1 y no se usan. */
  --tinta:#241A38;
  --suave:#5F5873;
  --tenue:#655F7C;
  --tinta-inv:#F7F4FB;
  --suave-inv:#BDB4CC;

  /* Marca. Un solo color de acento, racionado. El morado es del logo, medido
     del archivo, no elegido. El teal NO es un segundo acento: es apoyo —
     rótulos, filetes, puntos— y como texto va en su versión oscurecida, porque
     el #0D9096 pelado se queda en 3,68:1 sobre claro. */
  --acento:#771571;
  --acento-cl:#A32B9C;
  --acento-os:#5E1170;
  --acento-inv:#E9A5E4;     /* el único morado legible SOBRE oscuro: 8,4:1 */
  --apoyo:#0D9096;
  --apoyo-txt:#0A7276;      /* 5,70:1 sobre blanco */
  --apoyo-os:#066064;

  /* El degradado de marca. Es la firma del botón primario de la web y lo único
     que se trae tal cual. Se mide por su parada MÁS CLARA, no por su color
     medio: en blanco sobre #9B2FA6 da 6,27:1. */
  --deg-morado:linear-gradient(135deg,#9B2FA6 0%,#6A1270 100%);

  /* SEÑALES DE ESTADO, deliberadamente fuera de la gama de marca.
     Un estado no se puede decir con el color del acento: si «vencido» fuera
     morado, la pantalla entera —botones, enlaces, navegación— parecería estar
     avisando de algo. Por eso el rojo, el ámbar y el verde no se parecen a
     nada más de la interfaz, y por eso ninguna pastilla se apoya SOLO en el
     color: todas llevan forma y texto (ver `.app-ins` en app.css).
     Los cuatro pasan AA sobre blanco: 6,53 · 5,90 · 6,46 · 7,15. */
  --alerta:#B3261E;         /* vencido y crítico */
  --aviso:#8A5A1E;          /* por vencer */
  --ok:#1B6B4A;             /* al día */
  --quieto:#5A5470;         /* pausado, cumplido, anulado: sin urgencia */

  /* Los fondos lavados de cada señal van escritos en hexadecimal y no con
     `color-mix()` a propósito. `color-mix()` se computa en oklab y el banco de
     contraste lo lee como un color que no es: en la web produjo ocho fallos
     falsos seguidos. Un color que no se puede medir no sirve de señal. */
  --alerta-lav:#FBEDEC;  --alerta-filo:#E9B9B5;
  --aviso-lav:#FBF3E4;   --aviso-filo:#E0C38C;
  --ok-lav:#E9F5EF;      --ok-filo:#A9D2BF;
  --quieto-lav:#EFEDF5;  --quieto-filo:#CBC5D9;
  /* El lavado del teal de apoyo. Existe como TOKEN y no como hexadecimal
     suelto porque un color escrito a mano no se entera de que hay modo
     oscuro: la nota explicativa se quedaba con fondo agua y letra clara, y
     daba 1,06:1. Lo encontró el banco de contraste con el esquema oscuro
     emulado, no el ojo. */
  --apoyo-lav:#EDF7F8;   --apoyo-filo:#B7DDE0;

  /* Filos y cristal. EL FILO ES DOBLE: un anillo interior de morado muy bajo
     —el «borde de 1 px»— y una línea blanca en el canto de arriba. La segunda
     es la que hace que el objeto parezca tener grosor; con solo el anillo es un
     rectángulo con borde, con las dos es una lámina. */
  --filete:rgba(119,21,113,.16);
  --filete2:rgba(119,21,113,.10);
  --filo-doble:inset 0 0 0 1px rgba(119,21,113,.13), inset 0 1px 0 rgba(255,255,255,.95);
  --cristal:rgba(255,255,255,.72);
  --cristal-bd:rgba(255,255,255,.88);
  /* El cristal de tarjeta no es blanco plano: baja del papel hacia la lavanda
     de marca, y eso le da volumen sin dibujar nada. Las dos paradas son opacas
     para que el contraste se pueda medir sin componer capas. */
  --cristal-tarjeta:linear-gradient(158deg,#FFFFFF 0%,#FDFBFF 46%,#F7F2FD 100%);

  /* SOMBRAS TINTADAS DE MORADO, NUNCA GRISES. No es gusto: sobre un lienzo
     lila el gris es lo único de la composición que no pertenece a la gama, y
     una sombra gris debajo de una tarjeta no se lee como sombra sino como
     suciedad. Dos capas siempre: contacto corto y difusión larga. */
  --s1:0 1px 2px rgba(94,17,112,.06);
  --s2:0 1px 2px rgba(94,17,112,.06), 0 6px 14px -8px rgba(94,17,112,.26);
  --s3:0 2px 5px -3px rgba(94,17,112,.22), 0 18px 34px -22px rgba(94,17,112,.45);
  --s4:0 4px 10px -4px rgba(94,17,112,.24), 0 36px 66px -32px rgba(94,17,112,.55);

  /* Tipografía. Una sola familia. La web usa Plus Jakarta Sans para todo y lo
     que separa un titular de un dato es el PESO y el apriete, no una segunda
     fuente. En una herramienta eso además es una ventaja medible: una serif de
     display en una tabla de cincuenta filas obliga a cambiar de modo de
     lectura en cada renglón.
     Los tres nombres de token se conservan —`--display`, `--cuerpo`,
     `--util`— porque están escritos por toda la aplicación; los tres apuntan
     ahora a la misma familia. */
  --display:"Plus Jakarta Sans",system-ui,-apple-system,"Segoe UI",sans-serif;
  --cuerpo:"Plus Jakarta Sans",system-ui,-apple-system,"Segoe UI",sans-serif;
  --util:"Plus Jakarta Sans",system-ui,-apple-system,"Segoe UI",sans-serif;

  /* Escala. La de la web llega a 72 px porque tiene que sostener una portada;
     aquí el techo son 28 px. Una herramienta con titulares de 58 px gasta en
     decir dónde está uno el espacio que necesita para mostrar el trabajo. */
  --t-xxl:clamp(26px,3vw,34px);
  --t-xl:clamp(22px,2.2vw,28px);
  --t-l:clamp(19px,1.8vw,22px);
  --t-m:17px; --t-b:15.5px; --t-s:14.5px; --t-xs:13px; --t-mini:11.5px;

  /* Ritmo. Radios más cerrados que los de la web (18-34 px) porque una tarjeta
     de datos con esquinas de 26 px pierde píxeles útiles en las cuatro
     esquinas y empieza a parecerse a una tarjeta de producto. */
  --r:14px;                 /* tarjetas y paneles */
  --r-s:10px;               /* campos, botones cuadrados, notas */
  --r-g:20px;               /* la caja de ingreso, que sí es una pieza suelta */
  --gap:clamp(20px,2.4vw,30px);
  --ancho:1280px;
  --lectura:66ch;

  /* LA CURVA DE LA CASA. Era easeOutQuint y se cambió con el reloj en la mano:
     sobre 0,35 s, a los 120 ms aquella llevaba el 87,5 % del recorrido y
     arrastraba los últimos píxeles, así que el ojo veía un salto y luego nada.
     Ésta va por el 50 % en ese instante y reparte el resto: se ve MOVERSE. */
  --sal:cubic-bezier(.2,.7,.3,1);
  --sal-larga:cubic-bezier(.22,1,.36,1);
  --e-out:cubic-bezier(.2,.7,.3,1);   /* nombre viejo, misma curva */
  --e-io:cubic-bezier(.65,0,.35,1);
  /* Entrar despacio, salir rápido. Al revés la interfaz se siente pegajosa: el
     cursor ya se fue y la pieza sigue volviendo. */
  --t-entra:240ms;
  --t-sale:150ms;
}

/* ── 1-bis · Oscuro ─────────────────────────────────────────────────────────
   La web nueva es clara y no tiene modo oscuro; la aplicación sí lo tenía y se
   conserva, porque quien la usa la tiene abierta todo el día y apagar eso es
   quitarle algo que ya tenía. Es la MISMA gama —morado, teal, lila— con la
   luz al revés, no una paleta distinta.

   Sobre el fondo oscuro el morado de marca da 2,3:1 y no se puede usar para
   nada que haya que leer: ahí manda `--acento-inv`, que da 8,4:1. */
@media (prefers-color-scheme:dark){
  :root:not([data-tema="claro"]){ color-scheme:dark;
    --fondo:#15111C; --fondo2:#221B2E; --papel:#1A1524; --papel2:#211A2D;
    --oscuro:#0F0C15; --oscuro2:#1B1420;
    --tinta:#F2EDF8; --suave:#BDB4CC; --tenue:#A79DB8;
    --acento:#E9A5E4; --acento-cl:#F3C2EF; --acento-os:#C77BC1;
    --apoyo:#5FD0D6; --apoyo-txt:#69D8DE; --apoyo-os:#3FA5AB;
    --alerta:#F0958C; --aviso:#E6B972; --ok:#7FCFA6; --quieto:#B0A7C2;
    --alerta-lav:#33191C; --alerta-filo:#6B3038;
    --aviso-lav:#302314;  --aviso-filo:#63492A;
    --ok-lav:#15291F;     --ok-filo:#2F5844;
    --quieto-lav:#241E30; --quieto-filo:#463C59;
    --apoyo-lav:#12262B;  --apoyo-filo:#2C525A;
    --filete:rgba(233,165,228,.22); --filete2:rgba(233,165,228,.13);
    --filo-doble:inset 0 0 0 1px rgba(233,165,228,.15), inset 0 1px 0 rgba(255,255,255,.06);
    --cristal:rgba(33,26,45,.78); --cristal-bd:rgba(33,26,45,.92);
    --cristal-tarjeta:linear-gradient(158deg,#241D31 0%,#211A2D 46%,#1D1728 100%);
    --deg-morado:linear-gradient(135deg,#8E2789 0%,#5E1170 100%);
    --s1:0 1px 2px rgba(0,0,0,.42);
    --s2:0 1px 2px rgba(0,0,0,.45), 0 6px 14px -8px rgba(0,0,0,.6);
    --s3:0 2px 5px -3px rgba(0,0,0,.6), 0 18px 34px -22px rgba(0,0,0,.85);
    --s4:0 4px 10px -4px rgba(0,0,0,.6), 0 36px 66px -32px rgba(0,0,0,.9);
  }
}

/* ── 2 · Base ───────────────────────────────────────────────────────────── */
*,*::before,*::after{ box-sizing:border-box }
html{ -webkit-text-size-adjust:100% }
body{
  margin:0; background:var(--fondo); color:var(--tinta);
  font-family:var(--cuerpo); font-weight:400; font-size:var(--t-b); line-height:1.58;
  -webkit-font-smoothing:antialiased;
  /* Cifras de ancho fijo en TODA la aplicación. Una columna de fechas y
     números en la que cada dígito mide distinto obliga a leer cada renglón en
     vez de barrer la columna, y esta interfaz es una columna de números. */
  font-variant-numeric:tabular-nums;
}
img,svg,video{ max-width:100%; height:auto; display:block }
a{ color:inherit; text-decoration:none }
button{ font:inherit; color:inherit; background:none; border:0; cursor:pointer }
input,select,textarea{ font:inherit; color:inherit }
h1,h2,h3,h4,h5,h6{ margin:0 }
p{ margin:0 0 1em }
p:last-child{ margin-bottom:0 }
strong,b{ font-weight:700 }

/* El foco se ve SIEMPRE y se ve igual en toda la aplicación. Es la única
   ayuda de quien navega con teclado, y en una herramienta de captura de datos
   —treinta vencimientos al día, tabulando— no es un caso raro: es el uso. */
:focus-visible{ outline:2.5px solid var(--acento); outline-offset:2px; border-radius:5px }
::selection{ background:var(--acento); color:#fff }

/* El salto al contenido lleva la tinta del LIENZO sobre el acento, no blanco.
   En claro el lienzo es casi blanco y da 9:1 sobre el morado; en oscuro el
   acento es un rosa claro y el blanco encima daba 1,91:1 — es decir, el unico
   atajo de quien navega con teclado era ilegible justo para quien lo usa. Un
   token que se invierte resuelve los dos casos con una sola declaracion. */
.salto-contenido{
  position:absolute; left:-9999px; top:0; z-index:200;
  background:var(--acento); color:var(--fondo); font-weight:700;
  padding:12px 20px; border-radius:0 0 var(--r-s) 0;
}
.salto-contenido:focus{ left:0 }
.vo{ position:absolute!important; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0 }

/* ── 3 · Tipografía ─────────────────────────────────────────────────────────
   Una sola familia, cuatro pesos y el apriete de la web (-.02 em en titular).
   El apriete es la mitad del parecido: sin él, Plus Jakarta Sans a 28 px se ve
   suelta y genérica. */
h1,h2,h3,.display{ color:var(--tinta); font-weight:700; line-height:1.14;
  letter-spacing:-.02em; text-wrap:balance }
h1,.t-xxl{ font-size:var(--t-xl) }
h2,.t-xl{ font-size:var(--t-m) }
h3,.t-l{ font-size:var(--t-s) }
h4,h5,h6{ font-weight:600; font-size:var(--t-s); line-height:1.4; letter-spacing:-.005em }

/* El rótulo de sección, con el punto teal de la web. Ahí el punto late; aquí
   está quieto: un punto que respira en una portada es señal de vida, y en una
   pantalla que se mira ocho horas es un parpadeo en el rabillo del ojo. */
.rotulo{
  display:inline-flex; align-items:center; gap:.5rem; margin:0 0 8px;
  font-size:var(--t-mini); font-weight:700; letter-spacing:.14em;
  text-transform:uppercase; color:var(--apoyo-txt);
}
.rotulo::before{ content:""; width:6px; height:6px; border-radius:50%;
  background:var(--apoyo); flex:none }
.rotulo.ac{ color:var(--acento) }
.rotulo.ac::before{ background:var(--acento) }

.bajada{ font-size:var(--t-b); line-height:1.55; color:var(--suave); max-width:62ch }
.dato{ font-variant-numeric:tabular-nums; font-weight:500; letter-spacing:0 }
.mini{ font-size:var(--t-xs); color:var(--tenue); line-height:1.5 }
.lectura{ max-width:var(--lectura) }

/* ── 4 · Botones ────────────────────────────────────────────────────────────
   Píldora, como en la web. El primario lleva el degradado de marca y su sombra
   TINTADA con el propio morado: una sombra gris debajo de un botón de color se
   ve sucia, y es el mismo motivo por el que cada icono del dock de la web
   lleva la sombra de su red. */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  font-weight:600; font-size:var(--t-s); letter-spacing:-.01em; line-height:1.2;
  padding:10px 20px; border-radius:999px; border:0; text-align:center;
  white-space:nowrap; min-height:40px;
  transition:transform var(--t-sale) var(--sal), box-shadow var(--t-sale) var(--sal),
             background-color var(--t-sale) var(--sal), color var(--t-sale) var(--sal);
}
.btn svg{ width:16px; height:16px; flex-shrink:0 }
.btn:active{ transform:translateY(1px) }

.btn--pri{ background-image:var(--deg-morado); color:#fff;
  box-shadow:0 8px 18px -10px rgba(106,18,112,.75) }
.btn--pri:hover{ box-shadow:0 12px 24px -10px rgba(106,18,112,.85); transform:translateY(-1px) }

.btn--sec{ background:var(--papel2); color:var(--tinta);
  box-shadow:var(--filo-doble), var(--s1) }
.btn--sec:hover{ color:var(--acento);
  box-shadow:inset 0 0 0 1px rgba(119,21,113,.38), inset 0 1px 0 rgba(255,255,255,.95), var(--s2);
  transform:translateY(-1px) }

.btn--fan{ background:transparent; color:var(--acento); box-shadow:inset 0 0 0 1px var(--filete) }
.btn--fan:hover{ background:var(--papel2); box-shadow:inset 0 0 0 1px var(--acento) }

/* El destructivo se nombra con la señal de estado, no con el acento: apagar
   los avisos de 750 personas no puede parecerse a «Guardar». */
.btn--mal{ background:var(--alerta); color:#fff; box-shadow:0 8px 18px -10px rgba(179,38,30,.8) }
.btn--mal:hover{ transform:translateY(-1px); box-shadow:0 12px 24px -10px rgba(179,38,30,.9) }

.btn--sm{ padding:7px 14px; font-size:var(--t-xs); min-height:34px }
.btn--g{ padding:13px 26px; font-size:var(--t-b); min-height:48px }
.btn[disabled],.btn[aria-disabled="true"]{ opacity:.45; pointer-events:none; box-shadow:none }
.acciones{ display:flex; flex-wrap:wrap; gap:10px; margin-top:18px }

/* ── 5 · El idioma de tarjeta ───────────────────────────────────────────────
   Una sola decisión para todo rectángulo de la aplicación: cristal con
   degradado, filo doble, sombra de color. Si una tarjeta necesita algo que no
   esté aquí, lo que hay que revisar es la tarjeta. */
.tarjeta{
  background-image:var(--cristal-tarjeta); border-radius:var(--r);
  padding:clamp(16px,2vw,22px); box-shadow:var(--filo-doble), var(--s1);
}
.tarjeta--plana{ background-image:none; background:var(--papel); box-shadow:var(--filo-doble) }

.cinta{
  display:inline-flex; align-items:center; gap:6px; padding:5px 12px; border-radius:999px;
  background:var(--apoyo-lav); color:var(--apoyo-os);
  font-size:var(--t-mini); font-weight:700; letter-spacing:.09em; text-transform:uppercase;
}
.sep{ height:1px; background:var(--filete2); border:0; margin:0 }

/* ── 6 · Formularios ────────────────────────────────────────────────────── */
.campo{ display:block; margin-bottom:14px }
.campo>span{ display:block; font-size:var(--t-mini); font-weight:700;
  letter-spacing:.1em; text-transform:uppercase; color:var(--tenue); margin-bottom:6px }
.campo input,.campo select,.campo textarea{
  width:100%; padding:11px 13px; background:var(--papel2); border-radius:var(--r-s);
  border:1px solid var(--filete); font-size:var(--t-b);
  transition:border-color var(--t-sale) var(--sal), box-shadow var(--t-sale) var(--sal);
}
.campo input:focus,.campo select:focus,.campo textarea:focus{ outline:none;
  border-color:var(--acento); box-shadow:0 0 0 3px rgba(119,21,113,.15) }
.campo .ayuda{ font-size:var(--t-xs); color:var(--tenue); margin-top:5px; display:block }
.campo .err{ font-size:var(--t-xs); color:var(--alerta); margin-top:5px; display:block }

/* ── 7 · Enlaces dentro de texto corrido ────────────────────────────────────
   Subrayados. Un enlace que solo se distingue por el color no existe para
   quien no distingue ese color, y aquí hay enlaces dentro de avisos que dicen
   dónde se arregla algo. */
.lectura a:not(.btn), .nota a:not(.btn), .tx a:not(.btn){
  color:var(--acento); text-decoration:underline;
  text-underline-offset:3px; text-decoration-thickness:1px;
  transition:text-decoration-thickness var(--t-sale) var(--sal);
}
.lectura a:not(.btn):hover, .nota a:not(.btn):hover,
.tx a:not(.btn):hover{ color:var(--acento-os); text-decoration-thickness:2px }

/* ── 8 · Movimiento reducido ────────────────────────────────────────────────
   Va con `!important` y gana siempre. En esta aplicación queda poco que
   apagar —no hay entradas ni revelados— así que lo que esto desactiva son las
   transiciones de hover y foco, que es justo lo que marea a quien lo pide. */
@media (prefers-reduced-motion:reduce){
  html{ scroll-behavior:auto }
  *,*::before,*::after{
    animation-duration:.001ms!important; animation-iteration-count:1!important;
    transition-duration:.001ms!important; scroll-behavior:auto!important;
  }
}
