/* ─────────────────────────────────────────────────────────────────────────
   COPIA LITERAL de obras-gestion/plugin/app-src/src/styles/base.css (20/09/2026).
   Es el sistema de diseño de la app de obras. NO se edita aquí: si hay que
   cambiar algo, se cambia allí y se vuelve a copiar, o las dos apps se separan.
   ───────────────────────────────────────────────────────────────────────── */

h1 { font-size: var(--qw-fs-2xl); font-weight: 700; line-height: var(--qw-lh-tight); }
h2 { font-size: var(--qw-fs-xl); font-weight: 600; line-height: var(--qw-lh-tight); }
h3 { font-size: var(--qw-fs-lg); font-weight: 600; line-height: var(--qw-lh-tight); }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0,0,0,0);
  white-space: nowrap;
  border: 0;
}

.qw-app {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--qw-bg);
}

/* Skip-link: invisible until keyboard-focused; lets AT users bypass header + 5 nav tabs. */
.qw-skip-link {
  position: absolute;
  top: -100px;
  left: 8px;
  z-index: var(--qw-z-overlay);
  padding: 12px 18px;
  background: var(--qw-green-deep);
  color: #fff;
  font-weight: 700;
  text-decoration: none;
  border-radius: 0 0 8px 8px;
  box-shadow: var(--qw-card-shadow);
  transition: top 150ms var(--qw-ease);
}
.qw-skip-link:focus,
.qw-skip-link:focus-visible {
  top: 0;
  outline: 2px solid #fff;
  outline-offset: -4px;
}
.qw-main {
  flex: 1;
  width: 100%;
  max-width: 720px;
  margin: 0 auto;
  padding: var(--qw-sp-4);
  /* 96px = 72px BottomNav + 24px buffer. Antes 64px era justo y la última fila
     de algunos forms quedaba pegada a la barra (audit responsive 2026-05-18). */
  padding-bottom: calc(96px + env(safe-area-inset-bottom));
}
@media (min-width: 768px) {
  .qw-main { padding: var(--qw-sp-6); }
}

/* Variante de qw-main usada en pantallas con BottomNav oculto (ej. /app/parte/*).
   El BottomNav no está, pero SÍ hay una StickyBar fija (Guardar jornada) que
   flota sobre el contenido. Hay que reservar su altura (--qw-stickybar-h,
   tokens.css) o el último campo del form (Incidencias) queda tapado por la
   barra. El valor por modo de tamaño de fuente vive SOLO en el token — no
   copiarlo aquí a mano (así se coló una vez el bug del círculo del BottomNav,
   ver el comentario de --qw-bottomnav-clear). */
.qw-main--flush {
  padding-bottom: calc(var(--qw-stickybar-h) + env(safe-area-inset-bottom));
  /* v0.87 — investigación «+ Añadir tramo»: abrir el selector de trabajadores
     (showModal) puede reposicionar el scroll de forma imprevisible en móvil
     (interacción con dvh/URL bar dinámica), y una mutación posterior del DOM
     (autoguardado, fila añadida) puede hacer que el navegador "compense" ese
     scroll (CSS Scroll Anchoring) y deje contenido interactivo bajo la
     StickyBar SIN que el usuario haya tocado la pantalla. No es un ajuste que
     queramos: aquí el scroll debe moverlo el usuario o nuestro propio código
     (ver el efecto de corrección en ParteForm.tsx), nunca una heurística del
     navegador reaccionando a un cambio de layout que no le pedimos. */
  overflow-anchor: none;
}

/* v0.87 — cualquier control interactivo de una pantalla `flush` (sin BottomNav,
   con StickyBar fija) debe dejar el alto de la barra como margen si algo lo
   trae a la vista con scrollIntoView (nuestro `revealHiddenBehindStickyBar` en
   ParteForm.tsx, o el propio navegador al restaurar foco). Centralizado aquí en
   vez de repetirlo control a control: cualquier botón/enlace/campo nuevo que se
   añada a una pantalla flush queda protegido sin tener que acordarse de nada. */
.qw-main--flush button,
.qw-main--flush a,
.qw-main--flush input,
.qw-main--flush select,
.qw-main--flush textarea {
  scroll-margin-bottom: var(--qw-stickybar-h);
}

/* Sin flechas de incremento en inputs numéricos. En obra (móvil + guantes) las
   spinners son diminutas, fáciles de pulsar sin querer y estorban al teclear el
   valor exacto. Los campos de COSTE usan DecimalInput (type=text, admite coma y
   decimales); esto cubre los type=number que quedan (p. ej. días de calendario). */
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
input[type="number"] {
  -moz-appearance: textfield;
  appearance: textfield;
}

/* ============================================================================
   1.10.3 — REGLA DE LA CASA PARA CAMPOS (Camilo, 15/09): sin borde, blancos y con la
   sombra negra difuminada. Vale para inputs de texto/fecha/número/búsqueda, textareas y
   selects de TODA la app, estén donde estén (20 módulos pintaban su propio borde con una
   clase, por eso va con !important: es la única forma de que una regla global gane a una
   clase sin tocar 20 hojas). Casillas, radios, rangos y ficheros quedan fuera. El foco es un
   anillo celeste sumado a la sombra; el error, un anillo rojo por dentro; el deshabilitado,
   sin sombra (no invita a pulsar).
   ============================================================================ */
.qw-app :is(
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="color"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="image"]),
  textarea,
  select
) {
  border-color: transparent !important;
  background-color: var(--qw-surface) !important;
  box-shadow: var(--qw-card-shadow) !important;
}
.qw-app :is(input, textarea, select):focus-visible {
  outline: none !important;
  box-shadow: var(--qw-card-shadow), 0 0 0 3px var(--qw-celeste-soft) !important;
}
.qw-app :is(input, textarea, select)[aria-invalid="true"] {
  box-shadow: var(--qw-card-shadow), inset 0 0 0 2px var(--qw-danger) !important;
}
.qw-app :is(input, textarea, select):disabled {
  box-shadow: none !important;
  background-color: var(--qw-surface-elev) !important;
  opacity: 0.7;
}
