/* ══════════════════════════════════════════════════════════════════════════════════════════════
   CAPA VISUAL DEL CIRCUITO DEL OPERARIO — bloques 02 y 03 del rediseño aprobado (05/09/2026)

   QUÉ ES. La segunda hoja de la base visual. La primera (`public/base-visual.css`) cubre las
   pantallas de cuenta y el CRM y tiene PROHIBIDO nombrar el circuito del operario. Esta cubre
   EXACTAMENTE lo que aquella no puede: `#screen-services`, `#screen-detail` y `#screen-done`.

   POR QUÉ EN UN ARCHIVO APARTE. Porque el contrato de alcance mide por hoja: cada una declara sus
   raíces autorizadas y ninguna puede pintar fuera de ellas. Dos hojas con dos listas de raíces
   disjuntas dicen, ejecutando, «la capa del CRM sigue sin tocar al operario» — que es la garantía
   que existía antes de este cambio y que NO se pierde al ampliar el alcance.

   TODO cuelga de `html[data-base-visual='on']`: el mismo interruptor, sin uno nuevo. Con
   `?base-visual=0` el operario vuelve a la interfaz anterior en el acto.

   LO QUE ESTA HOJA NO HACE, A PROPÓSITO: no cambia una sola regla de negocio, ni un permiso, ni
   una escritura. Es CSS. No esconde, no apaga y no vuelve inalcanzable ningún control de fotos ni
   de la cola sin conexión — eso está medido en tests/operario-visual.test.mjs (hermético) y en
   tests/operario-visual-navegador.mjs (navegador real, prueba de golpe sobre cada control).
   ══════════════════════════════════════════════════════════════════════════════════════════════ */

/* ── TOKENS ────────────────────────────────────────────────────────────────────────────────────
   La ÚNICA regla de esta hoja sin raíz de superficie, y solo declara variables (no pinta).
   Prefijo propio `--bvo-` para no chocar con los `--bv-` de la hoja del CRM.

   Los colores de estado salen de una medición, no del gusto: el chip «Completado» estaba a
   1,78:1 sobre la tarjeta (medido con tests/_lib-contraste.mjs) y el ítem tildado del checklist a
   1,92:1. Los pares nuevos están calculados contra el fondo REAL de cada uno y se verifican en el
   contrato; acá se escriben una sola vez. */
html[data-base-visual='on'] {
  /* espina de estado: franja de color al costado de cada tarjeta. Es señal NO textual, así que el
     piso que le corresponde es el de contraste no-texto (3:1) contra la tarjeta (--card #f4f8f6). */
  --bvo-espina: 3px;
  --bvo-espina-pendiente: #6b8279; /* 3,85:1 */
  --bvo-espina-asignado: #0b5ea8; /* 6,16:1 */
  --bvo-espina-curso: #6d28d9; /* 6,63:1 */
  --bvo-espina-completado: #00845f; /* 4,39:1 */

  /* chips de estado: texto sobre fondo sólido (nada de rgba() encima de un fondo que puede cambiar:
     el 1,78:1 de hoy nació justo de eso). Todos por encima de 4,5:1. */
  --bvo-chip-pendiente-bg: #e6ebe9;
  --bvo-chip-pendiente-fg: #3f5b52; /* 6,16:1 */
  --bvo-chip-asignado-bg: #dceafa;
  --bvo-chip-asignado-fg: #0a5490; /* 6,41:1 */
  --bvo-chip-curso-bg: #ece4fb;
  --bvo-chip-curso-fg: #5b21b6; /* 7,30:1 */
  --bvo-chip-completado-bg: #d6f2e4;
  --bvo-chip-completado-fg: #00684a; /* 5,74:1 */

  /* checklist tildado: #00684a sobre --green-dark (#e0f7ef) = 6,08:1 (era 1,92:1) */
  --bvo-check-hecho-fg: #00684a;

  /* pisos táctiles del campo. 48 px, no 44: se toca con guantes, al sol y de pie. */
  --bvo-toque: 48px;

  /* El piso de las dos acciones que viven DENTRO de una miniatura («borrar» y «reintentar»).
     HISTORIA, porque el número cambió dos veces: nació en 32 (por debajo del piso que esta misma
     hoja declaraba; lo marcó la revisión del 05/09), subió a 44 con un motivo escrito —«a 360 px la
     miniatura mide ~104 px y dos controles de 48 más el texto de Reintentar no entran sin
     recortarlo»— y ese motivo DEJÓ DE EXISTIR cuando «Reintentar» pasó a su propia fila (hallazgo
     B2 de la misma revisión). El frente V (05/09) lo midió en vez de suponerlo, en Chromium 148 y
     WebKit 26.4, a 360/390/428: con 48 el botón mide 48×48, «Reintentar» 84/94/107×48 SIN recorte,
     cero solape entre los dos, cero píxeles sobre la zona que abre la foto, el golpe lo recibe el
     botón, tres columnas y sin desborde. Costo: +8 px de alto por miniatura con acciones. Así que
     el segundo piso es el MISMO que el del campo: 48, guantes, sol, de pie. Lo que hace segura a
     «borrar» sigue sin ser el tamaño: es que no comparte un solo píxel con la foto, y eso se mide
     en el navegador, no se razona. */
  --bvo-toque-mini: 48px;
  --bvo-borrar: var(--bvo-toque-mini);
  --bvo-borrar-tira: 56px; /* alto de la tira de «borrar»: el control de 48 más aire */

  /* tablet: ancho de la columna de la lista en la vista partida */
  --bvo-lista-ancho: 300px;
}

/* ══ BLOQUE 02 · LISTA DE TRABAJOS DEL OPERARIO (#screen-services) ═════════════════════════════ */

/* ── Espina de estado ──────────────────────────────────────────────────────────────────────────
   El estado dejaba de leerse cuando el chip de 11 px quedaba lejos del pulgar o el sol pegaba en la
   pantalla. La espina lo dice con una franja de 3 px del alto entero de la tarjeta: se ve de reojo.
   Se pinta con ::before para NO pelearse con `.service-card.urgente`, que ya usa border-left. */
html[data-base-visual='on'] #screen-services .service-card {
  padding-left: 15px; /* 12 del original + los 3 de la espina */
  overflow: hidden; /* la espina sigue el radio de la tarjeta */
  min-height: var(--bvo-toque); /* la tarjeta ENTERA es el control que abre el trabajo */
}
html[data-base-visual='on'] #screen-services .service-card::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: var(--bvo-espina);
  background: var(--bvo-espina-pendiente);
}
html[data-base-visual='on'] #screen-services .service-card:has(.estado-asignado)::before {
  background: var(--bvo-espina-asignado);
}
html[data-base-visual='on'] #screen-services .service-card:has(.estado-en-curso)::before {
  background: var(--bvo-espina-curso);
}
html[data-base-visual='on'] #screen-services .service-card:has(.estado-completado)::before {
  background: var(--bvo-espina-completado);
}
/* `.service-card.urgente` conserva su franja ámbar (`border-left: 3px` de styles.css) y se ven las
   DOS: el ::before se posiciona contra la caja de relleno, así que la espina queda a la derecha del
   borde ámbar sin que haya que correrla. Acá vivía una regla `left: 0` que repetía lo que ya declara
   la general y un comentario que decía que la corría: no hacía nada. La sacó la revisión del 05/09. */

/* ── Contraste de los chips de estado ──────────────────────────────────────────────────────────
   Fondo sólido + texto oscuro. El emoji del propio texto («✅ Completado») sigue siendo la señal
   que no depende del color. */
html[data-base-visual='on'] #screen-services .service-estado {
  padding: 4px 10px;
  background: var(--bvo-chip-pendiente-bg);
  color: var(--bvo-chip-pendiente-fg);
}
html[data-base-visual='on'] #screen-services .service-estado.estado-asignado {
  background: var(--bvo-chip-asignado-bg);
  color: var(--bvo-chip-asignado-fg);
}
html[data-base-visual='on'] #screen-services .service-estado.estado-en-curso {
  background: var(--bvo-chip-curso-bg);
  color: var(--bvo-chip-curso-fg);
}
html[data-base-visual='on'] #screen-services .service-estado.estado-completado {
  background: var(--bvo-chip-completado-bg);
  color: var(--bvo-chip-completado-fg);
}

/* Los botones del encabezado (📦 Pedir, 💸 Gastos, ⋯) se tocan con el dedo en la camioneta. */
html[data-base-visual='on'] #screen-services .header button,
html[data-base-visual='on'] #screen-services .header .header-user {
  min-height: var(--bvo-toque);
  min-width: var(--bvo-toque);
}

/* ── Tablet: lista a la izquierda, trabajo elegido a la derecha ────────────────────────────────
   Sin abrir y cerrar pantallas. El operario planifica en la camioneta: mira la lista del día y el
   trabajo abierto al mismo tiempo.

   Cómo, sin tocar una línea de JS: `showScreen()` sigue haciendo exactamente lo de siempre (saca
   .active de una pantalla y se la pone a otra). Cuando la que quedó activa es la ficha
   (#screen-detail) o el cierre (#screen-done), esta regla vuelve a MOSTRAR la lista y acomoda las
   dos en columnas fijas. No hay una segunda rama de render ni un estado nuevo que mantener. */
@media (min-width: 768px) {
  html[data-base-visual='on'] body:has(#screen-detail.active),
  html[data-base-visual='on'] body:has(#screen-done.active) {
    max-width: none;
  }

  html[data-base-visual='on'] body:has(#screen-detail.active) #screen-services,
  html[data-base-visual='on'] body:has(#screen-done.active) #screen-services {
    display: flex;
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    width: var(--bvo-lista-ancho);
    height: auto;
    border-right: 1px solid var(--border);
    background: var(--bg);
    z-index: 2;
  }

  html[data-base-visual='on'] body:has(#screen-detail.active) #screen-detail,
  html[data-base-visual='on'] body:has(#screen-done.active) #screen-done {
    position: fixed;
    top: 0;
    bottom: 0;
    left: var(--bvo-lista-ancho);
    right: 0;
    width: auto;
    height: auto;
    z-index: 2;
  }

  /* La barra de acciones deja de estar clavada al centro de la ventana y se centra en el panel
     derecho, que es donde está el trabajo. Sin esto quedaba pisando la lista.
     El `#screen-detail` del medio NO es decorativo: la barra vive dentro de esa pantalla y el
     selector tiene que decirlo. Sin él, la regla nombraba una raíz y apuntaba a cualquier
     `.bottom-bar` del documento — el agujero M3 que encontró la revisión del 05/09. */
  html[data-base-visual='on'] body:has(#screen-detail.active) #screen-detail .bottom-bar {
    left: var(--bvo-lista-ancho);
    right: 0;
    width: auto;
    max-width: none;
    transform: none;
    padding-left: 24px;
    padding-right: 24px;
  }
}

@media (min-width: 1024px) {
  html[data-base-visual='on'] body:has(#screen-detail.active),
  html[data-base-visual='on'] body:has(#screen-done.active) {
    --bvo-lista-ancho: 360px;
  }
}

/* ══ BLOQUE 03 · CHECKLIST CON FOTOS (#screen-detail) ══════════════════════════════════════════ */

/* ── Pasos: cuadrados de 48 px ─────────────────────────────────────────────────────────────────
   Eran círculos de 28 px: por debajo de cualquier piso táctil y sin sitio para el número. Con 10
   pasos la barra no entra en un teléfono, así que scrollea de costado (ya lo hacía) y ahora lo
   AVISA con una pista de degradado en el borde. Que cada paso se pueda alcanzar deslizando está
   medido en el contrato de navegador. */
html[data-base-visual='on'] #screen-detail .step-nav {
  gap: 8px;
  padding: 10px 16px;
  scroll-padding-inline: 16px;
  -webkit-overflow-scrolling: touch;
}
html[data-base-visual='on'] #screen-detail .step-pill {
  width: var(--bvo-toque);
  height: var(--bvo-toque);
  min-width: var(--bvo-toque);
  min-height: var(--bvo-toque);
  border-radius: 12px;
  font-size: 0.9375rem;
  border-width: 2px;
}
/* El número del paso activo se queda en NEGRO sobre el verde de marca (9,74:1). La primera versión
   lo pasó a un verde muy oscuro «para ablandarlo» y lo bajó a 5,87:1: era el ÚNICO de los seis pares
   medidos que EMPEORABA, y ningún contrato lo frenaba porque solo se le pedía superar la norma.
   Ahora se declara acá —aunque styles.css ya diga lo mismo— para que el contrato lo mida y para que
   un cambio en la hoja vieja no lo baje sin que nadie se entere. (M4, revisión del 05/09.) */
html[data-base-visual='on'] #screen-detail .step-pill.active {
  color: #000000;
  font-weight: 800;
  box-shadow: inset 0 0 0 2px var(--bg);
}

/* ── Checklist: el ítem tildado se lee ─────────────────────────────────────────────────────────
   Estaba a 1,92:1 (verde marca sobre verde clarito). El tachado se conserva: es la señal que no
   depende del color. La casilla sube a 28 px y la fila entera al piso táctil de campo. */
html[data-base-visual='on'] #screen-detail .check-item {
  min-height: var(--bvo-toque);
  align-items: center;
  padding: 8px 12px;
  margin-bottom: 6px;
}
html[data-base-visual='on'] #screen-detail .checkbox {
  width: 28px;
  height: 28px;
  font-size: 1rem;
  margin-top: 0;
}
html[data-base-visual='on'] #screen-detail .check-item.checked .checkbox {
  background: var(--bvo-check-hecho-fg);
  border-color: var(--bvo-check-hecho-fg);
  color: #ffffff;
}
html[data-base-visual='on'] #screen-detail .check-label {
  font-size: 0.875rem;
}
html[data-base-visual='on'] #screen-detail .check-item.checked .check-label {
  color: var(--bvo-check-hecho-fg);
}

/* ── Fotos: borrar deja de estar pegado a lo que abre la foto ──────────────────────────────────
   Antes: botón de 22×22 apoyado ENCIMA de la miniatura, a 4 px del borde. La miniatura abre el
   visor; el botón borra. Dos acciones muy distintas a un dedo de distancia, en una pantalla que se
   usa con guantes.

   Ahora la miniatura tiene TRES filas: la foto arriba (sigue abriendo el visor), una tira de 56 px
   con «Borrar» —48 px, el mismo piso que el resto del campo— y, abajo, la fila propia de
   «Reintentar». Ninguna de las dos acciones comparte un solo píxel con la zona que abre la foto.
   (Los números de este comentario decían 40 px y 32 px: venían de main y quedaron viejos dos veces.
   Los corrigió la revisión del PR #388, H-10 — en un repo donde el doc desactualizado se paga caro.)

   Cuidado ya cometido y evitado: la capa de error (.photo-overlay) usa inset:0 y taparía la tira,
   dejando una foto fallada IMPOSIBLE de borrar. Se la acota a la zona de la foto, y el botón de
   reintentar se sube a esa zona. Está medido en negativo (sabotaje S6). */
html[data-base-visual='on'] #screen-detail .photo-thumb {
  aspect-ratio: auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-rows: auto var(--bvo-borrar-tira);
  background: var(--card);
}
html[data-base-visual='on'] #screen-detail .photo-thumb img,
html[data-base-visual='on'] #screen-detail .photo-thumb-empty {
  grid-row: 1;
  grid-column: 1 / -1;
  width: 100%;
  height: auto;
  aspect-ratio: 1;
}
html[data-base-visual='on'] #screen-detail .photo-thumb .photo-remove {
  position: static;
  grid-row: 2;
  grid-column: 2;
  justify-self: end;
  align-self: center;
  width: var(--bvo-borrar);
  height: var(--bvo-borrar);
  margin-right: 4px;
  border-radius: 8px;
  background: var(--bg);
  color: var(--red);
  border: 1px solid var(--border2);
  font-size: 1.125rem;
  font-weight: 700;
}
/* Reintentar tiene SU PROPIA fila, debajo de la tira. Compartir la tira con «borrar» funcionaba a
   390 px y se rompía a 360: con los dos controles en 44 px la miniatura mide ~104 y «Reintentar»
   terminaba montado encima del botón de borrar. Lo cazó el contrato de navegador al agregar el
   teléfono chico (hallazgo B2 de la revisión del 05/09), no el ojo. */
html[data-base-visual='on'] #screen-detail .photo-thumb .photo-retry {
  position: static;
  grid-row: 3;
  grid-column: 1 / -1;
  align-self: center;
  margin: 0 4px 4px;
  min-height: var(--bvo-toque-mini);
  border-radius: 8px;
  font-size: 0.6875rem;
  padding: 2px 6px;
}
/* La capa de estado (subiendo / error) cubre SOLO la foto: las filas de acciones quedan libres.
   Sin esto, una foto en error tendría el botón de borrar DEBAJO de la capa roja — imposible de
   tocar. Se resuelve por COLOCACIÓN, no restándole píxeles: la capa se mete en la misma celda de
   la grilla que la foto (fila 1) y se apila encima por orden de documento. Así no hay ningún número
   que se desincronice cuando cambie el alto de la tira. */
html[data-base-visual='on'] #screen-detail .photo-thumb .photo-overlay {
  position: static;
  grid-row: 1;
  grid-column: 1 / -1;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}

/* Los botones de sacar/elegir foto y la fila de acciones inferior: piso táctil de campo. */
html[data-base-visual='on'] #screen-detail .photo-add-btn {
  min-height: var(--bvo-toque);
}
html[data-base-visual='on'] #screen-detail .btn-main,
html[data-base-visual='on'] #screen-detail .btn-secondary,
html[data-base-visual='on'] #screen-detail .back-btn {
  min-height: var(--bvo-toque);
}
html[data-base-visual='on'] #screen-detail .sector-row,
html[data-base-visual='on'] #screen-detail .photo-ref-thumb {
  min-height: var(--bvo-toque);
}
/* El botón de «cancelar inicio» del banner: la revisión del 05/09 lo encontró sin piso porque la
   vista previa no dibujaba el banner y la regla no existía. Ahora el banner está en la fixture y
   este botón se mide en pantalla como cualquier otro. */
html[data-base-visual='on'] #screen-detail .cancelar-inicio-banner button {
  min-height: var(--bvo-toque);
}

/* ── Tablet: 4 columnas de fotos y la lista de ítems conviviendo con ellas ─────────────────────
   A 390 px la grilla sigue en 3 columnas: el móvil NO cambia (medido en el contrato).

   Los cortes están puestos sobre el ANCHO DEL PANEL, no sobre el de la ventana, porque en tablet
   el panel derecho mide `ventana − lista`. Con la lista en 300 px, a 768 px de ventana el panel
   mide 468: alcanza para 4 columnas de ~105 px (hoy, en el teléfono, cada miniatura mide ~113).
   La segunda columna del uploader (referencias y botones a un lado, grilla al otro) necesita ~700
   px de panel: eso ocurre desde 1060 px de ventana. Está dicho así, con el número, porque a 834 px
   en vertical NO ocurre y decirlo importa más que insinuar que sí. */
@media (min-width: 768px) {
  html[data-base-visual='on'] #screen-detail .photo-grid {
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;
  }
  /* El checklist deja de obligar a bajar: 16 ítems en dos columnas entran de una. */
  html[data-base-visual='on'] #screen-detail .step-content {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 16px;
    align-content: start;
  }
  html[data-base-visual='on'] #screen-detail .step-content > * {
    grid-column: 1 / -1;
  }
  html[data-base-visual='on'] #screen-detail .step-content > .check-item {
    grid-column: span 1;
  }
}

@media (min-width: 1060px) {
  /* Panel ancho: las referencias, los botones y el contador quedan a la izquierda y la grilla de
     fotos ocupa la columna derecha. El operario ve la lista de tomas a replicar Y las fotos que
     ya sacó, sin bajar. */
  html[data-base-visual='on'] #screen-detail .photo-uploader {
    display: grid;
    grid-template-columns: minmax(220px, 300px) minmax(0, 1fr);
    gap: 12px 20px;
    align-items: start;
  }
  html[data-base-visual='on'] #screen-detail .photo-uploader > * {
    grid-column: 1;
  }
  html[data-base-visual='on'] #screen-detail .photo-uploader > .photo-grid {
    grid-column: 2;
    grid-row: 1 / span 30;
    margin-top: 0;
  }
  html[data-base-visual='on'] #screen-detail .step-content {
    max-width: 1040px;
  }
}

/* ══ EL UPLOADER DEL OVERLAY DE SECTORES (#sector-overlay) — alcance PARCIAL, declarado ═══════
   El overlay de sectores sigue SIN migrar (se valida en el campo, de a uno). Pero su uploader es el
   MISMO markup que el del paso de fotos (renderSectorPhotoUploader, src/fotos.js) y conservaba el
   botón de borrar de 22 px apoyado encima de la miniatura: un servicio con sectores mostraba dos
   estilos de miniatura, y el dueño autorizó subirlo al piso «si es CSS puro». Entra SOLO el uploader
   (`.photo-grid` / `.photo-thumb`): está escrito en `parciales` del registro
   (tests/_lib-hojas-capa.mjs) y el contrato de alcance rechaza cualquier regla que toque otra cosa
   del overlay. Las reglas son las MISMAS del bloque 03, con el otro ancla; un contrato hermético
   exige que no se separen (misma geometría, mismos tokens). Sin @media: el overlay no tiene vista
   partida ni 4 columnas — no es parte del diseño aprobado. */
html[data-base-visual='on'] #sector-overlay .photo-thumb {
  aspect-ratio: auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-rows: auto var(--bvo-borrar-tira);
  background: var(--card);
}
html[data-base-visual='on'] #sector-overlay .photo-thumb img,
html[data-base-visual='on'] #sector-overlay .photo-thumb .photo-thumb-empty {
  grid-row: 1;
  grid-column: 1 / -1;
  width: 100%;
  height: auto;
  aspect-ratio: 1;
}
html[data-base-visual='on'] #sector-overlay .photo-thumb .photo-remove {
  position: static;
  grid-row: 2;
  grid-column: 2;
  justify-self: end;
  align-self: center;
  width: var(--bvo-borrar);
  height: var(--bvo-borrar);
  margin-right: 4px;
  border-radius: 8px;
  background: var(--bg);
  color: var(--red);
  border: 1px solid var(--border2);
  font-size: 1.125rem;
  font-weight: 700;
}
html[data-base-visual='on'] #sector-overlay .photo-thumb .photo-retry {
  position: static;
  grid-row: 3;
  grid-column: 1 / -1;
  align-self: center;
  margin: 0 4px 4px;
  min-height: var(--bvo-toque-mini);
  border-radius: 8px;
  font-size: 0.6875rem;
  padding: 2px 6px;
}
html[data-base-visual='on'] #sector-overlay .photo-thumb .photo-overlay {
  position: static;
  grid-row: 1;
  grid-column: 1 / -1;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}

/* ══ CIERRE (#screen-done) ═════════════════════════════════════════════════════════════════════ */
html[data-base-visual='on'] #screen-done .btn-main {
  min-height: var(--bvo-toque);
}

/* ══ MOVIMIENTO REDUCIDO ══════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
  html[data-base-visual='on'] #screen-detail .step-pill,
  html[data-base-visual='on'] #screen-detail .check-item,
  html[data-base-visual='on'] #screen-services .service-card {
    transition: none;
  }
}
