/* Obra360 — sistema de diseño. Escrito a mano, sin framework.
   Los tokens van en :root desde el inicio para que el modo oscuro no exija
   reescribir nada: solo se redefinen bajo [data-tema="oscuro"]. */

@font-face { font-family: 'Figtree'; src: url('fonts/figtree-latin.woff2') format('woff2');
  font-weight: 300 800; font-display: swap; unicode-range: U+0000-00FF, U+2000-206F, U+2212; }
@font-face { font-family: 'Figtree'; src: url('fonts/figtree-latin-ext.woff2') format('woff2');
  font-weight: 300 800; font-display: swap; unicode-range: U+0100-024F; }
@font-face { font-family: 'JetBrains Mono'; src: url('fonts/jbmono-latin.woff2') format('woff2');
  font-weight: 400 700; font-display: swap; unicode-range: U+0000-00FF, U+2212; }
@font-face { font-family: 'JetBrains Mono'; src: url('fonts/jbmono-latin-ext.woff2') format('woff2');
  font-weight: 400 700; font-display: swap; unicode-range: U+0100-024F; }

:root {
  /* Superficies */
  --ob-fondo:      #F7F8FA;
  --ob-superficie: #FFFFFF;
  --ob-borde:      #E3E6EC;
  --ob-texto:      #12161F;
  --ob-texto-2:    #5A6373;

  /* Semáforo. Cada estado lleva ADEMÁS un ícono o etiqueta en el marcado:
     el color solo no sirve para el 8 % de los hombres con daltonismo, y en una
     obra el porcentaje de hombres es alto. */
  --ob-verde:    #128A5A;
  --ob-amarillo: #B87A00;
  --ob-rojo:     #C4342B;
  --ob-azul:     #2A5FD6;

  /* Las variantes que LLEVAN TEXTO ENCIMA. Sobre blanco, --ob-verde da 4,37:1 y
     --ob-amarillo 3,61:1: los dos por debajo del 4,5:1 de AA. No se oscurecen los
     tokens de arriba porque también pintan el logo y las barras del Gantt, donde no
     hay texto y 4,37:1 sobra — oscurecerlos apagaría el semáforo entero para arreglar
     un toast. Estas dos van a ~5:1 y se usan sólo donde hay texto sobre el color. */
  --ob-verde-texto:    #117F53;   /* 5,02:1 sobre blanco */
  --ob-amarillo-texto: #946200;   /* 5,24:1 sobre blanco */

  /* Estados del Gantt */
  --ob-plazo:      var(--ob-verde);
  --ob-riesgo:     var(--ob-amarillo);
  --ob-atrasado:   var(--ob-rojo);
  --ob-completado: #7C8598;

  /* Tipografía */
  --ob-fuente: 'Figtree', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --ob-mono:   'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  /* Ritmo. Escala de 4 px: todo espaciado del producto es un múltiplo. */
  --ob-e1: 4px;  --ob-e2: 8px;  --ob-e3: 12px; --ob-e4: 16px;
  --ob-e6: 24px; --ob-e8: 32px; --ob-e12: 48px;

  --ob-radio: 10px;
  --ob-sombra: 0 1px 2px rgba(18,22,31,.06), 0 4px 16px rgba(18,22,31,.05);
}

:root[data-tema="oscuro"] {
  --ob-fondo:      #0E1116;
  --ob-superficie: #161B23;
  --ob-borde:      #262D38;
  --ob-texto:      #E8ECF3;
  --ob-texto-2:    #97A1B2;
  --ob-verde:      #3BC98A;
  --ob-amarillo:   #E0A32E;
  --ob-rojo:       #F2635A;
  --ob-azul:       #6E9BFF;
  /* En oscuro el semáforo se aclara, pero estas dos NO pueden seguirlo: el texto que
     llevan encima es blanco, así que tienen que quedarse oscuras. Suben apenas
     respecto del modo claro para despegarse de la superficie y siguen sobre 4,5:1
     contra el blanco de su propio texto. */
  --ob-verde-texto:    #12855C;   /* 4,63:1 sobre blanco · 4,08:1 sobre el fondo */
  --ob-amarillo-texto: #9E6900;   /* 4,69:1 sobre blanco · 4,03:1 sobre el fondo */
}

* { box-sizing: border-box; }
html { color-scheme: light dark; }
body {
  margin: 0; background: var(--ob-fondo); color: var(--ob-texto);
  font-family: var(--ob-fuente);
  /* 16px es el piso en móvil: bajo eso iOS hace zoom al enfocar un input, y en
     terreno, con guantes y a pleno sol, un texto de 14 px no se lee. */
  font-size: 16px; line-height: 1.5;
  -webkit-text-size-adjust: 100%;
}

/* Las cifras SIEMPRE en tabulares: sin esto una columna de montos alineada a la
   derecha baila de fila en fila y el tablero se ve amateur. */
.ob-cifra { font-family: var(--ob-mono); font-variant-numeric: tabular-nums; }

/* Objetivo táctil de 44 px en terreno: se usa con guantes. */
button, .ob-btn, input, select { min-height: 44px; font-size: 16px; font-family: inherit; }

:focus-visible { outline: 2px solid var(--ob-azul); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ===========================================================================
   Lo que sigue no viene del brief: es el resultado de frontend-design +
   ui-ux-pro-max aplicado a los tokens de arriba. Ver task-18-report.md para el
   razonamiento completo (paleta, tipografía, capa "Soft UI Evolution", el
   elemento firma).

   Todas las clases llevan prefijo .ob- : una clase suelta como .card puede
   chocar con una utilidad de un tercero y descuadrar el layout sin aviso.
   =========================================================================== */

*, *::before, *::after { margin: 0; }
img, svg { display: block; max-width: 100%; }
a { color: var(--ob-azul); text-decoration: none; }
a:hover { text-decoration: underline; }
:focus:not(:focus-visible) { outline: none; }

/* --- Escala tipográfica ---------------------------------------------------
   Figtree para todo lo que se lee; JetBrains Mono queda reservado para cifras
   (.ob-cifra, ya definida arriba) — mezclar la mono en títulos le quita el
   calor humano que Figtree le da al portal. */
h1, h2, h3, h4 { font-weight: 700; letter-spacing: -.02em; line-height: 1.16; }
h1 { font-size: clamp(1.6rem, 1.2rem + 1.6vw, 2.1rem); }
h2 { font-size: clamp(1.2rem, 1rem + .8vw, 1.5rem); letter-spacing: -.015em; }
h3 { font-size: 1.05rem; font-weight: 600; }

.ob-eyebrow {
  font-family: var(--ob-mono); font-size: .72rem; font-weight: 500;
  letter-spacing: .12em; text-transform: uppercase; color: var(--ob-texto-2);
}
.ob-bajada { color: var(--ob-texto-2); font-size: 1rem; max-width: 60ch; }
.ob-fina { font-size: .85rem; color: var(--ob-texto-2); }

/* --- Estructura ------------------------------------------------------------ */
.ob-shell { min-height: 100vh; display: flex; flex-direction: column; }
.ob-ancho { width: 100%; max-width: 1120px; margin-inline: auto; padding-inline: var(--ob-e6); }
.ob-ancho-full { max-width: 1440px; }
.ob-main { flex: 1; padding-block: var(--ob-e8) var(--ob-e12); }

/* Barra superior: fija, con un leve desenfoque — dashboard, no folleto. */
.ob-top {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--ob-superficie) 88%, transparent);
  backdrop-filter: saturate(160%) blur(12px);
  -webkit-backdrop-filter: saturate(160%) blur(12px);
  border-bottom: 1px solid var(--ob-borde);
}
.ob-top-in { display: flex; align-items: center; gap: var(--ob-e4); min-height: 60px; }
.ob-marca { display: flex; align-items: center; gap: var(--ob-e2); color: var(--ob-texto); font-weight: 700; flex: none; }
.ob-marca:hover { text-decoration: none; }
.ob-marca span { font-size: 1rem; letter-spacing: -.02em; }
.ob-logo { width: 24px; height: 24px; flex: none; }
.ob-logo-grande { width: 40px; height: 40px; flex: none; }

/* min-width:0 es lo que deja que un hijo flex se achique/haga scroll en vez de
   estirar a su padre — sin esto seis enlaces no caben en 390 px y toda la
   página gana scroll horizontal, no solo la barra. */
.ob-nav {
  margin-left: auto; display: flex; align-items: center; gap: 2px;
  min-width: 0; overflow-x: auto; scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.ob-nav::-webkit-scrollbar { display: none; }
.ob-nav a {
  padding: 0 var(--ob-e3); border-radius: calc(var(--ob-radio) - 4px);
  font-size: .89rem; font-weight: 600; color: var(--ob-texto-2);
  min-height: 44px; display: inline-flex; align-items: center; flex: none;
  white-space: nowrap;
  transition: background .15s ease, color .15s ease;
}
.ob-nav a:hover { background: color-mix(in srgb, var(--ob-texto) 6%, transparent); color: var(--ob-texto); text-decoration: none; }
.ob-nav a[aria-current="page"] { color: var(--ob-texto); background: color-mix(in srgb, var(--ob-azul) 12%, transparent); }

/* Salir viaja por POST con token (ver api/logout.php), así que es un <button> dentro
   de un <form>. Hereda exactamente el aspecto de los demás enlaces del nav: para el
   usuario es un enlace más, y el método HTTP no es asunto suyo. */
.ob-nav .ob-salir { display: inline-flex; flex: none; margin: 0; }
.ob-nav .ob-salir button {
  padding: 0 var(--ob-e3); border: 0; background: none; cursor: pointer;
  border-radius: calc(var(--ob-radio) - 4px);
  font-size: .89rem; font-weight: 600; color: var(--ob-texto-2);
  min-height: 44px; display: inline-flex; align-items: center; white-space: nowrap;
  transition: background .15s ease, color .15s ease;
}
.ob-nav .ob-salir button:hover {
  background: color-mix(in srgb, var(--ob-texto) 6%, transparent); color: var(--ob-texto);
}

.ob-pie {
  border-top: 1px solid var(--ob-borde); padding-block: var(--ob-e6);
  font-size: .8rem; color: var(--ob-texto-2);
  display: flex; flex-wrap: wrap; gap: var(--ob-e3); align-items: center; justify-content: space-between;
}
.ob-pie a { color: var(--ob-texto-2); }
.ob-pie a:hover { color: var(--ob-texto); }

/* --- Tarjetas --------------------------------------------------------------
   El único lugar donde vive la sombra: úsala en superficies elevadas, nunca
   como decoración suelta. */
.ob-card {
  background: var(--ob-superficie); border: 1px solid var(--ob-borde);
  border-radius: calc(var(--ob-radio) + 4px); box-shadow: var(--ob-sombra);
}
.ob-card-p { padding: var(--ob-e6); }

/* --- Botones ---------------------------------------------------------------
   min-height 44px ya viene del bloque obligatorio; acá solo se define el
   aspecto. */
.ob-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--ob-e2);
  padding: 0 var(--ob-e6);
  border-radius: var(--ob-radio); border: 1px solid transparent;
  font-weight: 600; letter-spacing: -.005em; cursor: pointer; background: transparent;
  transition: background .15s ease, border-color .15s ease, color .15s ease,
              box-shadow .15s ease, transform .1s ease;
}
.ob-btn:hover { text-decoration: none; }
.ob-btn:active { transform: translateY(1px); }
.ob-btn:disabled { opacity: .55; cursor: not-allowed; transform: none; }

.ob-btn-primario { background: var(--ob-azul); color: #fff; box-shadow: var(--ob-sombra); }
.ob-btn-primario:hover:not(:disabled) { background: color-mix(in srgb, var(--ob-azul) 88%, #000); }
.ob-btn-secundario { background: var(--ob-superficie); color: var(--ob-texto); border-color: var(--ob-borde); }
.ob-btn-secundario:hover:not(:disabled) { background: color-mix(in srgb, var(--ob-texto) 5%, transparent); }
.ob-btn-ancho { width: 100%; }

/* --- Campos ------------------------------------------------------------- */
.ob-campo { display: block; margin-bottom: var(--ob-e4); text-align: left; }
.ob-campo label,
form > label {
  display: block; font-size: .85rem; font-weight: 600; margin-bottom: var(--ob-e2);
  color: var(--ob-texto-2);
}
input, select {
  width: 100%; padding: 11px var(--ob-e4);
  border: 1px solid var(--ob-borde); border-radius: calc(var(--ob-radio) - 2px);
  background: var(--ob-superficie); color: var(--ob-texto);
  transition: border-color .15s ease, box-shadow .15s ease;
}
input:hover, select:hover { border-color: color-mix(in srgb, var(--ob-texto) 28%, var(--ob-borde)); }
input:focus, select:focus {
  outline: none; border-color: var(--ob-azul);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ob-azul) 18%, transparent);
}
.ob-ayuda { font-size: .8rem; color: var(--ob-texto-2); margin: 5px 0 var(--ob-e4); }

.ob-msg {
  padding: var(--ob-e3) var(--ob-e4); border-radius: calc(var(--ob-radio) - 2px);
  font-size: .9rem; border: 1px solid transparent; margin-bottom: var(--ob-e4);
}
.ob-msg[hidden] { display: none; }
.ob-error {
  padding: var(--ob-e3) var(--ob-e4); border-radius: calc(var(--ob-radio) - 2px);
  font-size: .88rem; margin-top: var(--ob-e2);
  background: color-mix(in srgb, var(--ob-rojo) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--ob-rojo) 26%, transparent);
  color: var(--ob-rojo);
}
.ob-error[hidden] { display: none; }
.ob-aviso {
  padding: var(--ob-e3) var(--ob-e4); border-radius: calc(var(--ob-radio) - 2px);
  font-size: .88rem; margin-bottom: var(--ob-e4);
  background: color-mix(in srgb, var(--ob-amarillo) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--ob-amarillo) 28%, transparent);
  color: var(--ob-texto);
}

/* ===========================================================================
   Acceso — el elemento firma del sistema

   El fondo es un plano de obra: la misma cuadrícula que usa un plano
   arquitectónico, más un fragmento de carta Gantt abstracta (barras SIN
   etiquetas ni cifras — no hay que sugerir que son datos reales) en los
   colores del semáforo que después van a leerse en el Gantt, la cascada y el
   termómetro de stock de verdad. No es decoración: es el mismo lenguaje
   visual del producto, adelantado un sprint.

   El panel es intencionalmente oscuro SIEMPRE, tema claro u oscuro: es la
   portada de la marca, no una superficie de contenido — igual que la carátula
   de un libro no cambia porque el lector prefiera modo noche.
   =========================================================================== */
/* .ob-acceso vive dentro de <main class="ob-main"><div class="ob-ancho"> (los
   pone _pagina.php en TODAS las páginas): no es full-bleed de viewport, es un
   panel "afiche" acotado por el ancho del sitio. Por eso el patrón se dibuja
   con :has() centrando ese main en vez de pelear con su padding — ver más
   abajo. Todas las capas de background-image se listan de la MÁS visible
   (arriba) a la MENOS (abajo): el primer color-stop opaco tapa a los que le
   siguen, así que el barniz radial de fondo va SIEMPRE al final de la lista. */
.ob-acceso {
  --ob-acceso-fondo: #0A0F18;
  display: grid; place-items: center;
  min-height: 480px;
  padding: clamp(28px, 6vh, 64px) var(--ob-e6);
  border-radius: calc(var(--ob-radio) + 10px);
  position: relative; overflow: hidden;
  background-repeat: no-repeat, no-repeat, no-repeat, no-repeat, no-repeat, no-repeat,
                      no-repeat, repeat, repeat, no-repeat;
  background-position:
    -10% 16%, -10% 30%, -10% 44%, -10% 58%, -10% 72%, -10% 86%,
    66% 0,
    0 0, 0 0,
    0 0;
  background-size:
    40% 11px, 26% 11px, 50% 11px, 22% 11px, 34% 11px, 28% 11px,
    2px 100%,
    100% 48px, 48px 100%,
    auto;
  background-image:
    /* la carta Gantt abstracta: SIN cifras ni etiquetas — es lenguaje visual,
       no un dato inventado que alguien podría confundir con uno real */
    linear-gradient(90deg, var(--ob-completado) 0 100%),
    linear-gradient(90deg, var(--ob-verde)      0 100%),
    linear-gradient(90deg, var(--ob-azul)       0 100%),
    linear-gradient(90deg, var(--ob-amarillo)   0 100%),
    linear-gradient(90deg, var(--ob-rojo)       0 100%),
    linear-gradient(90deg, var(--ob-completado) 0 100%),
    /* el cursor "hoy" */
    repeating-linear-gradient(180deg, rgba(255,255,255,.55) 0 5px, transparent 5px 11px),
    /* la cuadrícula de plano */
    repeating-linear-gradient(180deg, rgba(255,255,255,.09) 0 1px, transparent 1px 48px),
    repeating-linear-gradient(90deg,  rgba(255,255,255,.09) 0 1px, transparent 1px 48px),
    /* el barniz — SIEMPRE último: es opaco y taparía todo lo anterior */
    radial-gradient(130% 100% at 14% 10%, #16202F 0%, var(--ob-acceso-fondo) 60%);
  animation: ob-acceso-entra .7s cubic-bezier(.22,.61,.36,1) both;
}
@keyframes ob-acceso-entra { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/* El único lugar del sitio con :has(): centra verticalmente el panel de acceso
   dentro del main compartido, sin tocar el layout de las páginas normales
   (tablero.php etc.), que siguen alineadas arriba como corresponde a un
   dashboard. Si el navegador no soporta :has() el panel simplemente queda
   arriba en vez de centrado — se sigue viendo y funcionando igual. */
.ob-main:has(.ob-acceso) { display: flex; align-items: center; }
.ob-main:has(.ob-acceso) > .ob-ancho { width: 100%; }

@media (max-width: 640px) {
  /* En el teléfono el plano se simplifica: la cuadrícula queda, las barras del
     Gantt se apagan para no competir con la tarjeta, que a ese ancho ocupa
     casi todo el panel igual. */
  .ob-acceso {
    min-height: 0;
    background-image:
      repeating-linear-gradient(180deg, rgba(255,255,255,.07) 0 1px, transparent 1px 36px),
      repeating-linear-gradient(90deg,  rgba(255,255,255,.07) 0 1px, transparent 1px 36px),
      radial-gradient(130% 100% at 14% 10%, #16202F 0%, var(--ob-acceso-fondo) 60%);
    background-repeat: repeat, repeat, no-repeat;
    background-position: 0 0, 0 0, 0 0;
    background-size: 100% 36px, 36px 100%, auto;
  }
}

.ob-acceso-caja {
  width: 100%; max-width: 400px; text-align: center;
  background: var(--ob-superficie); color: var(--ob-texto);
  border: 1px solid var(--ob-borde); border-radius: calc(var(--ob-radio) + 6px);
  box-shadow: 0 1px 2px rgba(0,0,0,.08), 0 24px 64px rgba(4,8,16,.45);
  padding: var(--ob-e8) var(--ob-e6);
  position: relative; z-index: 1;
}
.ob-acceso-caja .ob-logo-grande { margin: 0 auto var(--ob-e4); }
.ob-acceso-caja h1 { font-size: 1.5rem; letter-spacing: -.025em; }
.ob-acceso-caja .ob-bajada { margin-inline: auto; margin-top: var(--ob-e1); margin-bottom: var(--ob-e6); font-size: .92rem; }
.ob-acceso-caja form { text-align: left; margin-top: var(--ob-e2); }
.ob-acceso-caja .ob-btn { margin-top: var(--ob-e2); }
.ob-acceso-caja .ob-error { text-align: left; }

#obTotpCampo { margin-bottom: var(--ob-e4); }
#obTotpCampo input { letter-spacing: .3em; text-align: center; font-family: var(--ob-mono); }

/* --- Toast ------------------------------------------------------------- */
.ob-toast {
  position: fixed; left: 50%; bottom: var(--ob-e6); transform: translate(-50%, 14px);
  z-index: 90; padding: var(--ob-e3) var(--ob-e4); border-radius: 999px;
  background: var(--ob-texto); color: var(--ob-fondo);
  font-size: .87rem; font-weight: 500; box-shadow: var(--ob-sombra);
  opacity: 0; pointer-events: none; transition: opacity .2s ease, transform .2s ease;
  max-width: min(90vw, 480px); text-align: center;
}
.ob-toast-visible { opacity: 1; transform: translate(-50%, 0); }
.ob-toast-error { background: var(--ob-rojo); color: #fff; }
.ob-toast-ok { background: var(--ob-verde-texto); color: #fff; }

/* --- Tablero (esqueleto sprint 0; el contenido real llega en el sprint 6) - */
.ob-main > .ob-ancho > h1 { margin-bottom: var(--ob-e2); }

/* --- Páginas legales (seguridad.php, privacidad.php) ---------------------
   Sin framework de tipografía: son dos páginas de texto corrido, así que el
   ritmo vertical se define acá en vez de inventar clases nuevas por bloque. */
.ob-legal { max-width: 68ch; }
.ob-legal > .ob-bajada { margin-bottom: var(--ob-e8); }
.ob-legal h2 { margin-top: var(--ob-e8); margin-bottom: var(--ob-e3); }
.ob-legal section:first-of-type h2 { margin-top: var(--ob-e6); }
.ob-legal p { margin-bottom: var(--ob-e4); color: var(--ob-texto-2); line-height: 1.6; }
.ob-legal ul { margin: 0 0 var(--ob-e4); padding-left: var(--ob-e6); display: grid; gap: var(--ob-e2); }
.ob-legal li { color: var(--ob-texto-2); line-height: 1.6; }
.ob-legal strong { color: var(--ob-texto); }
.ob-legal .ob-nota {
  margin-top: var(--ob-e8); padding: var(--ob-e4) var(--ob-e6);
  background: color-mix(in srgb, var(--ob-azul) 6%, transparent);
  border: 1px solid color-mix(in srgb, var(--ob-azul) 20%, transparent);
  border-radius: var(--ob-radio);
}
.ob-legal .ob-nota p:last-child { margin-bottom: 0; }
